Skip to content

fix: never expand credential-looking env vars into prompts or the builder UI [sec-check] - #47

Merged
hivecommons-hive[bot] merged 1 commit into
mainfrom
sec/env-secret-fallback
Sep 27, 2026
Merged

hivecommons-hive[bot] merged 1 commit into
mainfrom
sec/env-secret-fallback

Conversation

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Security Fix

Claims: src/autodetect.ts (env fallback + new isSensitiveEnvName), src/ui.ts (collectEnvVars), src/autodetect.test.ts, and their compiled dist/ counterparts. Disjoint from open PR #45, which touches only src/{cli,resolver,ui}.test.ts and their dist files.

autodetect() fell back to process.env[varName] for any unrecognized template variable, so a repo-committed .prompts/*.md template 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() returns undefined for sensitive names in the env fallback — the variable stays unfilled ({{NAME}} preserved) or falls through to the interactive ask. Explicit --VAR=value flags are unaffected.
  • collectEnvVars() skips sensitive names, so the builder page never embeds them.

Verified: GITHUB_TOKEN=ghp_FAKE promptargs innocent --no-interactive now emits {{GITHUB_TOKEN}} literally; {{EDITOR}} still auto-fills; --GITHUB_TOKEN=explicit still works; UI env map no longer contains MY_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

…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>
@hivecommons-hive

Copy link
Copy Markdown
Contributor Author

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 outreach agent is always held because it publishes project-facing communication.

Hive will automatically remove the hold label once current policy no longer requires a level hold for "sec-check". If this is an outreach PR, a human must review it and remove the label.

@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Sep 26, 2026
@kubestellar-prow

Copy link
Copy Markdown

[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.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 to process.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 flags is checked first at src/resolver.ts:112, before autodetect is ever called.
  • The regex behaves on the edge cases: (^|_)AUTH(_|$) flags AUTH_HEADER/X_AUTH but not AUTHOR or AUTHORIZED_USERS_FILE (covered by tests in src/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 test at head: 78/78 pass. Rebuilt and git 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

@hivecommons-hive
hivecommons-hive Bot merged commit 8f624ac into main Sep 27, 2026
11 of 12 checks passed
@kubestellar-prow
kubestellar-prow Bot deleted the sec/env-secret-fallback branch September 27, 2026 14:25
@github-actions

Copy link
Copy Markdown

Thank you for your contribution! Your PR has been merged.

We'd love to hear how your experience was: share feedback

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

Labels

copilot dco-signoff: yes Indicates the PR's author has signed the DCO. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sec-check] Templates silently expand secret env vars ({{GITHUB_TOKEN}}) into AI prompts; builder UI embeds unmasked secrets

0 participants