`thv run` ignores `--oidc-insecure-allow-http` and `--thv-ca-bundle` — both dropped in `createOIDCConfig` (same as #1470)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Summary
On CLI thv run, two OIDC flags are accepted but do nothing:
--oidc-insecure-allow-http("Allow HTTP (non-HTTPS) OIDC issuers for local
development/testing")--thv-ca-bundle("Path to CA certificate bundle for ToolHive HTTP operations
(JWKS, OIDC discovery, etc.)")
So there is no working way to point thv run at a local OIDC issuer — plain HTTP,
or HTTPS with a self-signed / private CA. Valid token gets 401 at request time.
One root cause: createOIDCConfig() in cmd/thv/app/run_flags.go builds the
auth.TokenValidatorConfig used for the auth middleware, but never sets
InsecureAllowHTTP or CACertPath. It only sets AllowPrivateIP. Same class as
#1470 ("Pass allowPrivateIP into createOIDCConfig") — that PR fixed
AllowPrivateIP in this function, the other two fields were left out.
Confirmed on v0.46.0 (commit c6c425a924) and still on main (6b40bf3d).
Why
CLI builds OIDC config two times:
WithOIDCConfig(...)(pkg/runner/config_builder.go) gets all fields, including
ThvCABundleandInsecureAllowHTTP. This fills the top-level
RunConfig.OIDCConfig.setupOIDCConfiguration()→createOIDCConfig()(cmd/thv/app/run_flags.go)
builds a secondTokenValidatorConfig. This one goes to
WithMiddlewareFromFlags(...), and it is what builds theauthmiddleware
config. HereInsecureAllowHTTPandCACertPathare missing.
setupOIDCConfigurationalso passes onlyrunFlags.JWKSAllowPrivateIP, not
runFlags.InsecureAllowHTTPand notrunFlags.ThvCABundle.
At runtime the proxy rebuilds the auth middleware from the middleware config
(auth.CreateMiddleware → json.Unmarshal(params) → GetAuthenticationMiddleware
→ NewTokenValidator). So it gets InsecureAllowHTTP:false / CACertPath:"", and
OIDC discovery fails in networking.ValidatingTransport.
Proof from the run config
The proxy reads ~/Library/Application Support/toolhive/runconfigs/<name>.json.
OIDC config is there two times and they do not match. The one the proxy uses has
the fields dropped:
top-level oidc_config.InsecureAllowHTTP = true # from WithOIDCConfig
MIDDLEWARE oidc_config.InsecureAllowHTTP (used) = false <-- dropped
top-level oidc_config.CACertPath = /path/to/ca.pem
MIDDLEWARE oidc_config.CACertPath (used) = "" <-- dropped
oidc_config.AllowPrivateIP (both) = true # survives, it is wired (#1470)
AllowPrivateIP survives but the other two do not. That is the tell — it is the
only one of the three that createOIDCConfig sets.
Repro A — --oidc-insecure-allow-http does nothing
- Serve any OIDC issuer over HTTP on localhost (discovery + JWKS), for
examplehttp://localhost:8099withissuer = http://localhost:8099. -
thv run --name t --transport stdio \ --oidc-issuer http://localhost:8099 --oidc-audience test \ --oidc-insecure-allow-http=true --jwks-allow-private-ip=true \ <image> POST /mcpwith a validAuthorization: Bearer <token>(tokeniss/aud
match).
Expected: HTTP is allowed for discovery (flag is set), token validates.
Actual: HTTP 401:
{"error":"invalid_token","error_description":"Invalid token: OIDC discovery failed:
... Get \"http://localhost:8099/.well-known/openid-configuration\": the supplied
URL ... is not HTTPS scheme"}
Repro B — --thv-ca-bundle does nothing
- Serve the same issuer over HTTPS with a self-signed CA cert
(basicConstraints=critical,CA:TRUE, SANDNS:localhost). -
thv run --name t --transport stdio \ --oidc-issuer https://localhost:8099 --oidc-audience test \ --jwks-allow-private-ip=true --thv-ca-bundle /path/to/ca.pem \ <image> POST /mcpwith a valid Bearer token.
Expected: CA bundle is trusted for discovery / JWKS, token validates.
Actual: HTTP 401; proxy log:
oidc discovery failed after retries ... Get
"https://localhost:8099/.well-known/openid-configuration":
tls: failed to verify certificate: x509: certificate signed by unknown authority
The --oidc-jwks-url "bypass" from #2288 does not help here either. Issuer
validation and the JWKS fetch use the same client, built without these fields.
Environment
thvv0.46.0 (Commitc6c425a924fac51c86cbade15d0e720e29a600ab), Homebrew- Runtime: OrbStack (Docker 29.4.0), macOS · Transport:
--transport stdio - Also checked
main@6b40bf3din source — samecreateOIDCConfig.
Suggested fix
Same as #1470, just for the other two fields:
createOIDCConfig(...)— addinsecureAllowHTTP boolandcaCertPath string
params, setInsecureAllowHTTP/CACertPathon the returned
TokenValidatorConfig.setupOIDCConfiguration(...)— passrunFlags.InsecureAllowHTTPand
runFlags.ThvCABundleintocreateOIDCConfig.
(AuthTokenFile / --jwks-auth-token-file looks dropped by the same function
too — maybe wire it in the same change.)
Related, but not duplicates
- #1470 (merged) — fixed
AllowPrivateIPin this same function. This is the
same thing for the last two fields. - #2288 (completed) — added
insecureAllowHTTPfor MCPRemoteProxy / the
operator (spec.oidcConfig). CLIthv run→createOIDCConfigwas not part
of it. - #5776 / #5787 —
insecure_allow_httpfor the authserver upstream
issuer. Different subsystem, notthv runclient-token validation.
Happy to open a PR for the CLI path.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in cmd/thv/app/run_flags.go with setupOIDCConfiguration and createOIDCConfig, then compare their fields with pkg/runner/config_builder.go and the wiring from issue #1470. Trace the returned config into the middleware path. Done means the middleware configuration preserves both CLI flags and the HTTP and private-CA reproductions validate tokens successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- authentication, cli, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100