Repository navigation
v0.26.1
v0.26.1
This release fixes additional security and reliability issues found during a follow-up review.
⚠️ Breaking changes
- Minimum key sizes and supported algorithms:
- The built-in PKI rejects CSRs with RSA keys smaller than 2048 bits, RSA keys with an even public exponent or an
exponent smaller than 3,P-224ECDSA keys, the CA's own public key, or unsupported key types. - The SSH certificate authority rejects RSA keys smaller than 2048 bits and refuses to sign the CA's own public key.
- Remote JWKS endpoints (
trustedIssuers) ignore RSA keys smaller than 2048 bits, RSA keys with an even public
exponent or an exponent outside[3, 2^31-1], EC keys on unsupported curves or not on the curve, Ed25519 keys with
an invalid size, and keys whoseuseis notsig.
- The built-in PKI rejects CSRs with RSA keys smaller than 2048 bits, RSA keys with an even public exponent or an
- Built-in PKI:
- The Root CA certificate and delegated OCSP/CRL signing certificates can no longer be revoked through the
certificate management endpoint (?get=revokeCert). - Delegated OCSP/CRL responder certificates are now issued with
IsCA: false(instead ofIsCA: true), and CRLs
are signed directly with the Root CA key. - If the Root CA certificate doesn't have the
CRLSignkey usage, it is re-issued at startup with the same key,
subject, andSubjectKeyId, but a new serial number and fingerprint. The old certificate is replaced in the
list of issued certificates, and a warning with the old and new fingerprints is logged. Clients that pin the CA
certificate's fingerprint must be updated. - The OCSP responder (
ServeOCSP) rejects OCSP requests that use hash algorithms other than SHA-1, SHA-256,
SHA-384, or SHA-512, and uses the request's hash algorithm forIssuerHashin responses. - Browser-generated OpenPGP keys in the PKI WASM client now use AES-256 and a higher S2K iteration count.
- The Root CA certificate and delegated OCSP/CRL signing certificates can no longer be revoked through the
- OCSP verification (
ocspcacheandtlsclient --ocsp):- Delegated OCSP responder certificates must be within their
NotBefore/NotAftervalidity window. - OCSP responses without
NextUpdateare rejected ifThisUpdateis more than 24 hours old, andThisUpdate
cannot be more than 5 minutes in the future. tlsclient --ocspverifies that stapled OCSP response serial numbers match the certificate, andocspcachefails
chain verification when constructing an OCSP request or parsing anOCSPServerURL fails.
- Delegated OCSP responder certificates must be within their
- Cookies and headers:
- TLSPROXY's internal cookies (
TLSPROXYAUTH,TLSPROXYIDTOKEN,TLSPROXYNONCE,TLSPROXYSAMLNONCE, and
__tlsproxySid) are stripped from theCookieheader before forwarding requests to backends.TLSPROXYIDTOKEN
is only forwarded whengenerateIdTokensis set on the backend'sssoconfiguration and the token is valid. - Client
Connectionheaders can no longer cause the proxy to strip headers it sets (X-Forwarded-*,
X-tlsproxy-user-id, orforwardHttpHeaders). X-Forwarded-Client-Certis now populated on HTTP requests served over raw QUIC streams (ALPN other thanh3).- Logging out (
/.sso/logout) rotates the__tlsproxySidsession ID cookie. - Built-in HTML pages now include
X-Frame-Options: DENYandContent-Security-Policy: frame-ancestors 'none'.
- TLSPROXY's internal cookies (
- Local OIDC server and identity providers:
rewriteRuleson the local OIDC server are rejected at config validation if they would overwrite reserved
JWT/OIDC claims (sub,iss,aud,exp,iat,nbf,jti,client_id,scope,groups,nonce,
proxyauth,provider,hhash,sid,th,depth), and extra claims from identity providers can no longer
overwritesub,iss,aud,exp,
iat,nbf,jti,email,scope,client_id,groups,proxyauth,provider,hhash,sid,th, or
non-integerdepth.- The device verification endpoint only copies standard OIDC profile claims (
sub,email,email_verified,
name,family_name,given_name,middle_name,nickname,preferred_username,profile,picture,
website,gender,birthdate,zoneinfo,locale) andsidinto device authorization sessions instead of
internal session claims.
- Passkeys:
- When a passkey provider is shared across multiple backends or SSO rules, ACLs from all rules are merged and any
open rule (acl: null) allows all authenticated users to register passkeys. /.sso/passkeysand/.well-known/passkey-endpointsare now registered on a passkey provider's callback host
even when that backend uses a different identity provider.- Passkey registration and assertion verification require RSA keys of at least 2048 bits with an odd public
exponent>= 3, credential IDs between 16 and 1023 bytes that are unique across users, and a matching
rpIdHashon assertions.
- When a passkey provider is shared across multiple backends or SSO rules, ACLs from all rules are merged and any
- Rate and bandwidth limits:
forwardRateLimitis now enforced on every HTTP request over keep-alive HTTP/1.1, HTTP/2, and HTTP/3
connections, not only when establishing a new connection.bwLimitsnames are matched case-insensitively on backends, and bandwidth limits also apply to QUIC datagrams.
- Metrics and profiling:
runtime.MemProfileRateis no longer set to1on startup; memory profiling uses Go's default sampling rate.forwardHttpHeadersvalues containing${JWT:...}expressions are redacted on the metrics config page.
🔒 Security fixes
- Remote JWKS keys were cached by
kidacross alltrustedIssuers, allowing one trusted issuer to override
another issuer's signing key with the samekid. - Unvalidated
TLSPROXYIDTOKENand internal session/nonce cookies were forwarded to backends. - A client could list
X-Forwarded-For,X-tlsproxy-user-id, or customforwardHttpHeadersin theConnection
header to have the proxy strip them before forwarding the request. - Reserved JWT claims could be overwritten via OIDC
rewriteRulesor identity provider extra claims. - The local OIDC server's device verification endpoint copied internal session claims (
provider,th,depth)
into device authorization sessions. - Passkey assertions did not verify
rpIdHash, passkey registration did not check for duplicate credential IDs
across users, andRefreshIDdid not verify the user's email orRefreshInterval. - Re-authorizing connections after a config reload did not close connections without a client certificate when
clientAuthhad noacl. checkIPwas not enforced before the TLS handshake on QUIC connections.
🔧 Misc
- Hardening and bug fixes:
- Bypass CSRF checks on the PKI OCSP (
POST) and local OIDC/userinfo(POST) endpoints, and check the HTTP
status code before parsing fetched OCSP responses. - Fix
GETOCSP requests when the base64-encoded request contains/or%2F, and stop cachingocsp.Unknown
responses. - Enforce
localHandlerscopes inenforceSSOPolicyeven when no SSO rule matches. - Recognize certificates issued by a local PKI by the
AuthorityKeyIdof all its issued certificates, not only
the current CA certificate'sSubjectKeyId, so that a CA certificate re-issued with a differentSubjectKeyId
(go 1.25 changed the default derivation from SHA-1 to SHA-256) doesn't send client certificates through OCSP. - Key the connection tracker by connection pointer to avoid 4-tuple collisions and leaks on QUIC connection
migration. - Track QUIC stream goroutines during backend shutdown, recover from panics in QUIC stream handlers, close the
underlying QUIC connection when dialing a stream fails, and fix aQUICConn.streamsleak on unidirectional
streams. - Close queued connections when
proxyListenercloses, and closeos.Roothandles (documentRoot) on backend
shutdown or reload. - Fix a data race in
TokenManager.HMAC(), a data race on WebSocketlastActivetimestamps, and a lock held
while collecting runtime memory/goroutine/mutex profiles on the metrics page; gate/debug/pprofhandlers
behind thepprofbuild tag. - Handle multi-token
Connectionheaders and non-binary frames in the WebSocket handler. - Add timeouts, status code checks, and 1 MiB response limits on OIDC discovery, token, and userinfo requests,
parse all PEM blocks in SAML IdP certificates, and delete denied or already-approved OIDC authorization
requests immediately. - Wipe the temporary SSH CA private key buffer after loading, and cap
RLIM_INFINITYinopenFileLimit(). - Harden the example servers (
examples/backend,examples/oauth2server,examples/deviceauth) and build
scripts.
- Bypass CSRF checks on the PKI OCSP (
- New tests for all the changes above.
- Update go: 1.27.2
- Update go dependencies:
- upgraded github.com/c2FmZQ/storage v0.3.2 => v0.3.3
- upgraded github.com/c2FmZQ/tlsproxy/jwks v0.0.0-20261007172857-b4d54d07896c => v0.0.0-20261007173353-8a25cfd4b704
- upgraded github.com/c2FmZQ/tpm v0.5.0 => v0.6.0
- upgraded github.com/google/go-tpm-tools v0.4.7 => v0.4.10
- upgraded github.com/quic-go/quic-go v0.63.0 => v0.64.0
- upgraded golang.org/x/crypto v0.57.0 => v0.58.0
- upgraded golang.org/x/net v0.59.0 => v0.61.0
- upgraded golang.org/x/sys v0.48.0 => v0.49.0
- upgraded golang.org/x/text v0.42.0 => v0.43.0
- upgraded google.golang.org/protobuf v1.36.5 => v1.36.12
- upgraded software.sslmate.com/src/go-pkcs12 v0.7.3 => v0.7.4