Skip to content

fix(whatsapp): read WHATSAPP_GROUP_ALLOW_FROM env var as group allowlist fallback - #56769

Open
liuhao1024 wants to merge 3 commits into
NousResearch:mainfrom
liuhao1024:liuhao/cron-bugfix-56767-whatsapp-group-env-fallback
Open

liuhao1024 wants to merge 3 commits into
NousResearch:mainfrom
liuhao1024:liuhao/cron-bugfix-56767-whatsapp-group-env-fallback

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What does this PR do?

Restores the WHATSAPP_GROUP_ALLOW_FROM / WHATSAPP_GROUP_ALLOWED_USERS env-var fallback for the group allowlist that was lost when WhatsApp migrated from a built-in adapter (gateway/platforms/whatsapp.py) to a plugin (plugins/platforms/whatsapp/adapter.py).

Without this fix, users who configure the group allowlist via .env (the standard way) have their group messages silently dropped — group_policy reports "allowlist" but the allowlist is empty.

Related Issue

Fixes #56767

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • plugins/platforms/whatsapp/adapter.py: Added os.getenv("WHATSAPP_GROUP_ALLOW_FROM") and os.getenv("WHATSAPP_GROUP_ALLOWED_USERS") as fallback sources for _group_allow_from (line 411), matching the pattern already used by _group_policy (line 410) and the setup wizard (line 1547).
  • tests/gateway/test_whatsapp_group_env_fallback.py: 6 regression tests covering env-only fallback, config precedence over env, and dual-env-var priority.

How to Test

  1. Run the new regression tests: pytest tests/gateway/test_whatsapp_group_env_fallback.py -v — all 6 should pass.
  2. Run existing group gating tests: pytest tests/gateway/test_whatsapp_group_gating.py -v — all 30 should pass.
  3. To reproduce the original bug: set WHATSAPP_GROUP_POLICY=allowlist and WHATSAPP_GROUP_ALLOW_FROM=120363001234567890@g.us in .env, remove any whatsapp: section from config.yaml, and observe that group messages are now processed (previously silently dropped).

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • 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
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15.2

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — N/A (env var reading is cross-platform)
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

…ist fallback

After the built-in → plugin migration, the group allowlist lost its env
var fallback. _group_policy reads WHATSAPP_GROUP_POLICY from env (line
410) but _group_allow_from only reads from config.extra (line 411),
causing group messages to be silently dropped when the allowlist is
configured via .env.

Add os.getenv fallback for both WHATSAPP_GROUP_ALLOW_FROM and
WHATSAPP_GROUP_ALLOWED_USERS (the name used by the setup wizard).

Fixes NousResearch#56767
@alt-glitch alt-glitch added type/bug Something isn't working platform/whatsapp WhatsApp Business adapter comp/plugins Plugin system and bundled plugins area/config Config system, migrations, profiles P3 Low — cosmetic, nice to have labels Jul 2, 2026

Copy link
Copy Markdown
Contributor

Recommendation: keep the implementation direction, but tighten the regression so it exercises the production adapter path.

The production change is the right narrow fix, and CI is green. The current new tests are weaker than they look, though: tests/gateway/test_whatsapp_group_env_fallback.py defines _init_group_allow_from() and reimplements the same config.extra ... or os.getenv(...) expression from WhatsAppAdapter.__init__. That proves the copied expression, not that WhatsAppAdapter actually wires the env fallback into _group_allow_from or that group gating now accepts the env-only allowlisted chat.

A stronger test can be small and should still stay focused:

monkeypatch.setenv("WHATSAPP_GROUP_POLICY", "allowlist")
monkeypatch.setenv("WHATSAPP_GROUP_ALLOW_FROM", "120363001234567890@g.us")
adapter = WhatsAppAdapter(PlatformConfig(enabled=True, extra={}))
assert adapter._group_allow_from == {"120363001234567890@g.us"}
assert adapter._is_group_allowed("120363001234567890@g.us") is True
assert adapter._is_group_allowed("999999999999@g.us") is False

That would cover the actual regression described in #56767: env-only group_policy=allowlist plus env-only group_allow_from should let the listed group through and keep unlisted groups blocked. I locally checked the existing focused slice on this PR: scripts/run_tests.sh tests/gateway/test_whatsapp_group_env_fallback.py tests/gateway/test_whatsapp_group_gating.py -> 36 passed. I also verified direct adapter construction with those two env vars gives _group_policy == "allowlist", _group_allow_from == {"120363001234567890@g.us"}, allowed group -> True, unlisted group -> False.

…allowlist

Address review feedback from harjothkhara: replace the
_init_group_allow_from() helper (which reimplemented the __init__
expression) with direct WhatsAppAdapter construction + monkeypatched
env vars.  This proves the adapter actually wires the env fallback
into _group_allow_from and _is_group_allowed, not just that the
expression logic is correct in isolation.

Also adds an end-to-end test that sets WHATSAPP_GROUP_POLICY=allowlist
and WHATSAPP_GROUP_ALLOW_FROM and asserts the adapter accepts listed
groups while blocking unlisted ones.
@liuhao1024

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review, @harjothkhara! Great catch — the _init_group_allow_from() helper was reimplementing the same expression rather than exercising the actual adapter path.

Pushed a fix that replaces the helper with direct WhatsAppAdapter(PlatformConfig(...)) construction + monkeypatched env vars. The tests now prove the adapter wires the env fallback into _group_allow_from and _is_group_allowed end-to-end:

  • 6 tests: env-only fallback, config-wins-over-env, env var priority, empty default — all via real constructor
  • 1 new end-to-end test: sets WHATSAPP_GROUP_POLICY=allowlist + WHATSAPP_GROUP_ALLOW_FROM and asserts _is_group_allowed accepts listed groups and blocks unlisted ones

All 7 env fallback tests + 30 existing gating tests pass.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for isolating a real WhatsApp allowlist regression. Current main still initializes the group allowlist only from config.extra at plugins/platforms/whatsapp/adapter.py:412, while the allowlist gate rejects the resulting empty set at gateway/platforms/whatsapp_common.py:242.

Problems

  • The proposed or chain treats an explicit empty group_allow_from config value as missing, then falls through to the environment. That can widen an explicitly empty allowlist; the new precedence tests cover only non-empty config values.
  • The matching DM path remains env-blind at plugins/platforms/whatsapp/adapter.py:410, even though the plugin bridge writes WHATSAPP_ALLOWED_USERS at plugins/platforms/whatsapp/adapter.py:1731-1735. Related PR #37452 identified this sibling path.

Suggested changes

  • Distinguish absent config keys from present-but-empty values for group fallback, with empty-list and empty-string regressions.
  • Apply the same safe fallback pattern to the DM allowlist and add an env-only DM intake test.

Automated hermes-sweeper review.

config.extra.get("group_allow_from")
or config.extra.get("groupAllowFrom")
or os.getenv("WHATSAPP_GROUP_ALLOW_FROM")
or os.getenv("WHATSAPP_GROUP_ALLOWED_USERS")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This truthiness chain makes an explicit group_allow_from: [] or "" fall through to the environment and can widen an allowlist from a stale env value. Select an env fallback only when neither config key is present, and add regressions for explicit empty snake_case and camelCase config values.

@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:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/plugins Plugin system and bundled plugins 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-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] WhatsApp plugin adapter does not read WHATSAPP_GROUP_ALLOW_FROM from env — group messages silently blocked

4 participants