fix(gateway): reject no-auth tailscale exposure#87286
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed May 27, 2026, 9:06 AM ET / 13:06 UTC. Summary PR surface: Source +61, Tests +81. Total +142 across 7 files. Reproducibility: yes. source-reproducible: current main lets Tailscale Serve keep the gateway on loopback while Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance: Risk before merge
Maintainer options:
Next step before merge Security Review detailsBest possible solution: Land the shared fail-closed policy after maintainer security/compatibility signoff and redacted real rejection proof, then close #50630 and supersede #50631. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main lets Tailscale Serve keep the gateway on loopback while Is this the best way to solve the issue? Yes, the proposed boundary is the maintainable fix shape: one shared policy applied to config validation, service install preflight, and runtime startup while preserving loopback-only no-auth. The remaining blocker is merge proof and maintainer acceptance of the fail-closed upgrade behavior, not a code finding. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 8e5183c60d4a. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +61, Tests +81. Total +142 across 7 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
e46da14 to
0b306e8
Compare
|
ClawSweeper PR egg 🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat. Where did the egg go?
|
|
Landed via squash as dc5954b. Proof:
|
|
Excellent hardening pass. The strongest part here is that the policy was enforced consistently across validation, install-token preflight, and runtime startup instead of patching only the runtime path. That closes the class of “configuration accepted but later unsafe in execution” issues very cleanly. Also smart to preserve the loopback-only I especially liked the explicit regression coverage around overrides and service-plan generation — those edge paths are exactly where auth-policy drift tends to reappear later. |
Summary
Fixes #50630.
Replaces the stale/conflicting runtime-only fix in #50631.
This rejects explicit
gateway.auth.mode=nonewhenever the gateway is exposed through Tailscale Serve or Funnel. The policy is shared across config validation, install-token preflight, and runtime startup so setup paths fail before writing/accepting a service plan, while loopback-only no-auth remains valid.Verification
Behavior addressed:
gateway.auth.mode=noneplusgateway.tailscale.mode=serveno longer reaches a running gateway exposed to the Tailnet; config and install preflight reject it before daemon startup, and runtime startup also fails closed.Real environment tested: No live Tailnet device run. This patch is preflight/runtime validation; the verified behavior is config rejection and startup/install blocking.
Exact steps or command run after this patch:
node scripts/run-vitest.mjs src/config/config.gateway-tailscale-bind.test.ts src/gateway/server-runtime-config.test.ts src/commands/doctor-gateway-auth-token.test.tspnpm check:changedvia Blacksmith Testboxtbx_01ksmpwc2fqfv5s9zpw3syvzzd, GitHub Actions run26511438060.agents/skills/autoreview/scripts/autoreview --mode localEvidence after fix:
gateway.auth.mode.Observed result after fix: focused Vitest passed, Testbox
check:changedexited 0, autoreview returned clean with no accepted/actionable findings.What was not tested: real Tailscale Serve/Funnel network access from another Tailnet device.
Risk
Did user-visible behavior change? Yes.
Did config, environment, or migration behavior change? Yes.
Did security, auth, secrets, network, or tool execution behavior change? Yes.
Existing explicit no-auth Tailscale exposure now fails closed. Loopback-only
gateway.auth.mode=noneremains accepted.