Skip to content

access tcp/ssh: service token ignored, browser auth attempted per-connection, TCP banner not delivered (2026.6.0 regression from 2026.5.1) #1674

Description

@johnmcelroy-ai

Summary

cloudflared access tcp (and access ssh) in 2026.6.0 ignores all headless auth credentials (service-token-id/secret flags, $TUNNEL_SERVICE_TOKEN_ID/SECRET env vars, -H header injection) and falls through to interactive browser auth on every new TCP connection. SSH banner never reaches the client; connection times out.

This is a regression from 2026.5.1, which honored service tokens correctly and never attempted browser auth when credentials were provided.

Environment

  • cloudflared client: 2026.6.0 (built 2026-06-08T18:16:09Z) on macOS arm64 (Apple Silicon)
  • cloudflared daemon: 2026.5.1 (remote tunnel daemon, working)
  • Tunnel mode: dashboard-managed (remote config), single hostname route <host>.example.com → ssh://localhost:2222
  • Access app: self-hosted, free tier, policy includes Emails + Service Auth

Steps to reproduce

  1. Create a CF Access Service Token + add to Access app policy as Include: Service Auth.
  2. Add hostname route in tunnel: <host>.example.com → ssh://localhost:2222.
  3. On client (where 2026.6.0 is running):
    export TUNNEL_SERVICE_TOKEN_ID="<id>.access"
    export TUNNEL_SERVICE_TOKEN_SECRET="<secret>"
    cloudflared access tcp \
      --hostname <host>.example.com \
      --url 127.0.0.1:2229 \
      --service-token-id "$TUNNEL_SERVICE_TOKEN_ID" \
      --service-token-secret "$TUNNEL_SERVICE_TOKEN_SECRET"
    
  4. From another shell: ssh -p 2229 user@127.0.0.1

Expected behavior (2026.5.1)

  • cloudflared authenticates against CF Access using the service token credentials
  • WebSocket established to CF edge, no browser prompt
  • TCP bytes (SSH banner, kex, payload) flow bidirectionally
  • SSH login succeeds

Actual behavior (2026.6.0)

  • cloudflared starts: INF Start Websocket listener host=127.0.0.1:2229 (looks fine)
  • On the first SSH connection attempt, cloudflared logs:
    A browser window should have opened at the following URL:
    https://<host>.example.com/cdn-cgi/access/cli?...
    
  • SSH client never receives a banner. Connection timed out during banner exchange.
  • Verified the service-token flag values DID reach cloudflared (--help shows them as defaults when env vars set).
  • Verified service token works for HTTP auth (curl -H "CF-Access-Client-Id:..." -H "CF-Access-Client-Secret:..." https://<host>.example.com/ returns HTTP 200 with a CF_Authorization cookie set).
  • Header injection via -H flag also attaches at WebSocket upgrade (cloudflared debug log shows Cf-Access-Client-Id + Cf-Access-Client-Secret headers in the WebSocket GET — and the WebSocket upgrades to HTTP 101 Switching Protocols), but per-connection auth still kicks off browser flow.
  • Cycle repeats on every TCP connection attempt.

Workaround

Downgrade to cloudflared 2026.5.1. No client-side workaround in 2026.6.0 has been found.

Repro environment context

  • macOS LaunchAgent (background process, cannot complete browser flow) calling cloudflared per-connection: broken.
  • Interactive foreground SSH: also broken (same per-connection retry on browser flow).
  • HTTP curl with service-token headers to same hostname: works (HTTP 200).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions