Repository navigation
tool-bash: strict profile skips quoted payloads (bash -c "sudo id" passes) #408
Description
Summary
The bash tool in microsoft/amplifier-module-tool-bash (that repo has issues disabled, so filing here) applies a strict safety profile (the default) that matches literal spellings at command position, and command positions inside quoted strings are excluded by design (to avoid false positives like git commit -m 'rm -rf cleanup'). The side effect: any blocked command wrapped in an interpreter payload is never examined, because it sits inside quotes:
'sudo id' -> allowed=False reason='Privilege escalation not allowed in strict mode'
'rm -rf /' -> allowed=False reason='Prevents root filesystem deletion'
'bash -c "sudo id"' -> allowed=True
"sh -c 'rm -rf /'" -> allowed=True
"eval 'sudo id'" -> allowed=True
'echo sudo | sh' -> allowed=True
'python -c "import os; os.system(\'rm -rf /\')"' -> allowed=True
Combined with validate() ending in "Default: allow" for everything not on the list, the profile only stops commands typed exactly the way the patterns spell them.
Where it happens
amplifier_module_tool_bash/safety.py:
_is_in_command_position()returnsFalsefor any position_in_quoted_region()— so an occurrence ofsudo,rm -rf /, etc. inside'…'or"…"is skipped entirely.STRICT_PROFILEblocks the literal tokenssudo,su -,rm -rf /,rm -rf ~,rm -fr …,mkfs,passwd,dd if=/dev/zero, the fork bomb — but nothing about interpreter wrappers (bash -c,sh -c,eval,python -c,env …) that carry the payload as a quoted argument.
Repro (offline, shipped bytes at HEAD)
Against amplifier_module_tool_bash/safety.py (blob a15c7fba):
import amplifier_module_tool_bash.safety as safety
v = safety.SafetyValidator(profile="strict")
for cmd in ["sudo id", "rm -rf /", 'bash -c "sudo id"', "sh -c 'rm -rf /'",
"eval 'sudo id'", "echo sudo | sh",
'python -c "import os; os.system(\'rm -rf /\')"']:
r = v.validate(cmd)
print(f"{cmd!r:58s} -> allowed={r.allowed}" + (f" reason={r.reason!r}" if not r.allowed else ""))The verbatim output is the table above.
Context
This tool does default require_approval = True, so the approval layer — not the pattern list — is the real control, and this report is about the gap between what the README §Security tells operators the profiles do and what they can do:
Use
strictprofile (default) for shared/workstation environments … Never execute untrusted user input
A pattern list that can be defeated by quoting cannot carry "never execute untrusted input" on a workstation; the two bullets promise different strengths. The same text-matching mechanism is reported against the pwsh sibling module in #407 (microsoft/amplifier-bundle-windows-shell), which additionally ships with no approval surface at all.
Suggested direction
- At
strict, reject interpreter wrappers carrying quoted payloads (bash -c,sh -c,eval,python -c, …) rather than skipping their contents — the false-positive goal (commit messages,echostrings) is about string arguments to ordinary commands, not about spawning a nested interpreter whose entire payload is quoted command text. - Block
evaloutright at strict, the waysudois blocked. - Longer term, decide on parsed structure rather than text: tokenize the command (e.g.
shlex) and evaluate the resulting argv tree, including recursing into-cpayloads, instead of substring positions.
Verified at HEAD aa363e9b (default branch main), 2026-09-20.
Activity