Skip to content

fix(miner-ui): restrict run-state API to loopback#4982

Open
JSONbored wants to merge 1 commit into
mainfrom
codex/fix-unauthenticated-run-state-api-vulnerability
Open

fix(miner-ui): restrict run-state API to loopback#4982
JSONbored wants to merge 1 commit into
mainfrom
codex/fix-unauthenticated-run-state-api-vulnerability

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Motivation

  • The Vite dev/preview middleware exposed GET /api/run-state unauthenticated, leaking local miner run-state rows to any client that can reach the dev server.
  • The endpoint read from the local SQLite-backed run-state store and could be reached when Vite was bound to a non-loopback host in container/VM/fleet setups, creating an information disclosure risk.

Description

  • Add a loopback-only guard by introducing isLoopbackAddress() and returning 403 for non-loopback remote addresses before loading or touching the local run-state module in apps/gittensory-miner-ui/vite-run-state-api.ts.
  • Wire the Vite middleware to pass req.socket?.remoteAddress into the extracted handler so remote address checks run on dev/preview requests.
  • Add regression tests in apps/gittensory-miner-ui/src/run-state-api.test.ts that assert non-loopback clients are denied without loading the store and that IPv6-mapped loopback addresses are allowed.
  • Preserve the existing fresh-install fast path (serve [] if the DB file is absent) and the read-only behavior for loopback clients.

Testing

  • Ran the endpoint unit tests with npm --workspace @jsonbored/gittensory-miner-ui exec -- vitest run src/run-state-api.test.ts, and all tests passed.
  • Type checking with npm --workspace @jsonbored/gittensory-miner-ui run typecheck completed successfully and eslint ran without errors (only existing warnings surfaced) via npm --workspace @jsonbored/gittensory-miner-ui run lint.
  • git diff --check produced no trailing whitespace or conflict markers, while npm audit --audit-level=moderate failed due to the registry returning 403 Forbidden (network/registry issue), not a local dependency advisory.

Codex Task

@superagent-security

Copy link
Copy Markdown
Contributor

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

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

gittensory-orb Bot commented Jul 11, 2026

Copy link
Copy Markdown

Warning

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

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-11 17:26:54 UTC

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

⏸️ 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 closes a real information-disclosure hole: the Vite dev/preview middleware's GET /api/run-state endpoint served local miner run-state rows to any client that could reach the dev server, with no origin check. The fix adds isLoopbackAddress() and returns 403 for non-loopback remote addresses before the run-state module is even imported, which correctly avoids the lazy-init write-on-read-only-endpoint concern noted in the existing code comments. The change is narrowly scoped, mirrors the existing handler-factored-out-for-testing pattern used by the sibling portfolio-queue endpoint, and is well covered by new regression tests for the denial path (verifying the store loader is never called) and for IPv6-mapped loopback.

Nits — 5 non-blocking
  • apps/gittensory-miner-ui/vite-run-state-api.ts:26 — isLoopbackAddress returns true when remoteAddress is undefined, which fail-opens if req.socket is ever absent (e.g. a stripped/mocked socket in some deployment shape); worth a comment noting this is intentional for the case where Node guarantees remoteAddress is always populated for a live TCP connection.
  • apps/gittensory-miner-ui/vite-run-state-api.ts:31 — the `remoteAddress.startsWith("127.")` branch (e.g. 127.0.0.2) is never exercised by the new tests since the only 127.x fixture used is 127.0.0.1, which is already caught by the exact `=== "127.0.0.1"` check one line above; add a case like `"127.0.0.2"` to actually cover that branch.
  • apps/gittensory-miner-ui/vite-run-state-api.ts:50 — the 403 status is a bare literal; naming it (e.g. `const LOOPBACK_ONLY_STATUS = 403`) would match the light self-documentation style already used elsewhere in this file.
  • Add a test asserting the fail-open branch for remoteAddress === undefined is intentional (e.g. call handleRunStateRequest without a remoteAddress arg and assert 200), since right now that path is only incidentally exercised by the unrelated 500-path test.
  • Consider extending isLoopbackAddress to cover the general ::ffff:127.0.0.0/8 mapped range rather than only the single ::ffff:127.0.0.1 literal, for parity with the plain-IPv4 startsWith("127.") handling.

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: 45 registered-repo PR(s), 37 merged, 414 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 45 PR(s), 414 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Improvement ✅ Minor risk: clean · value: minor — Code changes are accompanied by test evidence.
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: not available
  • Official Gittensor activity: 45 PR(s), 414 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.
[BETA] Chat with Gittensory

Ask Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @gittensory ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @gittensory chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @gittensory mention with a real question is routed to the closest matching read-only command automatically -- no exact syntax required.

Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands

Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before / after /
/ mobile before / (mobile) after / (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

🟩 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

@gittensory-orb gittensory-orb Bot added the manual-review Gittensor contributor context label Jul 11, 2026
@JSONbored JSONbored force-pushed the codex/fix-unauthenticated-run-state-api-vulnerability branch from 18ee35a to a663fef Compare July 11, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

aardvark codex 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