Skip to content

fix(gateway): add shared-secret fallback to trusted-proxy auth dispatcher#1

Closed
dashed wants to merge 2 commits intofix/trusted-proxy-device-pairingfrom
fix/trusted-proxy-auth-fallback
Closed

fix(gateway): add shared-secret fallback to trusted-proxy auth dispatcher#1
dashed wants to merge 2 commits intofix/trusted-proxy-device-pairingfrom
fix/trusted-proxy-auth-fallback

Conversation

@dashed
Copy link
Copy Markdown
Owner

@dashed dashed commented Feb 16, 2026

Summary

Stacked on openclaw#17705 — review/merge that PR first. Once merged, this PR's changes should be re-targeted to main on upstream.

The gateway's authorizeGatewayConnect dispatcher treats trusted-proxy as a single-mode gate: when proxy auth fails (e.g. internal services connecting directly without the reverse proxy), the function early-returns before reaching the shared-secret (token/password) or Tailscale code paths. This breaks all internal consumers — node host, CLI RPC, ACP, TUI, agent tools, etc.

This PR adds an inline shared-secret fallback within the trusted-proxy block:

  • When proxy auth fails and a token/password is configured, attempt shared-secret auth before returning failure
  • Rate-limit fallback attempts using the existing AuthRateLimiter
  • Preserve proxy auth priority (successful proxy auth still short-circuits)
  • Fix allowTailscale default to not exclude trusted-proxy mode

Changes

  • src/gateway/auth.ts: Move rate-limiter/IP resolution before trusted-proxy block; add token and password fallback with rate limiting when proxy auth fails; fix allowTailscale default condition
  • src/gateway/auth.test.ts: 9 new unit tests for the fallback path (success, rejection, rate limiting, priority)
  • src/gateway/server.auth.e2e.test.ts: 3 new e2e tests for internal connections with token fallback + device identity

Connection flow (after fix)

Client connects to gateway (mode=trusted-proxy)
├─ From trusted proxy with user header? → ✅ Authenticated (trusted-proxy)
├─ Proxy auth failed, token/password configured?
│  ├─ Rate-limited? → ❌ Rejected (rate_limited)
│  ├─ Valid token? → ✅ Authenticated (token) → device-pairing works
│  ├─ Valid password? → ✅ Authenticated (password) → device-pairing works
│  └─ No match → ❌ Original proxy failure reason
└─ No fallback credentials configured → ❌ Original proxy failure reason

Related Issues

Test Plan

  • 9 unit tests for shared-secret fallback (proxy success unchanged, token/password fallback, rejection, rate limiting, priority)
  • 3 e2e tests for internal connections (token + device identity, token + no device, proxy priority)
  • All existing 30 unit tests pass
  • All existing 33 e2e tests pass
  • oxlint — 0 errors
  • oxfmt — clean
  • tsgo — clean

…cher

When auth.mode is "trusted-proxy" and proxy auth fails (e.g. internal
connections that bypass the reverse proxy), fall back to token/password
credentials if configured. This allows CLI, node hosts, ACP, and other
internal services to authenticate directly while external users
authenticate via the proxy.

Also enable the tailscale overlay for trusted-proxy mode by removing the
mode exclusion from the allowTailscale default.
Add 9 unit tests covering fallback behavior: proxy success unchanged,
token/password fallback on valid credentials, rejection on mismatch,
no-fallback when server credentials unconfigured, rate limiting on
fallback attempts, and proxy-takes-priority when both are available.

Add 3 e2e tests covering internal connection scenarios: token auth with
device identity, token auth without device identity (canSkipDevice),
and proxy connection priority over token fallback.
@github-actions
Copy link
Copy Markdown

⚠️ Formal models conformance drift detected

The formal models extracted constants (generated/*) do not match this openclaw PR.

This check is informational (not blocking merges yet).
See the formal-models-conformance-drift artifact for the diff.

If this change is intentional, follow up by updating the formal models repo or regenerating the extracted artifacts there.

@dashed dashed closed this Feb 16, 2026
dashed pushed a commit that referenced this pull request Mar 2, 2026
… and docs (openclaw#16761)

Add inline file attachment support for sessions_spawn (subagent runtime only):

- Schema: attachments[] (name, content, encoding, mimeType) and attachAs.mountPath hint
- Materialization: files written to .openclaw/attachments/<uuid>/ with manifest.json
- Validation: strict base64 decode, filename checks, size limits, duplicate detection
- Transcript redaction: sanitizeToolCallInputs redacts attachment content from persisted transcripts
- Lifecycle cleanup: safeRemoveAttachmentsDir with symlink-safe path containment check
- Config: tools.sessions_spawn.attachments (enabled, maxFiles, maxFileBytes, maxTotalBytes, retainOnSessionKeep)
- Registry: attachmentsDir/attachmentsRootDir/retainAttachmentsOnKeep on SubagentRunRecord
- ACP rejection: attachments rejected for runtime=acp with clear error message
- Docs: updated tools/index.md, concepts/session-tool.md, configuration-reference.md
- Tests: 85 new/updated tests across 5 test files

Fixes:
- Guard fs.rm in materialization catch block with try/catch (review concern #1)
- Remove unreachable fallback in safeRemoveAttachmentsDir (review concern #7)
- Move attachment cleanup out of retry path to avoid timing issues with announce loop

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
Co-authored-by: napetrov <napetrov@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant