Skip to content

approval gate misses shell-idiom-obfuscated dangerous commands (RG-4 / GHSA-6cjf-cff6-j9mg follow-up) #25793

@GodsBoy

Description

@GodsBoy

Summary

The approval gate in tools/approval.py (detect_dangerous_command, DANGEROUS_PATTERNS, and the hardline list) is an in-process heuristic per SECURITY.md section 2.4: it pattern-matches shell command strings. It misses a class of dangerous commands that are simple compositions of standard shell idioms the regex tables do not model. This is CWE-184 (Incomplete List of Disallowed Inputs): the denylist is structurally incomplete.

This issue is the RG-4 follow-up to advisory GHSA-6cjf-cff6-j9mg, which the maintainers closed out-of-scope under SECURITY.md section 3.2 with an explicit invitation to file the bypass class as a regular issue plus a PR that extends the pattern table and adds regression tests. Per section 3.2 this is not a security-boundary report; the boundary remains OS-level isolation (section 2.2). It is hardening of the cooperative-mode catch.

Idiom classes the gate misses

A dangerous command the pattern tables already match can be hidden behind any of these, individually or composed:

  • ${IFS} expansion (and ${IFS} modifier forms) and bare $IFS, used in place of spaces so the token structure does not match.
  • ANSI-C quoting: $'...' with hex, octal, named, or unicode escapes, expressing a command name entirely as escape sequences.
  • Empty / adjacent quote splits: "" or '' inserted inside a command word.
  • eval / command / builtin wrapper prefixes: the inner command is not visible to a command-position match while wrapped.
  • chmod octal-prefixed world/other-writable modes (0777, 0666): the existing pattern only covered the bare-octal form.
  • Alternate shell binaries: dash, ash invoked with -c (the recognised set was bash|sh|zsh|ksh).
  • base64-decode piped into a shell: ... | base64 -d | sh, including through command wrappers such as | sudo bash or | timeout 5 sh.
  • Shell execution of a script in a world-writable / transient path: bash /tmp/x.sh and similar, where the dangerous content is in the file and invisible to the command string.

Scope

The fix decodes the reducible idioms in pre-match normalization and widens or adds DANGEROUS_PATTERNS entries for the idiom classes that are their own structure. Decoding the payload inside $(...) or backtick command substitution is explicitly out of scope: the gate flags the wrapper structure, it does not evaluate opaque inner content.

Proposed fix

A PR implementing this with per-class regression tests (true-positive catch plus false-positive guard) follows and links back to this issue.

Notes

  • No change to the security posture. The boundary remains OS-level isolation (section 2.2); this only makes the in-process heuristic catch more.
  • PoC hygiene: specific bypass strings live in the PR's regression-test fixtures, not in this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/agentCore agent loop, run_agent.py, prompt buildercomp/toolsTool registry, model_tools, toolsetstype/securitySecurity vulnerability or hardening

    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