Skip to content

sendPolicy not enforced on WhatsApp auto-reply delivery path #21824

@rsuk-mb

Description

@rsuk-mb

Summary

session.sendPolicy deny rules have no effect on WhatsApp auto-reply responses. The auto-reply delivery pipeline (on-message.tsprocess-message.tsdeliverWebReply) never calls resolveSendPolicy, so deny rules intended to suppress replies to specific DM sessions are silently ignored.

Related issues

All three issues stem from sendPolicy only being enforced in commands-core.ts and gateway/server-methods/agent.ts, while other outbound paths bypass it.

Reproduction

  1. Configure sendPolicy to deny WhatsApp DM replies except self-chat:
"session": {
  "sendPolicy": {
    "rules": [
      { "action": "allow", "match": { "keyPrefix": "agent:main:whatsapp:direct:+44XXXXXXXXXX" } },
      { "action": "allow", "match": { "channel": "whatsapp", "chatType": "group" } },
      { "action": "deny",  "match": { "keyPrefix": "agent:main:whatsapp:direct:" } }
    ],
    "default": "allow"
  }
}
  1. Set dmPolicy: "open" with allowFrom: ["*"] so messages are ingested
  2. Receive a DM from another WhatsApp contact
  3. Expected: message is ingested but no reply is sent (deny rule matches)
  4. Actual: assistant replies to the other contact, ignoring the deny rule

Root cause

resolveSendPolicy() is only called from:

  • src/auto-reply/reply/commands-core.ts (text command processing)
  • src/gateway/server-methods/agent.ts (gateway-mediated sends)

The WhatsApp auto-reply flow does not check it:

  • src/web/auto-reply/monitor/on-message.ts — DM branch (~line 145) has no reply gating (unlike the group branch which has applyGroupGating)
  • src/web/auto-reply/monitor/process-message.tsdeliverWebReply — no resolveSendPolicy call

Impact

Users cannot configure a "see but don't reply" mode for non-self DMs. The assistant responds to incoming DMs from other contacts even when sendPolicy explicitly denies them. The only workaround is dmPolicy: "allowlist" with empty allowFrom, which blocks messages at the inbound access-control layer entirely (no ingestion, no context).

Suggested fix

Add a resolveSendPolicy check in the DM branch of on-message.ts (or in process-message.ts before dispatching the reply). If the policy resolves to "deny", skip the reply but still allow the message to be ingested for context — mirroring how group mention-gating stores un-mentioned messages in history without replying.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions