Skip to content

fix(identity): harden HTTP clients and add TLS cert pinning for JWKS fetch (PILOT-241)#88

Merged
TeoSlayer merged 2 commits into
mainfrom
openclaw/pilot-241-20260629-214234
Jun 30, 2026
Merged

fix(identity): harden HTTP clients and add TLS cert pinning for JWKS fetch (PILOT-241)#88
TeoSlayer merged 2 commits into
mainfrom
openclaw/pilot-241-20260629-214234

Conversation

@matthew-pilot

Copy link
Copy Markdown
Collaborator

What changed

sharedHTTPClient hardening

  • Disabled HTTP redirects on the identity webhook HTTP client (previously followed up to 10 redirects by default)
  • Enforced TLS 1.2 minimum version

TLS certificate pinning for JWKS fetch (PILOT-241)

  • New jwksPinnedHTTPClient() helper that returns a hardened HTTP client which verifies the server TLS certificate fingerprint (SHA-256 of DER-encoded cert) against a configured pin
  • New GetKeyWithPinning() method on JWKSCache — fetches JWKS keys with optional TLS fingerprint verification
  • New FetchJWKSKeysWithPinning() exported function for direct use by external callers
  • HandleValidateToken now uses the Store’s pinned fingerprint (when configured) during JWKS key fetch
  • Store.SetPinnedCertFingerprint() / Store.GetPinnedCertFingerprint() for runtime configuration

Why

PILOT-241 reported that the OIDC/JWKS fetch path followed up to 10 redirects and had no TLS certificate pinning. The redirect + TLS minimum version parts were already addressed via jwksHTTPClient in the original implementation. This PR:

  1. Extends the same hardening to sharedHTTPClient (used by the identity webhook path)
  2. Adds certificate pinning infrastructure to prevent MITM attacks during JWKS key fetch

Verification

  • go build ./... — clean
  • go vet ./... — clean
  • go test ./... — all passing (including identity package)

Closes PILOT-241

…fetch (PILOT-241)

Harden sharedHTTPClient used for identity webhook calls: disable redirects
(redirect is a protocol anomaly) and enforce TLS 1.2 minimum version.

Add TLS certificate pinning support for JWKS key fetch:
- New jwksPinnedHTTPClient helper returns a client that verifies the
  server's TLS certificate fingerprint (SHA-256 of DER) against a
  configured pin, rejecting MITM who serve a different certificate.
- New GetKeyWithPinning method on JWKSCache accepts a pinning fingerprint.
- New FetchJWKSKeysWithPinning exported function for external callers.
- HandleValidateToken uses the Store's pinned fingerprint when fetching
  JWKS keys.
- SetPinnedCertFingerprint / GetPinnedCertFingerprint on Store for runtime
  configuration (future: migrate to BlueprintIdentityProvider field).

Previously sharedHTTPClient had no redirect protection and no TLS
minimum. JWKS fetch was already hardened with jwksHTTPClient but
lacked certificate pinning.

Closes PILOT-241
@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Comment thread identity/identity.go Fixed
G402/CWE-295: the JWKS pinning client set InsecureSkipVerify:true with a
VerifyPeerCertificate callback, which disabled all chain/expiry/hostname
verification - the opposite of pinning. gosec G402 and CodeQL
go/disabled-certificate-check flagged identity.go:1091.

Pin via tls.Config.VerifyConnection, which runs after Go's default chain
verification (InsecureSkipVerify stays false). It requires the leaf to
match the configured pin by SPKI-SHA256 (preferred, survives key-preserving
renewal) or full-cert SHA-256, fail-closed on missing/mismatched cert.
Add tests covering SPKI match, cert-fingerprint match, mismatch rejection,
empty-pin passthrough, and the no-peer-cert path.
@TeoSlayer TeoSlayer merged commit ebca5ee into main Jun 30, 2026
9 checks passed
@matthew-pilot matthew-pilot deleted the openclaw/pilot-241-20260629-214234 branch June 30, 2026 18:37
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.

4 participants