Skip to content

Fix public repo-stats endpoint hardcoded to jsonbored/gittensory only #4612

Description

@JSONbored

Context

Part of the review-stack architecture audit (parent epic — hardcoding dimension). This is the clearest
"a self-hoster deploying their own fork silently can't use a generic-looking route" finding.

src/github/public.ts:54-55,153:

const PUBLIC_REPO_STATS_OWNER = "jsonbored";
const PUBLIC_REPO_STATS_REPO = "gittensory";
...
if (normalizedOwnerName !== PUBLIC_REPO_STATS_OWNER || normalizedRepoName !== PUBLIC_REPO_STATS_REPO)
  throw new Error("invalid_github_repo");

Caller: src/api/routes.ts:962-971 mounts this as GET /v1/public/github/repos/:owner/:repo/stats — a
generically-parameterized route (unauthenticated, publicly cached) that looks like it serves stats
for any repo, but the implementation hard-rejects everything except one literal repo. Compare the sibling
route one block below it, /v1/public/repos/:owner/:repo/badge.svg
(loadPublicRepoBadge, routes.ts:976-988), which correctly works for any installed repo, gated
only by a per-repo opt-in setting — not a hardcoded owner/repo allowlist. A self-hoster deploying their
own fork and hitting their own /v1/public/github/repos/<their-owner>/<their-repo>/stats gets a hard 400
invalid_github_repo, even though the URL shape and route wiring say this should be generic.

Fix

Replace the two constants with an env-driven allowlist (or drop the allowlist and validate only
owner/repo syntax, matching badge.svg's pattern), e.g. PUBLIC_REPO_STATS_ALLOWLIST
(comma-separated owner/repo, empty = allow any — mirroring GITTENSORY_PUBLIC_STATS_REPOS's shape in
src/review/public-stats.ts).

Acceptance criteria

  • A self-hoster can configure their own repo(s) for this endpoint without code changes.
  • Default behavior for existing deployments (JSONbored's own) is unchanged.
  • Regression test covering both the allowlisted and rejected cases.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

Status
Done

Relationships

None yet

Development

No branches or pull requests

Issue actions