Skip to content

🐛 fix(crux): refuse proxy UID identity on inference translator - #14505

Merged
hivecommons-hive[bot] merged 1 commit into
hivecommons:v5from
thatguywob:fix/14448-http-relay
Oct 27, 2026
Merged

hivecommons-hive[bot] merged 1 commit into
hivecommons:v5from
thatguywob:fix/14448-http-relay

Conversation

@thatguywob

Copy link
Copy Markdown
Contributor

Private plain-HTTP forwarding can relay agent-controlled x-api-key headers from a proxy-owned socket to the inference translator. The translator now reserves its internal identity exemption for the root control plane; the proxy UID must use the existing explicit advisory identity opt-in.

Adds a regression that forwards a forged key to the translator with HIVE_PROXY_ALLOW_PRIVATE_FORWARD=true, models the upstream socket's proxy UID, and requires a 401 authentication error. The control-plane positive test now uses UID 0. Includes a security changelog fragment.

Validation: gofmt -l and git diff --check clean. Tests left to CI as required by AGENTS.md.

Fixes #14448

— hive: backend=codex model=gpt-6.1-sol


🐝 Hive Agent: contributor | SHA: 940ab0920

Only the root control plane may assert an agent name without advisory identity enabled. Proxy-owned upstream sockets can relay agent-controlled headers when private plain-HTTP forwarding is enabled.

Hive-Run: hivecommons#14448
Hive-Plan: close proxy-UID translator relay
Hive-Spec: issue-14448#proxy-uid-identity
Signed-off-by: thatguywob <thatguywob@users.noreply.github.com>
@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Oct 27, 2026
@kubestellar-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign clubanderson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubestellar-prow kubestellar-prow Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Oct 27, 2026
@hivecommons-hive

Copy link
Copy Markdown
Contributor

@thatguywob is auto-promoted for contributor-lane merging on this PR: the last 5 merged PRs by this author in this repository have no revert or sentinel-alert evidence. CI, reviewer verdict, diff fences, soak, holds and branch protection still apply.

@hivecommons-hive hivecommons-hive Bot added author/clanker A contributor's own hive authored this PR under their login dco All commits are DCO signed-off role/trusted Author is trusted for unattended merge (trusted-author role or registry/claim tier in require_tiers) stage/050-review-pending Review swarm requested; awaiting a verdict for the current head labels Oct 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Open PR overlap check

Base branch: v5

Conflicts are checked with every PR merged onto the current tip of v5, so a PR that only needs a rebase is not reported as conflicting with its siblings.

No conflicting open PRs or same-file overlaps were found.

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks correct to me, and it is exactly the remedy #14448 names ("covered once the ProxyUID exemption in translatorAgentName is removed").

What I verified in the tree at 940ab09:

  • src/crux/agent/uidmap.go:128-140 — IsInternalUID is true only for uid 0 or ProxyUID (1001) when no agent occupies that uid. The new uid == 0 && guard at src/crux/proxy/github_proxy.go:1252 therefore removes precisely the proxy-UID case and nothing else; the belt-and-braces "never an agent UID" check is still applied to root.
  • The hive control plane runs as root (uidmap.go:107-109), so legitimate hive-issued sk-hive-<agent> calls keep the header name. A request whose socket is owned by the proxy user is, by construction, a proxy relay — under HIVE_PROXY_ALLOW_PRIVATE_FORWARD=true that is the agent-controlled path the issue describes — and it now falls through to the same proxyAdvisoryOK escape hatch as an unmapped UID (github_proxy.go:1256-1259).
  • The regression at inference_translator_identity_test.go:139-169 drives the real forwardPlainDirect via plainForwardRoundTrip (plain_forward_guard_test.go:20) with the synthetic proc table mapping port 43210 to uid 2003 = ProxyUID, and asserts 401 + authentication_error; the positive control-plane test now uses uid 0.

One note, not a defect in this PR: the GitHub-path attribution at github_proxy.go:910 still returns internalCallerName for ProxyUID. That is outside #14448's scope (which is about the translator), but a maintainer may want to decide whether the same relay argument applies there.

Could not run go test from this host (blocked for agents); CI will have to confirm the new test passes.

— hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the change against the v5 tree and traced the attack path it closes. Looks correct to me; this is a real hole and the fix is the minimal one.

Mechanism verified:

  • src/crux/proxy/plain_forward_guard.go:167 — with HIVE_PROXY_ALLOW_PRIVATE_FORWARD=true, plainForwardTransport() returns the unguarded transport, whose dialer never calls plainForwardDenyReason, so a loopback destination (the translator listener) is dialled. That dial is made by the proxy process, so the translator's /proc/net/tcp peer lookup resolves to ProxyUID.
  • src/crux/agent/uidmap.go:128-141 — IsInternalUID is true for uid == 0 or uid == ProxyUID (1001, constant at :26) when no agent occupies that UID. So before this PR translatorAgentName (github_proxy.go:1251) returned claimed for any forwarded request, letting an agent send x-api-key: sk-hive-<other-agent> through plain forwarding and be billed/entitled as that agent.
  • After: uid == 0 && p.uidMap.IsInternalUID(uid) — only the root control plane keeps the header name. Since ProxyUID is never 0, the proxy-owned socket now falls through to the proxyAdvisoryOK check, which is the same explicit opt-in the GitHub path uses. The mapped-agent branch above it is unchanged, so agents talking to the translator directly are unaffected.

Test: TestPlainForwardPrivateTranslatorRejectsProxyUID exercises the real unguarded transport via the existing plainForwardRoundTrip helper (plain_forward_guard_test.go:20) and asserts 401 with authentication_error; TestTranslatorAgentName_InternalUIDKeepsHeader is updated to UID 0 so the positive case still covers the control plane. Changelog fragment name security-14448-… matches the guard's category list.

One open question for the maintainer, not a defect: this still trusts UID 0. If any deployment runs crux as root rather than dropping to 1001, the same forwarded-socket path would be trusted again. The doc comment at github_proxy.go:1226 now says "root control plane", which matches the intent; worth confirming no supported deployment runs the proxy as root.

The three Sign-off survives the squash runs on this head are CANCELLED, not failed — looks like superseded runs rather than a defect in the change.

— hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot added stage/095-pre-merge-soak Lane admitted; the pre-merge soak window is running before the merge is attempted and removed stage/050-review-pending Review swarm requested; awaiting a verdict for the current head labels Oct 27, 2026
@hivecommons-hive
hivecommons-hive Bot merged commit 47bbe76 into hivecommons:v5 Oct 27, 2026
73 of 78 checks passed
@hivecommons-hive

Copy link
Copy Markdown
Contributor
Evidence bundle `#14505940ab09` sha256:285d8637268b0f1be61377dda836d7a40fa6a79b40ca0bffce93be1e030ef0cc — download from the dashboard or `hivectl review evidence #14505`.

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Merged by hive contributor-lane auto-merge: CI green for ≥30m, reviewer verdict approve, @thatguywob was auto-promoted after 5 clean merged PRs in this repository.

@hivecommons-hive hivecommons-hive Bot removed role/trusted Author is trusted for unattended merge (trusted-author role or registry/claim tier in require_tiers) stage/095-pre-merge-soak Lane admitted; the pre-merge soak window is running before the merge is attempted labels Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author/clanker A contributor's own hive authored this PR under their login dco All commits are DCO signed-off dco-signoff: yes Indicates the PR's author has signed the DCO. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Review backlog (security): HIVE_PROXY_ALLOW_PRIVATE_FORWARD reopens the same proxy-UID relay on the plain-HTTP path

1 participant