fix(signal): add group-level allowlist support via groups config#4337
fix(signal): add group-level allowlist support via groups config#4337derekross wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Signal's groupPolicy: allowlist was checking senders against groupAllowFrom, but users expected to put group IDs there. This adds proper group-level allowlisting via channels.signal.groups.<groupId>, matching the pattern used by Telegram and iMessage. When a group is explicitly listed in the groups config, it bypasses the sender-level groupAllowFrom check, allowing all members of that group to interact with the bot. - Add SignalGroupConfig type and groups property to SignalAccountConfig - Add resolveChannelGroupPolicy check before sender-level gating - Add tests for group-level allowlist functionality - Update docs to clarify groupAllowFrom vs groups config
The TypeScript type was added but the Zod runtime schema was missing, causing config validation to reject the groups key.
|
Just to add that I've actively been using this since last night configured as such and it's been working great in my family chat. So this proof of concept fix actually does work, following the Telegram structure. |
| export const SignalGroupSchema = z | ||
| .object({ | ||
| requireMention: z.boolean().optional(), | ||
| tools: ToolPolicySchema, | ||
| toolsBySender: ToolPolicyBySenderSchema, | ||
| enabled: z.boolean().optional(), | ||
| allowFrom: z.array(z.union([z.string(), z.number()])).optional(), | ||
| systemPrompt: z.string().optional(), | ||
| }) |
There was a problem hiding this comment.
[P0] SignalGroupSchema makes tools and toolsBySender required, but SignalGroupConfig marks them optional and docs/tests use empty objects (groups: { "id": {} }). With .strict(), {} will fail validation because required keys are missing, so the new channels.signal.groups.<groupId>: {} example won’t work.
A minimal fix is to make these optional (like Telegram): tools: ToolPolicySchema.optional() and toolsBySender: ToolPolicyBySenderSchema.optional() (and keep allowFrom/enabled/etc. optional as they already are).
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/config/zod-schema.providers-core.ts
Line: 61:69
Comment:
[P0] `SignalGroupSchema` makes `tools` and `toolsBySender` required, but `SignalGroupConfig` marks them optional and docs/tests use empty objects (`groups: { "id": {} }`). With `.strict()`, `{}` will fail validation because required keys are missing, so the new `channels.signal.groups.<groupId>: {}` example won’t work.
A minimal fix is to make these optional (like Telegram): `tools: ToolPolicySchema.optional()` and `toolsBySender: ToolPolicyBySenderSchema.optional()` (and keep `allowFrom`/`enabled`/etc. optional as they already are).
How can I resolve this? If you propose a fix, please make it concise.
Additional Comments (1)
If the intent is “explicitly allowed groups bypass sender-level allowlist checks”, you may want to incorporate Prompt To Fix With AIThis is a comment left during a code review.
Path: src/signal/monitor/event-handler.ts
Line: 469:482
Comment:
[P1] Group-level allowlisting is checked for message delivery, but `commandGate` still uses `effectiveGroupAllow` (sender allowlist) and ignores `channels.signal.groups`. That means a group explicitly allowed via `groups` can send normal messages, but control commands may still be blocked (since `groupAllowedForCommands` is based on sender allowlist).
If the intent is “explicitly allowed groups bypass sender-level allowlist checks”, you may want to incorporate `groupExplicitlyAllowed` into the `authorizers`/`commandAuthorized` path (or document that `groups` only affects message delivery, not command authorization).
How can I resolve this? If you propose a fix, please make it concise. |
bfc1ccb to
f92900f
Compare
|
Closing as AI-assisted stale-fix triage. Linked issue #4336 ("Signal groupPolicy: allowlist doesn't work with group IDs in groupAllowFrom") is currently closed and was closed on 2026-02-18T04:24:23Z with state reason not_planned. If the underlying bug is still reproducible on current main, please reopen this PR (or open a new focused fix PR) and reference both #4336 and #4337 for fast re-triage. |
|
This issue still exists for Signal and you just merged a similar fix for WhatsApp #24670 |
Signal was the only channel missing group-level allowlist support. While Telegram, iMessage, WhatsApp, IRC, and BlueBubbles all use resolveChannelGroupPolicy to allow specific groups by ID, Signal only supported sender-level gating via groupAllowFrom. Changes: - Add SignalGroupConfig type with requireMention/tools/toolsBySender - Add SignalGroupSchema to Zod validation - Add groups field to SignalAccountSchemaBase - Wire resolveChannelGroupPolicy into Signal event handler - Groups explicitly allowed via config bypass sender-level checks - Incorporate groupExplicitlyAllowed into command authorization - Update docs with groups config usage and examples Fixes openclaw#25540 Supersedes openclaw#4337
Summary
Fixes #4336
channels.signal.groups.<groupId>config to allow specific Signal groups by IDgroupAllowFromcheckChanges
SignalGroupConfigtype andgroupsproperty to Signal config schemaSignalGroupSchemato Zod validationresolveChannelGroupPolicycheck in Signal event handlergroupAllowFrom(senders) vsgroups(group IDs)Usage
Testing
Greptile Overview
Greptile Summary
This PR adds a per-group allowlist for Signal via
channels.signal.groups.<groupId>, updates Signal config types/Zod schema, adds a group allowlist check in the Signal event handler, and documents the difference between sender allowlists (groupAllowFrom) vs group-ID allowlists (groups).The new behavior plugs into the shared
resolveChannelGroupPolicymechanism (already used by Telegram/iMessage/WhatsApp) so Signal can allow or block groups by ID (including"*"wildcard) before applying sender-levelgroupAllowFromgating.Confidence Score: 3/5
groups: { id: {} }), which would break the feature at runtime. Also, command authorization may not align with the new group-level allowlist semantics.(2/5) Greptile learns from your feedback when you react with thumbs up/down!
Context used:
dashboard- CLAUDE.md (source)dashboard- AGENTS.md (source)