fix(security): respect top-level restriction for Telegram group allowFrom wildcard#48804
fix(security): respect top-level restriction for Telegram group allowFrom wildcard#48804yelog wants to merge 2 commits intoopenclaw:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b7581b7e56
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| continue; | ||
| } | ||
|
|
||
| if (groupLevelWildcards.length > 0 && !hasTopLevelRestriction) { |
There was a problem hiding this comment.
Flag per-group Telegram wildcard even with top-level allowlist
This guard suppresses the new critical finding whenever hasTopLevelRestriction is true, but Telegram runtime auth does not intersect top-level groupAllowFrom with per-group/topic overrides; it replaces it (groupAllowOverride ?? groupAllowFrom in extensions/telegram/src/bot-message-context.ts and extensions/telegram/src/bot/helpers.ts). In configurations like groupAllowFrom: ["123456"] plus groups.<id>.allowFrom: ["*"], group messages are still effectively wildcard-authorized, so the audit now returns a false negative for a real command-control exposure.
Useful? React with 👍 / 👎.
Greptile SummaryThis PR fixes a false-positive security audit issue where a per-group Issues to address:
Confidence Score: 3/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/security/audit-channel.ts
Line: 816-827
Comment:
**Early `continue` suppresses invalid-entry warnings**
Moving the top-level wildcard block before `invalidTelegramAllowFromEntries` means that if a config has **both** a top-level `*` wildcard **and** other non-numeric entries (e.g., `@username` alongside `*`), those invalid entries will no longer be reported. Previously the `invalidTelegramAllowFromEntries` check ran before the `continue`, so both findings were emitted.
While the wildcard is the dominant concern, silently dropping the invalid-entry WARN could hide misconfigured allowlists that users still need to fix after removing the wildcard. Consider reporting invalid entries even in the wildcard path:
```typescript
// report invalid entries first, then bail
if (invalidTelegramAllowFromEntries.size > 0) {
// ... push warn finding ...
}
if (storeHasWildcard || groupAllowFromHasWildcard) {
findings.push({ checkId: "channels.telegram.groups.allowFrom.wildcard", ... });
continue;
}
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/security/audit-channel.ts
Line: 829-840
Comment:
**`*` wildcard generates spurious invalid-entry WARN alongside CRITICAL**
When a group-level wildcard is detected and the CRITICAL finding is pushed (lines 830–840), the code falls through to the `invalidTelegramAllowFromEntries` check at line 842. Because `*` is non-numeric, `collectInvalidTelegramAllowFromEntries` will have already collected it, so a redundant WARN finding (`channels.telegram.allowFrom.invalid_entries`) will also be emitted for every group that has `allowFrom: ["*"]`.
This produces confusing output: a CRITICAL for the wildcard plus a WARN for `*` being non-numeric. Consider either:
1. Filtering `*` out of `invalidTelegramAllowFromEntries` before/during collection, or
2. Adding a `continue` after the CRITICAL push (while still reporting legitimate invalid entries via a pre-check, similar to the suggestion above).
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/security/audit-channel.ts
Line: 812-814
Comment:
**Verify `storeAllowFrom` acts as a global gate for group access**
`storeAllowFrom` (the pairing store) is used here to mark a "top-level restriction" that suppresses the group-level wildcard CRITICAL. If a non-empty, non-wildcard `storeAllowFrom` does **not** actually filter Telegram group senders at runtime (e.g., it only gates DM-paired users), then this could produce false negatives — a group with `allowFrom: ["*"]` would be silently allowed despite an unrelated store entry.
The remediation text only mentions `channels.telegram.groupAllowFrom` as the global mechanism. It would be worth confirming that `storeAllowFrom` entries are also enforced before group-level `allowFrom` overrides in the Telegram runtime, and if not, removing `storeAllowFrom.length > 0 && !storeHasWildcard` from `hasTopLevelRestriction`.
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: b7581b7 |
| if (storeHasWildcard || groupAllowFromHasWildcard) { | ||
| findings.push({ | ||
| checkId: "channels.telegram.groups.allowFrom.wildcard", | ||
| severity: "critical", | ||
| title: "Telegram group allowlist contains wildcard", | ||
| detail: | ||
| 'Telegram group sender allowlist contains "*", which allows any group member to run /… commands and control directives.', | ||
| remediation: | ||
| 'Remove "*" from channels.telegram.groupAllowFrom and pairing store; prefer explicit numeric Telegram user IDs.', | ||
| }); | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Early
continue suppresses invalid-entry warnings
Moving the top-level wildcard block before invalidTelegramAllowFromEntries means that if a config has both a top-level * wildcard and other non-numeric entries (e.g., @username alongside *), those invalid entries will no longer be reported. Previously the invalidTelegramAllowFromEntries check ran before the continue, so both findings were emitted.
While the wildcard is the dominant concern, silently dropping the invalid-entry WARN could hide misconfigured allowlists that users still need to fix after removing the wildcard. Consider reporting invalid entries even in the wildcard path:
// report invalid entries first, then bail
if (invalidTelegramAllowFromEntries.size > 0) {
// ... push warn finding ...
}
if (storeHasWildcard || groupAllowFromHasWildcard) {
findings.push({ checkId: "channels.telegram.groups.allowFrom.wildcard", ... });
continue;
}Prompt To Fix With AI
This is a comment left during a code review.
Path: src/security/audit-channel.ts
Line: 816-827
Comment:
**Early `continue` suppresses invalid-entry warnings**
Moving the top-level wildcard block before `invalidTelegramAllowFromEntries` means that if a config has **both** a top-level `*` wildcard **and** other non-numeric entries (e.g., `@username` alongside `*`), those invalid entries will no longer be reported. Previously the `invalidTelegramAllowFromEntries` check ran before the `continue`, so both findings were emitted.
While the wildcard is the dominant concern, silently dropping the invalid-entry WARN could hide misconfigured allowlists that users still need to fix after removing the wildcard. Consider reporting invalid entries even in the wildcard path:
```typescript
// report invalid entries first, then bail
if (invalidTelegramAllowFromEntries.size > 0) {
// ... push warn finding ...
}
if (storeHasWildcard || groupAllowFromHasWildcard) {
findings.push({ checkId: "channels.telegram.groups.allowFrom.wildcard", ... });
continue;
}
```
How can I resolve this? If you propose a fix, please make it concise.
src/security/audit-channel.ts
Outdated
| if (groupLevelWildcards.length > 0 && !hasTopLevelRestriction) { | ||
| findings.push({ | ||
| checkId: "channels.telegram.groups.group_allowFrom.wildcard", | ||
| severity: "critical", | ||
| title: "Telegram group allowlist contains wildcard", | ||
| detail: | ||
| `Per-group sender allowlist contains "*" at:\n${groupLevelWildcards.map((p) => `- ${p}`).join("\n")}\n` + | ||
| 'This allows any group member to run /… commands and control directives.', | ||
| remediation: | ||
| 'Remove "*" from per-group allowFrom, or set channels.telegram.groupAllowFrom to restrict access globally.', | ||
| }); | ||
| } |
There was a problem hiding this comment.
* wildcard generates spurious invalid-entry WARN alongside CRITICAL
When a group-level wildcard is detected and the CRITICAL finding is pushed (lines 830–840), the code falls through to the invalidTelegramAllowFromEntries check at line 842. Because * is non-numeric, collectInvalidTelegramAllowFromEntries will have already collected it, so a redundant WARN finding (channels.telegram.allowFrom.invalid_entries) will also be emitted for every group that has allowFrom: ["*"].
This produces confusing output: a CRITICAL for the wildcard plus a WARN for * being non-numeric. Consider either:
- Filtering
*out ofinvalidTelegramAllowFromEntriesbefore/during collection, or - Adding a
continueafter the CRITICAL push (while still reporting legitimate invalid entries via a pre-check, similar to the suggestion above).
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/security/audit-channel.ts
Line: 829-840
Comment:
**`*` wildcard generates spurious invalid-entry WARN alongside CRITICAL**
When a group-level wildcard is detected and the CRITICAL finding is pushed (lines 830–840), the code falls through to the `invalidTelegramAllowFromEntries` check at line 842. Because `*` is non-numeric, `collectInvalidTelegramAllowFromEntries` will have already collected it, so a redundant WARN finding (`channels.telegram.allowFrom.invalid_entries`) will also be emitted for every group that has `allowFrom: ["*"]`.
This produces confusing output: a CRITICAL for the wildcard plus a WARN for `*` being non-numeric. Consider either:
1. Filtering `*` out of `invalidTelegramAllowFromEntries` before/during collection, or
2. Adding a `continue` after the CRITICAL push (while still reporting legitimate invalid entries via a pre-check, similar to the suggestion above).
How can I resolve this? If you propose a fix, please make it concise.
src/security/audit-channel.ts
Outdated
| const hasTopLevelRestriction = | ||
| (groupAllowFrom.length > 0 && !groupAllowFromHasWildcard) || | ||
| (storeAllowFrom.length > 0 && !storeHasWildcard); |
There was a problem hiding this comment.
Verify
storeAllowFrom acts as a global gate for group access
storeAllowFrom (the pairing store) is used here to mark a "top-level restriction" that suppresses the group-level wildcard CRITICAL. If a non-empty, non-wildcard storeAllowFrom does not actually filter Telegram group senders at runtime (e.g., it only gates DM-paired users), then this could produce false negatives — a group with allowFrom: ["*"] would be silently allowed despite an unrelated store entry.
The remediation text only mentions channels.telegram.groupAllowFrom as the global mechanism. It would be worth confirming that storeAllowFrom entries are also enforced before group-level allowFrom overrides in the Telegram runtime, and if not, removing storeAllowFrom.length > 0 && !storeHasWildcard from hasTopLevelRestriction.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/security/audit-channel.ts
Line: 812-814
Comment:
**Verify `storeAllowFrom` acts as a global gate for group access**
`storeAllowFrom` (the pairing store) is used here to mark a "top-level restriction" that suppresses the group-level wildcard CRITICAL. If a non-empty, non-wildcard `storeAllowFrom` does **not** actually filter Telegram group senders at runtime (e.g., it only gates DM-paired users), then this could produce false negatives — a group with `allowFrom: ["*"]` would be silently allowed despite an unrelated store entry.
The remediation text only mentions `channels.telegram.groupAllowFrom` as the global mechanism. It would be worth confirming that `storeAllowFrom` entries are also enforced before group-level `allowFrom` overrides in the Telegram runtime, and if not, removing `storeAllowFrom.length > 0 && !storeHasWildcard` from `hasTopLevelRestriction`.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8bfd777f74
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| continue; | ||
| } | ||
|
|
||
| if (groupLevelWildcards.length > 0 && !hasTopLevelRestriction) { |
There was a problem hiding this comment.
Do not suppress per-group wildcard findings with global allowlist
The new !hasTopLevelRestriction gate hides a real command-control exposure: Telegram runtime authorization replaces groupAllowFrom when a group/topic override exists (groupAllowOverride ?? groupAllowFrom in extensions/telegram/src/bot-message-context.ts and extensions/telegram/src/bot/helpers.ts), so groups.<id>.allowFrom: ["*"] still authorizes any member even if top-level groupAllowFrom is restricted. In configs that set a global allowlist plus per-group/topic wildcard, the audit now returns a false negative instead of the critical finding.
Useful? React with 👍 / 👎.
…From wildcard Security audit now correctly handles per-group allowFrom wildcard when top-level groupAllowFrom is already restricted. Previously, the audit only checked top-level wildcards but missed group-level ones, causing false CRITICAL alerts for intentional configurations. Closes openclaw#48687
…udit - Report invalid entries before wildcard check to avoid suppression - Add continue after group-level wildcard CRITICAL to prevent redundant WARN - Simplify hasTopLevelRestriction to only use groupAllowFrom (more conservative)
8bfd777 to
3414c3c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3414c3c7d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| continue; | ||
| } | ||
|
|
||
| if (groupLevelWildcards.length > 0 && !hasTopLevelRestriction) { |
There was a problem hiding this comment.
Flag per-group wildcard even when top-level list is set
This condition suppresses a real critical exposure: Telegram runtime authorization does not intersect top-level groupAllowFrom with per-group/topic allowFrom; it replaces it via groupAllowOverride ?? groupAllowFrom (see extensions/telegram/src/bot-message-context.ts and extensions/telegram/src/bot/helpers.ts). In configs like groupAllowFrom: ["123456"] plus groups.<id>.allowFrom: ["*"], group messages are still wildcard-authorized, so the audit now produces a false negative instead of reporting the command-control risk.
Useful? React with 👍 / 👎.
Summary
allowFromwildcard when top-levelgroupAllowFromis already restrictedChanges
groups.<id>.allowFromandgroups.<id>.topics.<topicId>.allowFromhasTopLevelRestrictioncheck to verify if top-levelgroupAllowFromor pairing store restricts accessTest plan
groupAllowFromis restrictedCloses #48687