Skip to content

fix(review): tighten hyphenated secret placeholder scan#3673

Merged
JSONbored merged 1 commit into
mainfrom
codex/fix-secret-scanner-bypass-vulnerability
Jul 6, 2026
Merged

fix(review): tighten hyphenated secret placeholder scan#3673
JSONbored merged 1 commit into
mainfrom
codex/fix-secret-scanner-bypass-vulnerability

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Motivation

  • A previous change treated any entirely lowercase hyphenated value as a placeholder and suppressed generic_secret_assignment matches, which incorrectly allowed plausible passphrase-style credentials (e.g. password = "correct-horse-battery-staple") to bypass the hard secret_leak gate.
  • The intent is to keep common token/fixture exclusions (like installation-token) while preserving hard-blocking behavior for sensitive keys such as password, passwd, and client_secret.

Description

  • Capture the assignment key and value in the generic-assignment regex so placeholder logic can be key-aware instead of value-only, and add mock to the placeholder pattern. (src/review/secrets-scan.ts).
  • Replace the broad lowercase-hyphenated exclusion with a narrow two-word token-fixture pattern that only exempts token-style fixtures (e.g. installation-token), and make isPlaceholderSecretValue accept (key, value) so password-like keys are not exempted. (src/review/secrets-scan.ts).
  • Update hasGenericSecretAssignment to use the key-aware placeholder check and preserve existing monotonic-run / placeholder checks so high-entropy tokens still block. (src/review/secrets-scan.ts).
  • Add unit tests covering the intended behavior: ensure known token fixtures remain excluded but lowercase-hyphenated credentials assigned to password/passwd/client_secret (and multi-segment tokens) are flagged, and add an advisory wiring test verifying a lowercase-hyphenated password assignment becomes a secret_leak with file:line location. (test/unit/secrets-scan.test.ts, test/unit/safety-wiring.test.ts).

Testing

  • Ran the focused unit tests with npx vitest run test/unit/secrets-scan.test.ts test/unit/safety-wiring.test.ts, and all selected tests passed.
  • Ran npm run typecheck and it completed successfully.
  • Attempted the full coverage run npm run test:coverage but the repository-wide suite failed to complete due to unrelated long-running/timeouts in existing backfill tests and global coverage thresholds (existing unrelated tests caused the run to exceed time/thresholds).
  • Attempted npm audit --audit-level=moderate but the environment returned 403 Forbidden for the npm audit endpoint so the dependency-audit step could not be completed here.

Codex Task

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 6, 2026
@loopover-orb

loopover-orb Bot commented Jul 6, 2026

Copy link
Copy Markdown

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-06 02:03:41 UTC

3 files · 1 AI reviewer · 2 blockers · readiness 93/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.

Review summary
This PR fixes a real over-broad exclusion: the previous LOWERCASE_HYPHENATED_COMPOUND_PATTERN exempted any pure lowercase-hyphenated value from generic_secret_assignment regardless of the assignment key, which let passphrase-style credentials like password = "correct-horse-battery-staple" bypass the hard secret_leak gate. The fix makes the exclusion key-aware (only exempts when the captured key is literally "token") and value-shape-narrow (exactly two hyphen-joined segments), while adding "mock" to the placeholder-phrase list to keep multi-segment fixture names like "some-mock-secret-value" excluded via that separate path. I traced the regex capture-group change (match[1]=key, match[2]=value) through isPlaceholderSecretValue and hasGenericSecretAssignment and it's internally consistent, and the new tests exercise both arms of the key==='token' branch (exempted vs. not) plus the multi-segment-token case that still gets flagged despite the key being 'token'.

Nits — 3 non-blocking
  • The token-fixture exemption only fires for an exact key match of "token" (src/review/secrets-scan.ts isPlaceholderSecretValue) — a fixture keyed `access_token` or `apiToken` won't get the carve-out even though it's semantically the same kind of fixture; worth confirming no existing test fixtures in the repo use those key spellings with two-word hyphenated values, since they'd newly start blocking.
  • The generic_secret_assignment test fixtures ("alpha-bravo-charlie-delta") are synthetic and clearly not real credentials, but an automated secret scanner may flag them — worth a one-line comment noting they're synthetic test data if that scanner runs in CI, similar to the FAKE_GH_TOKEN comment already in safety-wiring.test.ts.
  • Consider whether other sensitive keys beyond password/passwd/client_secret (e.g. secret itself) should also be explicitly covered by a dedicated test case for the multi-segment-flagged behavior, for symmetry with the token case already tested.

Concerns raised — review before merging

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.
Signal Result Evidence
Code review ❌ 2 blockers 1 reviewer
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 55 registered-repo PR(s), 46 merged, 457 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 55 PR(s), 457 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 55 PR(s), 457 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Explain no-issue PR.
  • No action.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.20%. Comparing base (ad581ac) to head (267022a).
⚠️ Report is 32 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3673   +/-   ##
=======================================
  Coverage   93.20%   93.20%           
=======================================
  Files         313      313           
  Lines       31910    31910           
  Branches    11677    11677           
=======================================
  Hits        29741    29741           
  Misses       1517     1517           
  Partials      652      652           
Files with missing lines Coverage Δ
src/review/secrets-scan.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 6, 2026
@JSONbored
JSONbored merged commit ddf68c3 into main Jul 6, 2026
10 checks passed
@JSONbored
JSONbored deleted the codex/fix-secret-scanner-bypass-vulnerability branch July 6, 2026 02:08
JSONbored added a commit that referenced this pull request Jul 12, 2026
)

PR #5346 (a resubmission of #5341) was auto-closed over two inert
test-fixture strings that matched the generic_secret_assignment
keyword-plus-quoted-value SHAPE but weren't real credentials -- the
same heuristic has now caused at least eight prior false-positive
incidents (#2613, #3178, #3673, #3866, #4587, #4733, plus several
fixture-rewording commits), each patched by narrowing an allowlist
rather than fixing the underlying design.

REES's own copy of this rule already rates it "medium confidence"
("catches real keys but also the occasional long opaque non-secret"),
and content-lane/security-scan.ts's own header states the design
principle this violated: a gate that auto-closes with no human queue
may only hard-close on a signal unambiguous enough that a false
positive is essentially impossible.

Split generic_secret_assignment out of HARD_SECRET_KINDS into a new
ADVISORY_ONLY_SECRET_KINDS: it still surfaces (a warning-severity
possible_secret_assignment finding / a "manual" content-lane verdict),
but never auto-blocks or auto-closes on its own. Concrete credential
formats (github_token, aws_access_key, private_key_block, ...) are
unaffected and remain unconditional hard blockers.

Also add a structural placeholder heuristic (looksLikeDescriptive
PlaceholderPhrase, mirrored in REES): a value with 5+ lowercase-only
hyphen/underscore segments containing an English function word reads
as written prose describing the value, not a credential or a chosen
passphrase -- this independently resolves both PR #5346 literals
without weakening detection of a genuine human-chosen passphrase like
"correct-horse-battery-secret" (no function words, by design).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant