Skip to content

fix(interp): refuse help <cmd> in Check for RemediationOnly builtins - #709

Open
astuyve wants to merge 1 commit into
mainfrom
patina/help-check-remediation
Open

astuyve wants to merge 1 commit into
mainfrom
patina/help-check-remediation

Conversation

@astuyve

@astuyve astuyve commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator

What

Run refuses help <cmd> for a RemediationOnly builtin (rm, tee, truncate, logrotate, systemctl) outside remediation mode, but Check returned early for help without looking at its operand, so it approved scripts Run then refused. Not an escape (Run still enforces the gate), but Check should never approve what Run refuses.

  • Check now applies the same remediationOnlyRefusal predicate dispatch uses for help <name> (unless the operand is a feature topic) and reports CheckRemediationRequired with the same message.
  • help now checks the remediation gate before printing static Help text, so a RemediationOnly builtin with static help can't print it outside remediation mode. None of today's five has static help; this closes it for future ones.

Not covered here: Check also doesn't model help <cmd> for a command outside AllowedCommands, which Run refuses with exit 1.

Credit

Found by Jacob Hayes with his deterministic-simulation tool patina (finding #3: Check-vs-Run oracle, about 6.3k runs). Findings thread: https://dd.slack.com/archives/D0AC8RLB21J/p1793475631273749

Tests

TestCheckHelpOfRemediationOnlyBuiltinMatchesRun (interp/check_test.go) enumerates the RemediationOnly builtins from the registry, so new ones are covered, and asserts that Check's verdict matches Run in read-only and remediation mode. It fails for all five on main. go test ./... passes except TestPSPentestLargePIDListDoesNotHang in builtins/ps, which fails the same way on clean main on this host.

🤖 Generated with Claude Code

Run refuses `help <cmd>` for a RemediationOnly builtin (rm, tee,
truncate, logrotate, systemctl) outside remediation mode, but Check
returned early for `help` without looking at its operand, so it
approved scripts Run then refused. Check now applies the same
remediationOnlyRefusal predicate dispatch uses and reports
CheckRemediationRequired.

help also checks the remediation gate before printing a command's
static Help text, so a RemediationOnly builtin with static help can't
print it outside remediation mode either.

Found by Jacob Hayes with patina (https://github.com/JacobHayes/patina),
with a Check-vs-Run oracle.

Environment: Datadog workspace

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@astuyve
astuyve marked this pull request as ready for review November 1, 2026 00:00
@astuyve
astuyve requested review from a team as code owners November 1, 2026 00:00
@astuyve
astuyve requested a review from louis-cqrl November 1, 2026 00:00

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant