[Bug] --tls-client-cert flag is not used for API health check, breaking mTLS setups

Open Beginner friendly
#69 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
go
Domain
api, cli, security

Research direction

Start in internal/client/up.go around the healthClient initialization and trace api.InitClient, CheckHealth, and the later TunnelConfig setup. Verify how opts.TlsClientCert is passed through startup API calls; the issue is done when the initial health check and subsequent startup requests work against the described mTLS configuration without weakening server security.

Written by the indexing model from the issue text.

Description

bug
Describe the Bug

The --tls-client-cert flag on pangolin up client is documented and accepted by the CLI, but the certificate is not used for the initial API health check. As a result, when the Pangolin server is fronted by a reverse proxy (e.g. Traefik) configured with clientAuthType: RequireAndVerifyClientCert, the client always fails before the tunnel can be established.

Root cause

In internal/client/up.go (≈ line 270 in 0.8.0):

healthClient, err = api.InitClient(endpoint, "")
...
healthOk, healthErr := healthClient.CheckHealth()
if healthErr != nil || !healthOk {
    err := fmt.Errorf("the server appears to be down: %w", healthErr)
    ...
}

The healthClient is initialized via api.InitClient(endpoint, "") with no reference to opts.TlsClientCert. The TLS client certificate is only attached later, when building the TunnelConfig:

tunnelConfig := olmpkg.TunnelConfig{
    ...
    TlsClientCert: opts.TlsClientCert,
    ...
}

So the CheckHealth() call on the API client always runs without a client certificate. When the Pangolin server enforces mTLS, the TLS handshake fails with tls: certificate required and the CLI exits before the tunnel is ever started.

Environment
  • OS Type & Version: Linux Debian 12
  • Pangolin Version: 1.17.0
  • Traefik Version: v3.6.13
  • Client Version: pangolin up client (CLI 0.8.0) : Tested on 0.6.0 and 0.8.0 (linux_amd64).
To Reproduce
sudo /usr/local/bin/pangolin up \
  --id  \
  --secret  \
  --endpoint https://tunnel.example.com \
  --override-dns=false \
  --tls-client-cert /path/to/client.p12 \
  --log-level debug \
  --attach

Output:

A new version is available: 0.8.0 (current: 0.6.0)
Run 'pangolin update' to update to the latest version
Error: the server appears to be down: server unreachable: Get "https://tunnel.example.com/api/v1": remote error: tls: certificate required
Please check that the server is running and accessible.

Expected Behavior

When --tls-client-cert is provided, the certificate should be used for all TLS handshakes the client makes against the Pangolin server, including the initial CheckHealth() call and any other API calls performed during startup, not only the tunnel runtime.

Workarounds tried

  1. PKCS12 file generated with step certificate p12 ... --no-password --insecure — same error.
  2. Concatenated PEM bundle (cert + key) passed to --tls-client-cert — same error.
  3. Upgrade 0.6.0 → 0.8.0 via pangolin update — same error.

Impact

This makes mTLS-protected Pangolin admin/API endpoints unusable with the CLI client. The only current workaround on the deployment side is to remove mtls-strict from the api-router (and ws-router) entrypoints, which weakens the security posture by exposing the API to anyone who can reach the entrypoint.

Notes

  • The newt client (1.11.0) does not have this problem because its --tls-client-cert-file and --tls-client-key are honored both for the WebSocket connection and the token endpoint.
  • I would be happy to test a patched build if a fix is proposed.
Dominant language
Go
Stars
50
Forks
18
Avg merge
2d 8h
Merged PRs (30d)
7

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from fosrl/cli

All issues in fosrl/cli

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.