Repository navigation
Redact bounded env/shell wrapper command operands #907
Copy link
Copy link
Open
Labels
area: apiAPI, protocol, event, or external contractAPI, protocol, event, or external contractarea: performancePerformance, resource use, scalability, or benchmarkingPerformance, resource use, scalability, or benchmarkingarea: securitySecurity boundary, hardening, or vulnerability preventionSecurity boundary, hardening, or vulnerability preventionarea: ui-uxFrontend, interaction, design, or user experienceFrontend, interaction, design, or user experiencemaintenancepriority: mediumNormal-priority or P2 workNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmentOpen issue has an organization taxonomy assignmenttype: featureNew or expanded product capabilityNew or expanded product capability
Description
Outcome
Sandbox command evidence redacts credentials inside supported wrapper operands without creating unbounded recursive parsing or masking benign command arguments.
Current defect
Draft #906 contains the direct Docker/Podman login -p, -p=, and --password= repair, but the current command-text path tokenizes only the outer command. Direct reproductions remain:
env -S 'docker login -p <opaque>';sh -c 'podman login -p <opaque>';- nested
env→ shell-ccombinations.
The opaque credential survives because the wrapper operand is treated as ordinary data. Blindly calling the text and argv redactors recursively would instead create attacker-controlled recursion/CPU risk.
Required repair
- recognize only exact wrapper program basenames and exact option/operand positions:
env -S,env --split-string, and the long--split-string=...spelling;sh,bash,dash,ksh, orzshcommand strings selected by an exact/combined-coption;
- preserve the public APIs through private depth/context helpers and compile the literal matcher once at the public entry point;
- use
MAX_COMMAND_WRAPPER_DEPTH = 4,MAX_COMMAND_INPUT_BYTES = 65_536,MAX_COMMAND_TOKENS = 4_096, andMAX_COMMAND_WORK = 262_144; share one UTF-8 byte/token/cumulative-work budget across the complete wrapper tree; - at the depth bound, redact the entire remaining nested operand; at a root byte/token/work limit, fail closed for the complete public evidence;
- fail closed on malformed quoting/tokenization without publishing the raw nested operand or parser diagnostic;
- preserve executable argv,
shell=False, environment, exit, timeout, process-group, and cleanup behavior; - preserve benign
env -u/--unset,env -C/--chdir, assignments, Docker publish-port-p 8080:80, and SSH port-p 22diagnostics; - keep the direct Docker/Podman fix and its runtime-synthesized fixtures.
Security design constraints
- Python
shlexis not a semantic parser for either full shell-cinput or GNUenv -S; it may be used only after a linear quote-state scanner accepts a documented grammar subset. - For every supported wrapper, backslashes, line breaks, an unquoted
$, backtick, or#, and unclosed/unsupported quoting fail closed. For shell operands, unquoted control/operators such as;,&&,||, pipes, redirection, substitution, heredoc, parentheses, and glob/meta syntax also fail closed. Expansion inside double quotes is unsupported and fails closed. - GNU
env -S/--split-stringhas its own escape, comment, expansion, and trailing-argv behavior. Unsupported#, backslash forms (including\c),${...}, or any trailing argv that could combine with the split operand fail closed for the complete command evidence. - Shell
-cfollowing$0/positional argv must be preserved only under an explicitly proven mapping; otherwise the complete command evidence fails closed. A compound command such assh -c 'echo ok; docker login -p <opaque>'must never be treated as one simpleshlexcommand. - Share one precompiled sensitive-value context and the single cumulative budget across every nested wrapper. Depth-only recursion, repeated full rescans, and repeated unbounded
shlex.joinexpansion are forbidden. - Malformed syntax, unsupported grammar, depth exhaustion, or budget exhaustion returns bounded redaction without raw text or exception details.
- Container-login detection is exact: the normalized program is Docker/Podman and
command[1] == "login"; never infer the subcommand using membership elsewhere in argv. - Fix and pin the current option false positives:
docker login --password-stdin registrypreserves the registry because the option consumes stdin, not the following argv element;--password-stdin=...remains conservatively redacted because it is not the valid no-argument form;docker run --name login -p 8080:80 imageanddocker run login -p 8080:80 imagepreserve the publish port because an unrelatedloginargument is not the login subcommand.
- Preserve
env -u/--unset/-C/--chdirvalues, ordinary assignments, Docker publish ports, and SSH ports. - Cross-boundary fixtures cover JSON command fields containing wrappers and shell operands containing JSON; unsupported compositions fail closed.
Acceptance
- fail-first tests cover
env -S,env --split-string, long=form, every listed shell basename and combined-cselector, env → shell nesting, malformed inner/outer quoting, compound shell syntax, env escapes/expansion/trailing argv, and a fixed ten-level nesting tree; - boundary tests cover input UTF-8 bytes, total parsed tokens, cumulative scan work, maximum depth, and each limit plus one;
- negative tests prove benign env options/assignments,
--password-stdinregistry, unrelatedloginarguments, Docker publish ports, and SSH ports are byte-visible; - direct Docker/Podman
-p,-p=, and--password=credential cases remain redacted; - all credential-shaped fixtures are synthesized at runtime; no fixed credential-shaped literal is committed;
- Sandbox Log Redaction Quality CI passes at the exact head with 100% statement/branch coverage for the three owned production modules;
- full suite, compile/docstring checks, Secret Scan over the full PR range, security/supply-chain gates, current source review, independent non-author approval, and protected-main stdout/stderr/timeout/service-tail canaries pass;
- Bound sandbox subprocess output and long-running service logs #766 remains the separate total-output/service-file resource-safety residual; this issue must not claim end-to-end output-memory closure;
- fix(sandbox): replay redaction after fixture-history contamination #906 remains Draft until this issue and the separate atomic-JSON boundary are either repaired or explicitly removed from its acceptance scope.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area: apiAPI, protocol, event, or external contractAPI, protocol, event, or external contractarea: performancePerformance, resource use, scalability, or benchmarkingPerformance, resource use, scalability, or benchmarkingarea: securitySecurity boundary, hardening, or vulnerability preventionSecurity boundary, hardening, or vulnerability preventionarea: ui-uxFrontend, interaction, design, or user experienceFrontend, interaction, design, or user experiencemaintenancepriority: mediumNormal-priority or P2 workNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmentOpen issue has an organization taxonomy assignmenttype: featureNew or expanded product capabilityNew or expanded product capability
Activity
seonghobae commentedon Aug 11, 2026
Implemented on Draft #906 exact head
18a6d125fead8cb95972fe3e1a97e4cc4163e9d2without broadening execution authority. The fail-first slice began with 31 focused failures; current local acceptance is 142 focused passes with exact 100% statement/branch coverage across the three owned modules (784 statements, 302 branches), followed by 1,060 full-suite passes plus 16 subtests, exact complete owned-production coverage (7,395 statements, 2,960 branches), compilation/diff checks, and a passing Strix quick gate. The permanent quality workflow now owns the new wrapper suite. Exact-head hosted CI/security is running; this issue remains open and #906 remains Draft until that evidence and the separate #908 boundary are resolved.seonghobae commentedon Aug 11, 2026
Current active-PR evidence: #906 exact head
d573d21752e07d3cbbf9845b4b413baf81ecea7cnow fails closed when malformed outersh -c,env -S, orenv --split-string=quoting prevents safe tokenization. Three fail-first cases exposed the runtime-synthesized opaque credential on predecessor head and pass after the repair. Local exact-head proof is 145 focused tests with 789/789 statements and 306/306 branches, followed by 1,063 full-suite tests plus 16 subtests and 7,400/7,400 owned-production statements with 2,964/2,964 branches. Exact-head Sandbox Log Redaction Quality CI, Strix, Secret Scan, Security Scan, Semgrep, SBOM, Scorecard, and OSV have succeeded; CodeQL and Python Security remain queued and are not passing evidence. Keep this issue open: the capability isactive_pr, notimplemented_on_protected_main, and independent review plus protected-main acceptance remain outstanding.