Skip to content

feat(whatsapp): proxy support for the Baileys bridge - #12787

Closed
d0uub wants to merge 1 commit into
NousResearch:mainfrom
d0uub:feat/whatsapp-proxy
Closed

feat(whatsapp): proxy support for the Baileys bridge#12787
d0uub wants to merge 1 commit into
NousResearch:mainfrom
d0uub:feat/whatsapp-proxy

Conversation

@d0uub

@d0uub d0uub commented Apr 20, 2026

Copy link
Copy Markdown

Adds optional outbound HTTP/HTTPS proxy support to the WhatsApp bridge so users behind a corporate proxy can still establish the WebSocket and HTTP traffic Baileys needs.

Behaviour:

  • If WHATSAPP_PROXY (preferred) or HTTPS_PROXY / HTTP_PROXY is set in the environment, the bridge:
    • routes the makeWASocket WebSocket through HttpsProxyAgent (passed as agent)
    • routes Baileys' fetch-based traffic through the same proxy via fetchAgent and undici's setGlobalDispatcher.
  • If no proxy env var is set, behaviour is unchanged from upstream.
  • Proxy URL is logged with the password masked (//user:***@).
  • fetchLatestBaileysVersion() is wrapped in try/catch with a hard-coded fallback version, since that endpoint is frequently blocked by corporate proxies and would otherwise abort startup.

Dependencies added:

  • https-proxy-agent ^7.0.5 (WebSocket proxy)
  • undici ^6.21.0 (fetch dispatcher)

Both are imported lazily so they're only loaded when a proxy URL is configured.

What does this PR do?

The Baileys-based WhatsApp bridge currently has no way to honour an outbound HTTP/HTTPS proxy, which means it cannot connect from any environment that forces all egress through one (corporate networks, locked-down VMs, some cloud egress policies, etc.). This PR makes the bridge proxy-aware in a fully opt-in way: if WHATSAPP_PROXY / HTTPS_PROXY / HTTP_PROXY is present, the WebSocket and Baileys' internal fetch traffic both route through it; otherwise behaviour is byte-for-byte identical to before.

The implementation uses the two community-standard libraries for this — https-proxy-agent for the underlying socket and undici's ProxyAgent for fetch — both lazy-imported so users without a proxy never load them. It also defends against a related failure mode: fetchLatestBaileysVersion() is the very first network call the bridge makes and is frequently blocked by the same proxies, so it's now wrapped in try/catch with a known-good fallback version, preventing the bridge from failing to even start.

Related Issue

Fixes # (no existing issue — happy to file one if maintainers prefer)

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • scripts/whatsapp-bridge/bridge.js — added a proxy-detection block at the top of the file that reads WHATSAPP_PROXY / HTTPS_PROXY / HTTP_PROXY, dynamically imports https-proxy-agent and undici, calls setGlobalDispatcher(new ProxyAgent(PROXY_URL)), and exposes the constructed agent for makeWASocket. Also wrapped fetchLatestBaileysVersion() in try/catch with a hard-coded fallback version [2, 3000, 1023223821] so a blocked version-fetch no longer kills startup. The proxy URL is masked (//user:***@) before being logged.
  • scripts/whatsapp-bridge/package.json — added https-proxy-agent ^7.0.5 and undici ^6.21.0 to dependencies.
  • scripts/whatsapp-bridge/package-lock.json — regenerated to include the new transitive deps.

How to Test

Without a proxy (regression check — should be identical to upstream):

  1. cd scripts/whatsapp-bridge && npm install
  2. node bridge.js — bridge starts, scans QR, connects normally. No [bridge] using proxy line appears in the log.

With a proxy:

  1. cd scripts/whatsapp-bridge && npm install
  2. WHATSAPP_PROXY=http://user:pass@proxy.corp.example:8080 node bridge.js (or use HTTPS_PROXY=… for the same effect).
  3. Confirm the bridge prints [bridge] using proxy http://user:***@proxy.corp.example:8080 (password masked).
  4. Scan QR / pair as normal — both the wss:// socket and Baileys' fetch calls (e.g. profile pic uploads) flow through the proxy.
  5. Optionally point the proxy at something that blocks web.whatsapp.com/check-update to confirm the fetchLatestBaileysVersion fallback kicks in ([bridge] fetchLatestBaileysVersion failed, using fallback).

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (feat(whatsapp): …)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass — N/A: this PR only touches the Node.js bridge, no Python code changed
  • I've added tests for my changes — no test harness exists for the WhatsApp bridge yet; happy to add one if maintainers want a recommended approach
  • I've tested on my platform: Windows 11 (Node 20), behind an authenticated corporate HTTPS proxy

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — can add a short note in docs/platforms/whatsapp.md if requested
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A (purely env-var driven, no config schema change)
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) — env-var read works identically on all OSes; tested on Windows
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A (no tool surface changed)

Screenshots / Logs

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have platform/whatsapp WhatsApp Business adapter labels Apr 23, 2026
Adds optional outbound HTTP/HTTPS proxy support to the WhatsApp
bridge so users behind a corporate proxy can still establish the
WebSocket and HTTP traffic Baileys needs.

Behaviour:
- If WHATSAPP_PROXY (preferred) or HTTPS_PROXY / HTTP_PROXY is
  set in the environment, the bridge:
    * routes the makeWASocket WebSocket through HttpsProxyAgent
      (passed as 'agent')
    * routes Baileys' fetch-based traffic through the same proxy
      via 'fetchAgent' and undici's setGlobalDispatcher.
- If no proxy env var is set, behaviour is unchanged from upstream.
- Proxy URL is logged with the password masked (//user:***@).
- fetchLatestBaileysVersion() is wrapped in try/catch with a
  hard-coded fallback version, since that endpoint is frequently
  blocked by corporate proxies and would otherwise abort startup.

Dependencies added:
- https-proxy-agent ^7.0.5 (WebSocket proxy)
- undici             ^6.21.0 (fetch dispatcher)

Both are imported lazily so they're only loaded when a proxy URL
is configured.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing a real current-main gap: scripts/whatsapp-bridge/bridge.js:389-408 still fetches the Baileys version and opens makeWASocket() without proxy options.

Problems

  • scripts/whatsapp-bridge/bridge.js:55 in this PR logs raw PROXY_URL when lazy imports fail. A proxy URL may contain user:password@host; use the masked value in this error path too.
  • The change has no proxy regression test. The existing bridge test files cover unrelated helpers and do not exercise proxy resolution or socket options.

Suggested changes

  • Redact the URL consistently in every log path, including the import-error handler.
  • Add a focused Node test for precedence, masked logging, and generated Baileys options.
  • Please align the egress direction with maintainers before salvage: linked open PR #21627 proposes direct bridge egress, while this PR enables proxy egress.

Automated hermes-sweeper review.

console.log('[bridge] Proxy enabled:', _masked);
} catch (e) {
console.error('[bridge] Failed to enable proxy (' + PROXY_URL + '):', e.message);
console.error('[bridge] Run: npm install https-proxy-agent undici');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error path logs the raw PROXY_URL, unlike the masked success log above. An import failure would therefore expose an embedded proxy password in bridge logs; log the masked value here as well.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
@d0uub d0uub closed this Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low — cosmetic, nice to have platform/whatsapp WhatsApp Business adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants