Repository navigation
fix: never expand credential-looking env vars into prompts or the builder UI [sec-check] - #47
Conversation
…into prompts or the builder UI
autodetect()'s process.env fallback expanded any {{VAR}} name, so a
repo-committed .prompts/ template containing {{GITHUB_TOKEN}} silently
exfiltrated the secret into the generated AI prompt — even with
--no-interactive. The builder UI likewise embedded every non-cosmetic
env var (full tokens survive the 80-char truncation) in the served page.
Add isSensitiveEnvName() (TOKEN/SECRET/PASSWORD/PASSWD/CREDENTIAL/
API_KEY/ACCESS_KEY/PRIVATE_KEY/BEARER/COOKIE/AUTH-segment, case-
insensitive) and gate both sinks: the implicit env fallback returns
undefined for sensitive names (the var stays unfilled or falls through
to interactive ask), and collectEnvVars() skips them. Explicit
--VAR=value flags are unaffected.
Closes #46
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sec-check <sec-check@hive.kubestellar.io>
|
Important Held for human review by the hive's ACMM level gate. This PR was opened by the "sec-check" agent while Hive policy required a human checkpoint for that agent. Non-outreach agents are held at ACMM L3–L5; the Hive will automatically remove the |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Read the tree at head 878a345, ran the suite: the fix is correct and does what the body claims. Details verified:
- The exfiltration path was real:
autodetect()fell back toprocess.env[varName]for any unknown name (src/autodetect.ts, pre-change), and the resolver consults autodetect before defaults/ask (src/resolver.ts:125), so a repo template{{GITHUB_TOKEN}}did expand silently. - Explicit flags still work as claimed:
v.name in flagsis checked first atsrc/resolver.ts:112, before autodetect is ever called. - The regex behaves on the edge cases:
(^|_)AUTH(_|$)flagsAUTH_HEADER/X_AUTHbut notAUTHORorAUTHORIZED_USERS_FILE(covered by tests insrc/autodetect.test.ts). - Both sinks are gated: env fallback (
src/autodetect.ts) and the builder UI page (src/ui.ts:53). - Ran
npm ci && npm testat head: 78/78 pass. Rebuilt andgit status --porcelain -- dist/is clean, so the dist-sync gate will pass. - Claimed disjointness from #45 is accurate — no file overlap.
One follow-up (low, doc-only): README.md:280 still lists GITHUB_TOKEN among "Common useful env vars", and the section at README.md:269 says any env var is available. Both are now untrue for credential-shaped names; worth a one-line doc touch-up here or in a follow-up.
Looks correct to me — a human should confirm the deny-pattern breadth (e.g. names like KEY alone are deliberately not matched) and sign off.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88
|
Thank you for your contribution! Your PR has been merged. We'd love to hear how your experience was: share feedback |
Security Fix
Claims:
src/autodetect.ts(env fallback + newisSensitiveEnvName),src/ui.ts(collectEnvVars),src/autodetect.test.ts, and their compileddist/counterparts. Disjoint from open PR #45, which touches onlysrc/{cli,resolver,ui}.test.tsand their dist files.autodetect()fell back toprocess.env[varName]for any unrecognized template variable, so a repo-committed.prompts/*.mdtemplate containing{{GITHUB_TOKEN}}silently exfiltrated the secret into the generated AI prompt — before defaults, before interactive ask, even with--no-interactive. The builder UI (collectEnvVars) likewise embedded every env var not in the cosmetic skip lists into the served page; the 80-char truncation does not protect real tokens (~40 chars).This PR adds
isSensitiveEnvName()(matches TOKEN, SECRET, PASSWORD, PASSWD, CREDENTIAL, API_KEY/APIKEY, ACCESS_KEY, PRIVATE_KEY, BEARER, COOKIE, and AUTH as a name segment, case-insensitive) and gates both sinks:autodetect()returnsundefinedfor sensitive names in the env fallback — the variable stays unfilled ({{NAME}}preserved) or falls through to the interactive ask. Explicit--VAR=valueflags are unaffected.collectEnvVars()skips sensitive names, so the builder page never embeds them.Verified:
GITHUB_TOKEN=ghp_FAKE promptargs innocent --no-interactivenow emits{{GITHUB_TOKEN}}literally;{{EDITOR}}still auto-fills;--GITHUB_TOKEN=explicitstill works; UI env map no longer containsMY_API_TOKEN. Full suite: 78/78 pass.dist/rebuilt and committed for the dist-sync gate.Closes #46
Filed by sec-check agent (ACMM L4/L5 — hold-gated mode). Hold-gated: human review required.
— hive: agent=sec-check backend=copilot model=claude-fable-5 copilot=1.0.88