Skip to content

fix(signal): isolate group allowlist from DM pairing-store entries#26029

Closed
bmendonca3 wants to merge 4 commits intoopenclaw:mainfrom
bmendonca3:bm/security-5th-20260225
Closed

fix(signal): isolate group allowlist from DM pairing-store entries#26029
bmendonca3 wants to merge 4 commits intoopenclaw:mainfrom
bmendonca3:bm/security-5th-20260225

Conversation

@bmendonca3
Copy link
Copy Markdown
Contributor

@bmendonca3 bmendonca3 commented Feb 25, 2026

Summary

Signal group allowlist enforcement currently mixes two trust domains:

  • explicit group sender policy (channels.signal.groupAllowFrom)
  • DM pairing-store state (readChannelAllowFromStore("signal"))

Because of that merge, a sender who is only DM-paired can bypass group allowlist gating and trigger agent execution in Signal groups where they are not explicitly allowed.

This PR isolates group allowlist checks from DM pairing-store entries.

Change Type

  • Security fix
  • Regression tests

Scope

  • src/signal/monitor/event-handler.ts
  • src/signal/monitor/event-handler.group-allowlist.test.ts

Security Impact

High. This is an AuthZ boundary bypass:

  • Expected boundary: group-trigger permission comes only from groupAllowFrom (or open group policy).
  • Actual behavior before fix: DM pairing-store entries were implicitly accepted as group sender authorization.
  • Worst case: any sender who can get DM-paired can drive agent behavior in restricted groups despite being absent from group allowlist.

Repro + Verification

Repro (before this patch):

  1. Configure Signal with groupPolicy=allowlist, groupAllowFrom excluding sender +15550001111, and dmPolicy=pairing.
  2. Ensure pairing store includes sender +15550001111 (DM paired).
  3. Send a Signal group message from +15550001111 in group g1.
  4. Observe message is dispatched (unexpected).

Deterministic local regression test:

  • pnpm exec vitest run src/signal/monitor/event-handler.group-allowlist.test.ts --maxWorkers=1
  • Fails on parent commit, passes with this patch.

Post-fix targeted verification:

  • pnpm exec vitest run src/signal/monitor/event-handler.group-allowlist.test.ts src/signal/monitor/event-handler.inbound-contract.test.ts src/signal/monitor/event-handler.mention-gating.test.ts --maxWorkers=1

Evidence

Dedupe checks against existing work:

Code-level fix evidence:

  • effectiveGroupAllow now uses only deps.groupAllowFrom.
  • Added regression test that simulates paired DM sender not in group allowlist and asserts drop.

Human Verification

  1. Start with Signal config:
    • dmPolicy: pairing
    • groupPolicy: allowlist
    • groupAllowFrom: ["+15550002222"]
  2. Pair sender +15550001111 in DM.
  3. From +15550001111, send group message into a Signal group.
  4. Confirm no dispatch/agent reply occurs.
  5. From +15550002222, send group message and confirm dispatch continues.

Compatibility / Migration

No config schema changes. Existing DM pairing behavior for direct messages is unchanged.

Failure Recovery

If unexpected regressions appear, revert this commit to restore previous behavior while preserving a clear regression test for the bypass scenario.

Risks and Mitigations

Risk:

  • Deployments that accidentally relied on DM pairing-store entries to authorize group senders will now be denied.

Mitigation:

  • Explicitly add intended group senders to channels.signal.groupAllowFrom.
  • Regression test locks expected policy separation going forward.

Greptile Summary

Fixes authorization boundary bypass in Signal group allowlist by removing DM pairing-store entries from group sender authorization. Previously, senders who were only DM-paired could bypass groupAllowFrom restrictions and trigger agent execution in Signal groups where they weren't explicitly allowed.

  • Single-line fix in src/signal/monitor/event-handler.ts:449 removes storeAllowFrom from effectiveGroupAllow
  • Regression test added that verifies DM-paired sender +15550001111 is blocked from group when only +15550002222 is in groupAllowFrom
  • Fix correctly isolates group authorization from DM pairing state while preserving DM pairing behavior

Note: Similar vulnerability pattern exists in other channels (src/security/dm-policy-shared.ts:28, Telegram, LINE) that use mergeAllowFromSources or resolveEffectiveAllowFromLists for group allowlists. Those channels may need equivalent fixes.

Confidence Score: 5/5

  • This PR is safe to merge - it's a critical security fix with minimal code change and comprehensive test coverage
  • Single-line security fix with clear before/after behavior, deterministic regression test that locks the expected behavior, and thorough PR documentation including reproduction steps and verification commands
  • No files require special attention - the fix is straightforward and well-tested

Last reviewed commit: fc34437

Copy link
Copy Markdown

@nikolasdehor nikolasdehor left a comment

Choose a reason for hiding this comment

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

Same class of fix as #25988 (Telegram) but for Signal. The one-line change from [...deps.groupAllowFrom, ...storeAllowFrom] to deps.groupAllowFrom correctly isolates the group allowlist from DM pairing-store entries, preventing paired DM users from automatically gaining group access. The test mock setup is thorough — it seeds the pairing store with the sender's number while keeping groupAllowFrom pointing to a different number, and asserts no dispatch context is created. Clean and minimal.

@openclaw-barnacle openclaw-barnacle bot added the agents Agent runtime and tooling label Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: signal Channel integration: signal size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants