Skip to content

fix(trust): eliminate TOCTOU race in filter loading; harden CI trust bypass#2050

Open
rosschurchill wants to merge 2 commits into
rtk-ai:developfrom
rosschurchill:fix/c01-toctou-filter-trust
Open

fix(trust): eliminate TOCTOU race in filter loading; harden CI trust bypass#2050
rosschurchill wants to merge 2 commits into
rtk-ai:developfrom
rosschurchill:fix/c01-toctou-filter-trust

Conversation

@rosschurchill
Copy link
Copy Markdown

Two issues in the filter trust path:

TOCTOU race (CWE-367): check_trust() reads and hashes the filter file, then load() re-reads it via fs::read_to_string(). An attacker can swap a malicious file into the race window between the two reads. Fix: read once into Vec<u8>, compute SHA-256 in-process, pass the pre-computed hash to a new check_trust_from_hash() — the file is never re-read.

CI trust bypass: CI=true is trivially settable in any .envrc or shell profile, making the env-var trust override reachable outside CI. Tightened to require a platform-specific var (GITHUB_ACTIONS, GITLAB_CI, JENKINS_URL, or BUILDKITE).

Also adds a validate_filter_safety() gate in compile_filter() that rejects obviously dangerous filter patterns (on_empty=pass, head_lines=1, match_command=.*).

Free to use as-is.

rosschurchill and others added 2 commits May 23, 2026 06:26
…rust bypass

C-01 (TOCTOU): toml_filter.rs previously called check_trust() (which reads+hashes
the file) then fs::read_to_string() a second time. A race-replacement between the
two reads could inject arbitrary filter rules. Fix: read once into Vec<u8>, compute
SHA-256 in-process, call new check_trust_from_hash() which never re-reads the file.

CI bypass hardening (Chain A): removed bare CI=true from the allowed list for
RTK_TRUST_PROJECT_FILTERS=1. Only verified platform variables (GITHUB_ACTIONS,
GITLAB_CI, JENKINS_URL, BUILDKITE) now grant EnvOverride. CI=true is trivially
settable in .envrc and was a local-bypass vector.

Chain A risk gate: compile_filter() now calls validate_filter_safety() before
adding a filter to the registry. Rejects on_empty="pass", head_lines=1, and
match_command=".*"/".*+" — the three patterns identified in the Chain A exploit.

Also gates all eprintln! sites in trust.rs (2) and toml_filter.rs (13) behind
in_hook_mode() to fix C-07 in these files (C-07 helper landed in prior commit).

Adds TOCTOU regression test and CI-bypass test in trust.rs test module.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore helper

test_env_override_with_ci used generic CI=true which C-01 intentionally
removed — update to use GITHUB_ACTIONS to match the new hardened policy.
test_ci_bypass_requires_platform_ci_not_generic and test_env_override_with_ci
both mutate the same env vars; add ENV_TEST_LOCK mutex to serialize them.
Add check_trust_from_hash_with_store test helper so the TOCTOU test can
verify hash comparison without reading from the real trust store.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

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.

2 participants