OIDC discovery and token exchange (internal/web/oidc.go:80, oidc.NewProvider) use the system TLS trust store without optional certificate pinning. The provider/oauth2.Config/http.Client chain uses the default transport.
Impact
If an attacker compromises a CA trusted by the system trust store, they can:
- Issue a certificate for the IdP's hostname
- MITM OIDC discovery → serve a fake JWKS with the attacker's public key
- Sign a forged ID token for any subject
- Authenticate as any operator in the mesh
This requires CA compromise + network position (high-bar), but the blast radius (full mesh compromise) justifies defence-in-depth.
Proposed fix
Add an optional oidc.tls_ca_cert config field pointing to a PEM CA bundle:
oidc:
tls_ca_cert: /etc/nebula-mgmt/oidc-ca.pem # optional: pin IdP TLS to this CA
When set, build a dedicated *tls.Config with a custom RootCAs pool for the OIDC HTTP client (passed via oidc.ClientContext), leaving the system store intact for every other connection.
Code pointers
- OIDC constructor:
internal/web/oidc.go:73-105 (NewOIDC)
- Provider creation:
internal/web/oidc.go:80 (oidc.NewProvider)
- Config model:
internal/config/server.go:349-371 (OIDCConfig) — no TLS field today
OIDC discovery and token exchange (
internal/web/oidc.go:80,oidc.NewProvider) use the system TLS trust store without optional certificate pinning. The provider/oauth2.Config/http.Clientchain uses the default transport.Impact
If an attacker compromises a CA trusted by the system trust store, they can:
This requires CA compromise + network position (high-bar), but the blast radius (full mesh compromise) justifies defence-in-depth.
Proposed fix
Add an optional
oidc.tls_ca_certconfig field pointing to a PEM CA bundle:When set, build a dedicated
*tls.Configwith a customRootCAspool for the OIDC HTTP client (passed viaoidc.ClientContext), leaving the system store intact for every other connection.Code pointers
internal/web/oidc.go:73-105(NewOIDC)internal/web/oidc.go:80(oidc.NewProvider)internal/config/server.go:349-371(OIDCConfig) — no TLS field today