Skip to content

fix(review): tighten mock placeholder carve-out to avoid secret-scan false negatives - #3866

Merged
JSONbored merged 1 commit into
mainfrom
codex/propose-fix-for-mock-placeholder-vulnerability
Jul 6, 2026
Merged

fix(review): tighten mock placeholder carve-out to avoid secret-scan false negatives#3866
JSONbored merged 1 commit into
mainfrom
codex/propose-fix-for-mock-placeholder-vulnerability

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Motivation

  • A recent change added a broad \bmock\b placeholder term that short-circuited isPlaceholderSecretValue, causing generic secret assignments containing a separate mock token to be suppressed and creating a security-relevant false negative.
  • The intent is to continue excluding clear lowercase-hyphenated fixture names from false positives while restoring detection for mixed-case or digit-bearing values that include mock.

Description

  • Remove the broad \bmock\b entry from PLACEHOLDER_VALUE_PATTERN so values containing mock are no longer universally treated as placeholders.
  • Add LOWERCASE_HYPHENATED_MOCK_FIXTURE_PATTERN to precisely match lowercase hyphenated mock fixture names and treat only those as placeholders.
  • Update isPlaceholderSecretValue to consider the new LOWERCASE_HYPHENATED_MOCK_FIXTURE_PATTERN before excluding a match.
  • Add unit tests covering mixed-case / digit-bearing mock-... credential values and a safety-gate regression to ensure such cases produce a generic_secret_assignment and a secret_leak finding (test/unit/secrets-scan.test.ts and test/unit/safety-wiring.test.ts).

Testing

  • Ran git diff --check and the focused unit suite via npm test -- --run test/unit/secrets-scan.test.ts test/unit/safety-wiring.test.ts, and those tests passed.
  • Attempted the full coverage run npm run test:coverage, which did not complete due to an unrelated recursion in test/unit/queue.test.ts producing a RangeError: Maximum call stack size exceeded.
  • Attempted npm audit --audit-level=moderate, but the registry audit endpoint returned 403 Forbidden so the audit step could not be completed.

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
Contributor

Warning

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

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-06 20:33:40 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 narrows a secret-scanner placeholder carve-out that had regressed detection: the prior broad `\bmock\b` term in PLACEHOLDER_VALUE_PATTERN caused any secret-shaped value containing the substring "mock" to be silently excluded, including real-looking mixed-case/digit-bearing credentials. The fix removes that broad term and replaces it with a narrow LOWERCASE_HYPHENATED_MOCK_FIXTURE_PATTERN (`^(?:[a-z]+-)*mock(?:-[a-z]+)*$`) that only exempts clearly-fixture-shaped, all-lowercase hyphenated mock names, restoring detection for `mock-aK9xQ2mZw7Ln4Rv8Pt3Bh6`-style values. The logic is correct and the new/updated unit tests (secrets-scan.test.ts, safety-wiring.test.ts) exercise both the exemption and the regression case end-to-end through secretLeakFinding and the gate.

Nits — 5 non-blocking
  • src/review/secrets-scan.ts:72 — the new pattern nests a `+` quantifier inside a `*`-quantified group (`(?:[a-z]+-)*`), which superficially resembles a ReDoS shape; on inspection the mandatory literal `-` separator forces a deterministic split at each hyphen so there's no actual exponential backtracking, but it'd be worth a comment noting why this is safe (or a quick fuzz/timing test) since a future edit could remove that separator and reintroduce real risk.
  • test/unit/safety-wiring.test.ts:321-330 and test/unit/secrets-scan.test.ts:170-176 — the two new test cases are near-duplicates of each other (one in the safety-wiring integration test, one in the unit test); consider whether both are needed or if one could reference the other to avoid drift.
  • No test verifies a case like `'mock-mock'` or a bare `'mock'` used as the whole value — not required given the 16+ char floor on the generic pattern, but worth a comment noting that constraint so a reader doesn't assume the new fixture pattern alone gates short values.
  • Consider adding one test asserting that a lowercase-hyphenated value ending or starting with `mock` but containing digits (e.g. `mock-fixture-2`) is still treated as a fixture, to pin down the exact boundary of the new pattern versus the digit-bearing regression case.
  • The header comment above LOWERCASE_HYPHENATED_MOCK_FIXTURE_PATTERN (secrets-scan.ts:70-71) could briefly note why the nested quantifier is ReDoS-safe (mandatory hyphen separator forces a unique split), preempting the exact concern a future reviewer or scanner will raise.

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: 51 registered-repo PR(s), 43 merged, 372 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 51 PR(s), 372 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 is configured for direct PR review.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 51 PR(s), 372 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.
  • 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.49%. Comparing base (125aa00) to head (8a497ae).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3866   +/-   ##
=======================================
  Coverage   93.49%   93.49%           
=======================================
  Files         333      333           
  Lines       33196    33198    +2     
  Branches    12140    12141    +1     
=======================================
+ Hits        31035    31037    +2     
  Misses       1530     1530           
  Partials      631      631           
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 7d145f0 into main Jul 6, 2026
10 checks passed
@JSONbored
JSONbored deleted the codex/propose-fix-for-mock-placeholder-vulnerability branch July 6, 2026 20:53
JSONbored added a commit that referenced this pull request Jul 10, 2026
…ds (#4604)

content-lane/security-scan.ts had drifted from its two siblings
(secrets-scan.ts, review-enrichment's secret-scan.ts): it was missing the
LOWERCASE_HYPHENATED_MOCK_FIXTURE_PATTERN placeholder carve-out added by
#3866, so a fixture value like `token: "mock-response-value"` would
auto-close a legitimate content-lane submission with no human queue to
catch the false positive. It was also missing the voyage_api_key and
firecrawl_api_key patterns added to secrets-scan.ts by #3980, so a real
Voyage/Firecrawl key embedded in a content submission produced no
finding at all.

Ports both fixes verbatim into the content-lane copy and adds both kinds
to its HARD_SECRET_KINDS set for auto-close parity with the PR-diff gate.
No shared-module extraction here — that is tracked separately in #4608.
JSONbored added a commit that referenced this pull request Jul 10, 2026
…ds (#4604) (#4628)

content-lane/security-scan.ts had drifted from its two siblings
(secrets-scan.ts, review-enrichment's secret-scan.ts): it was missing the
LOWERCASE_HYPHENATED_MOCK_FIXTURE_PATTERN placeholder carve-out added by
#3866, so a fixture value like `token: "mock-response-value"` would
auto-close a legitimate content-lane submission with no human queue to
catch the false positive. It was also missing the voyage_api_key and
firecrawl_api_key patterns added to secrets-scan.ts by #3980, so a real
Voyage/Firecrawl key embedded in a content submission produced no
finding at all.

Ports both fixes verbatim into the content-lane copy and adds both kinds
to its HARD_SECRET_KINDS set for auto-close parity with the PR-diff gate.
No shared-module extraction here — that is tracked separately in #4608.
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

Development

Successfully merging this pull request may close these issues.

1 participant