Skip to content

fix(scoring): fail closed on a semantically-garbage 200 constants body - #1235

Merged
JSONbored merged 1 commit into
mainfrom
fix/scoring-snapshot-validation
Jun 24, 2026
Merged

fix(scoring): fail closed on a semantically-garbage 200 constants body#1235
JSONbored merged 1 commit into
mainfrom
fix/scoring-snapshot-validation

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

Closes audit finding 3.6 (+ the drift-ref §4 item). #1192 pinned the upstream constants fetch and froze last-good on a non-2xx response — but a 200 with a semantically-garbage body (HTML interstitial, Git-LFS pointer, or truncated file) parsed to ~0 recognized constants and silently reverted every constant to DEFAULT_SCORING_CONSTANTS while keeping sourceKind="raw-github", moving live scoring with no staleness signal.

Fix

  • Sanity floor: a 200 constants body must parse at least MIN_RECOGNIZED_SCORING_CONSTANTS (8) recognized constants to be trusted. Below that it's handled exactly like a failed fetch — freeze the last-good snapshot, or bootstrap to a clearly-labeled "fallback" (never a deceptive "raw-github") when there's no verified last-good.
  • Unpinned-ref warning: surfaces a warning when the upstream ref can't be resolved to an immutable SHA (the fetch falls back to the mutable ref).
  • Drift source ref: records the resolved fetchRef in the drift-sync source rather than the raw mutable ref.

Scope

  • Backend only (src/scoring/model.ts); no schema change; no migration; refresh is cron/internal-token gated (not contributor-reachable) — defense-in-depth

Validation

  • npm run test:ci — full gate green
  • npm audit --audit-level=moderate — 0 vulnerabilities
  • New tests: LFS-pointer body freezes last-good; HTML body with no last-good → fallback. Updated existing fixtures to realistic constants bodies (≥ the floor)
  • Every changed line + branch covered

Safety

  • No secrets / wallets / hotkeys / trust scores / reward values; fails toward freezing last-good
  • No site/ / CNAME / lovable

#1192 pinned the upstream constants fetch and froze last-good on a non-2xx
response, but a 200 with a semantically-garbage body — an HTML interstitial,
a Git-LFS pointer, or a truncated file — parsed to ~0 recognized constants
and silently reverted every constant to DEFAULT_SCORING_CONSTANTS while
keeping sourceKind="raw-github", moving live scoring with no staleness
signal.

The refresh now applies a sanity floor: a 200 body must parse at least
MIN_RECOGNIZED_SCORING_CONSTANTS recognized constants to be trusted.
Otherwise it is handled exactly like a failed fetch — freeze the last-good
snapshot, or bootstrap to a clearly-labeled "fallback" when there is no
verified last-good. Also surfaces a warning when the upstream ref can't be
resolved to an immutable SHA (the fetch falls back to the mutable ref), and
records the resolved fetch ref in the drift-sync source.
@dosubot dosubot Bot added the size:M label Jun 24, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

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

@JSONbored JSONbored self-assigned this Jun 24, 2026
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.93%. Comparing base (56edf42) to head (fdd9783).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1235   +/-   ##
=======================================
  Coverage   94.92%   94.93%           
=======================================
  Files         173      173           
  Lines       19643    19650    +7     
  Branches     7062     7067    +5     
=======================================
+ Hits        18647    18654    +7     
  Misses        397      397           
  Partials      599      599           
Files with missing lines Coverage Δ
src/scoring/model.ts 98.11% <100.00%> (+0.13%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored
JSONbored merged commit f058338 into main Jun 24, 2026
17 of 18 checks passed
@JSONbored
JSONbored deleted the fix/scoring-snapshot-validation branch June 24, 2026 12:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant