Skip to content

orb(redaction): one shared token-redaction pattern — three surfaces miss ghs_/gho_/ghu_/ghr_ #9697

Description

@JSONbored

⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.

Context

Four hand-written token-redaction patterns guard public-facing text in src/services/**, and every one of them misses something another one catches:

Site Pattern Misses
src/services/miner-dashboard-recommendations.ts:49 ghp_, github_pat_, gts_, orbenr_, orbsec_, glpat-, sk- gho_ ghu_ ghs_ ghr_, xox*-
src/services/control-panel-roles.ts:304 same list gho_ ghu_ ghs_ ghr_, xox*-
src/services/weekly-value-report.ts:414 same list + xox[baprs]- gho_ ghu_ ghs_ ghr_
src/services/score-breakdown.ts:15, src/services/agent-action-explanation-card.ts:15 github_pat_, gh[pousr]_ + path gts_ orbenr_ orbsec_ glpat- sk- xox*-

The gh[pousr]_ class is the correct one for GitHub — it is what src/review/secret-patterns.ts:28 (/\bgh[pousr]_[A-Za-z0-9]{20,}\b/) and src/review/content-lane/registry-logic.ts:110 use. The three surfaces that only match ghp_ therefore pass ghs_... through verbatim — and ghs_ is the GitHub App installation access token this Worker itself mints on every pass via createInstallationToken. Input "token ghs_AAAAAAAAAAAAAAAAAAAAAAAA leaked" through sanitizePublicText (miner-dashboard-recommendations.ts:386-393) comes out unchanged; the same string with ghp_ comes out as "token private context leaked".

This is drift the files already know about in the adjacent line. miner-dashboard-recommendations.ts:46-47 says of the path pattern directly above: "Compose the roots from the canonical PUBLIC_LOCAL_PATH_INLINE in redaction.ts (so this surface cannot drift)" — while leaving the token pattern on line 49 a local literal. score-breakdown.ts:9-10 names miner-dashboard-recommendations.ts as following the same established pattern; it does not.

Requirements

  • Add to src/signals/redaction.ts (the module that already owns PUBLIC_LOCAL_PATH_INLINE / PUBLIC_LOCAL_PATH_SCRUB_PATTERN / PUBLIC_UNSAFE_PATTERN) a single exported source-of-truth:
    • export const PUBLIC_TOKEN_INLINE: string — the alternation of every prefix, being the union of all four current lists: gh[pousr]_, github_pat_, gts_, orbenr_, orbsec_, glpat-, sk-, xox[baprs]-.
    • export function publicTokenPattern(): RegExp — returns a fresh RegExp built from PUBLIC_TOKEN_INLINE with the g flag on each call, so no module-level /g object is ever shared across call sites.
  • Rewrite all five sites to build their pattern from PUBLIC_TOKEN_INLINE (composing with their own trailing character class / path alternation as they do today for the path root), removing every hand-written prefix literal: miner-dashboard-recommendations.ts:49, control-panel-roles.ts:304, weekly-value-report.ts:414, score-breakdown.ts:15, agent-action-explanation-card.ts:15.
  • Each site keeps its own replacement string exactly as today ("private context", "<redacted-token>") — this issue unifies what is matched, not what it is replaced with.
  • After the change, the literal strings ghp_ and gh[pousr]_ must not appear in any file under src/services/.

⚠️ Required pattern: PUBLIC_LOCAL_PATH_INLINE in src/signals/redaction.ts and the way miner-dashboard-recommendations.ts:46-48 already composes its LOCAL_PATH from it is the exact precedent — one exported inline root, composed per-surface. It does NOT satisfy this issue to fix only the ghs_ gap by editing three literals in place, leaving four divergent lists; to export a single shared module-level RegExp with the g flag (a shared stateful /g object would carry lastIndex across surfaces); or to change any site's replacement token or its surrounding forbidden-term checks.

Deliverables

  • PUBLIC_TOKEN_INLINE and publicTokenPattern() exist in src/signals/redaction.ts and are the only place any token prefix literal appears under src/ outside src/review/secret-patterns.ts (grep-verifiable for ghp_, gts_, orbenr_, orbsec_, glpat-, xox).
  • Named regression test: sanitizePublicText in miner-dashboard-recommendations.ts redacts a ghs_-prefixed token — asserted as a REGRESSION: case naming the installation-token gap.
  • sanitizeRoleText (control-panel-roles.ts) redacts ghs_, gho_, ghu_, ghr_ and an xoxb- token — one it.each over every prefix in PUBLIC_TOKEN_INLINE.
  • The weekly-value-report.ts, score-breakdown.ts and agent-action-explanation-card.ts sanitizers each redact every prefix in PUBLIC_TOKEN_INLINE — one it.each per file.
  • publicTokenPattern() returns a new object on each call and a repeated .replace() on the same input is idempotent (guards against a shared-lastIndex regression) — asserted in the redaction unit test.

All Deliverables above are required in a single PR. A PR that satisfies only some of them — for example adding the shared constant and adopting it in two of the five sites — does not resolve this issue.

Test Coverage Requirements

99%+ Codecov patch coverage, branch-counted, on src/**. All six touched files are inside coverage.include. Because the change is a regex, coverage alone is insufficient: every prefix in PUBLIC_TOKEN_INLINE must be exercised at every call site via it.each, plus at least one non-token string per site asserting it is left unmodified.

Expected Outcome

A GitHub App installation token (ghs_), OAuth token (gho_), user token (ghu_), refresh token (ghr_) or Slack token cannot reach a public dashboard string, role summary, weekly report, score breakdown, or explanation card. One list of token prefixes exists, so adding a new provider's prefix updates every surface at once.

Links & Resources

src/signals/redaction.ts; src/services/miner-dashboard-recommendations.ts:44-49, :386-393; src/services/control-panel-roles.ts:301-310; src/services/weekly-value-report.ts:414; src/services/score-breakdown.ts:9-15; src/services/agent-action-explanation-card.ts:15; src/review/secret-patterns.ts:28.

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions