fix(runtime): block separator-less secret env names from WASM guests#6316
Merged
Conversation
host_env_read suppresses secret-looking env vars (API_KEY, MY_TOKEN, ...) before returning them to a WASM guest, using a both-sides word-boundary match that was deliberately tightened so benign config like MONKEYHOUSE / TOKENIZER_OPTS stays readable by an EnvRead("*") plugin. But a separator-less name such as APIKEY, MYTOKEN, DBPASSWORD or ALGOLIA_APIKEY glues the credential word to the end with no boundary, so the both-sides check missed it and host_env_read returned the real value to any guest holding a wildcard EnvRead capability.
Add a suffix rule: any name ending in a blocked secret word (KEY / SECRET / TOKEN / PASSWORD / CREDENTIAL / PRIVATE) is now treated as a secret. This errs toward over-blocking (a benign TURKEY / MONKEY ending in KEY is also suppressed), which is the safe direction here — the guest receives null, never a credential. A starts_with rule is deliberately NOT added: it would re-break TOKENIZER_OPTS / PRIVATELABEL_NAME / PASSWORDLIST_FILE, which legitimately begin with a blocked word.
houko
force-pushed
the
fix-wasm-env-blocklist-suffix
branch
from
June 25, 2026 13:16
3d7cad1 to
07ef530
Compare
This was referenced Jun 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
host_env_read(the WASM host function backingEnvRead) suppresses secret-looking environment variables before handing them to a guest, so that a plugin grantedEnvRead("*")cannot readANTHROPIC_API_KEY,MY_TOKEN, etc.The match is a both-sides word-boundary check, deliberately tightened (over a plain
contains) so benign config likeMONKEYHOUSE,KEYBOARD_LAYOUT,TOKENIZER_OPTSstays readable.The gap: a separator-less secret name glues the credential word to the end with no boundary —
APIKEY,MYTOKEN,DBPASSWORD,GHTOKEN,STRIPEKEY,ALGOLIA_APIKEY.For
APIKEY,KEYstarts at index 3 with the preceding byteI(alphanumeric), so the both-sides rule rejects the match and the variable is not blocked —host_env_readthen returns the real secret to the guest.This is a defense-in-depth bypass for any plugin holding a wildcard
EnvReadcapability.Changes
crates/librefang-runtime/src/host_functions.rs—is_blocked_env_varnow matchesupper.ends_with(sub) || has_word_boundary_substring(&upper, sub).The suffix arm catches the separator-less names; the existing both-sides arm is unchanged.
starts_witharm is intentionally omitted: it would re-flagTOKENIZER_OPTS/PRIVATELABEL_NAME/PASSWORDLIST_FILE, the exact benign-config false positives the both-sides rule was written to allow.TURKEY,MONKEY), which is the safe direction — the guest getsnull, never a credential.Verification
cargo clippy -p librefang-runtime --lib -- -D warnings— passed, zero warnings.cargo test -p librefang-runtime --lib is_blocked_env_var— 2 passed, 0 failed. The extendedtest_is_blocked_env_var_word_boundarynow assertsAPIKEY/MYTOKEN/DBPASSWORD/GHTOKEN/STRIPEKEY/ALGOLIA_APIKEYare blocked, while the existing benign negatives (MONKEYHOUSE,KEYBOARD_LAYOUT,TOKENIZER_OPTS,PRIVATELABEL_NAME,PASSWORDLIST_FILE,MASTERKEYBOARD) still pass.cargo fmt -p librefang-runtime --check— clean.(Run in the repo's
Dockerfile.rust-devimage against an isolated target volume, per the project's no-local-cargo rule.)Context
Surfaced by a repo-wide security audit. Filed as its own PR (one of several from that pass); it is self-contained in the WASM-sandbox host-function layer and unrelated to the other findings.