TL;DR: A JWT's kid header is attacker-controlled text that many libraries hand straight to the filesystem. Put ../ in it and the verifier reads a file of the attacker's choosing as the signing key — which means they can then sign their own tokens. PainHunt's DevSecOps data carries a small but unusually intense cluster of these reports, alongside a matching temp-file race. The wedge is a library that enforces key ID whitelisting itself, plus static analysis that finds the pattern before it ships.
The evidence
PainHunt's DevSecOps category holds 171 high-scoring signals (10+/15), average intensity 7.6/10, average score 11.7, sourced mostly from GitHub (75), Mastodon (37), HackerNews (15), Reddit (11) and Dev.to (11).
Inside it, 10 signals form a key-handling cluster with intensity 7.9/10 — above the category average. The reports are specific, and all trace to the same shape:
- JWT verification uses the
kid(Key ID) header directly in a filesystem path, allowing path traversal. - The
kidheader accepts traversal characters like../because no input validation rejects them. - The consequence named repeatedly is secret key leakage leading to complete authentication bypass — not merely an unauthorized read.
- No automated validation exists for cryptographic key identifiers in the affected authentication libraries.
The same cluster contains a structurally identical filesystem bug in shell and system-level scripts: time-of-check to time-of-use (TOCTOU) races in temporary file handling, exploitable through symlinks for arbitrary file writes, caused by missing atomic creation (mkstemp, O_EXCL) and unenforced 0600 permissions with no owner verification.
The reporters are open-source maintainers, security researchers and bug bounty hunters — the sources are dominated by GitHub, which is where this class of finding gets filed rather than discussed.
The fixes named in the data are equally specific: a hardened JWT library with built-in whitelist enforcement for key IDs, automated static analysis for kid header injection risks, a JWT security auditing tool, and a secure temporary file management library.
Why now
Two things made this cluster bigger than it should be.
First, kid is one of the few JWT header fields with no prescribed semantics. RFC 7515 says it's a hint for which key to use and stops there. Every library invents its own resolution, and "look up a file named after it" is the shortest path from spec to working code. The spec never said the hint is untrusted input, so implementations keep re-learning it.
Second, key rotation went mainstream. Multi-tenant services and short-lived signing keys made dynamic key lookup normal, so far more code paths now resolve a kid at verification time than did five years ago. The bug is old; the surface area is new.
Meanwhile the failure is unusually quiet. A traversal that leaks a signing key produces no failed logins and no anomalous errors — the attacker's subsequent tokens verify correctly. There is nothing for a WAF or an auth log to catch.
The wedge
Don't sell a scanner. Sell the safe default, then the proof it's in place.
- Whitelist inside the library, not in the caller's hands. The verifier accepts a set of permitted key IDs, or a resolver function, and refuses anything else. Any
kidcontaining a path separator or..is rejected before it reaches a filesystem call, regardless of how the application configured it. This is the fix the reports ask for, and it belongs one layer below where teams keep getting it wrong. - Static analysis for the exact taint path. A rule that flags
kid(and equivalent header-derived identifiers) flowing intoopen,readFile,require, or path joins. Narrow, high-signal, and shippable as a CI check or a linter plugin rather than another dashboard. - The same rule for temp files. TOCTOU on
mkstemp-less temporary file creation is the second half of this cluster and detectable by the same class of analysis: non-atomic creation, missingO_EXCL, permissions wider than0600, no owner check. - An audit mode that reports what is enforced. Maintainers filing these reports need to show a project that the fix landed. A verifiable statement — which key IDs are permitted, which paths are reachable — is more useful to them than a severity score.
Risks and honest caveats
- The cluster is 10 signals, not 100. Intensity is high (7.9/10) and the reports are precise, but this is a narrow finding inside a 171-signal category. Treat it as evidence that the pattern is live and being filed, not as sizing for a market.
- The obvious buyer may not pay. These reports come from open-source maintainers and bounty hunters. The people who need the hardened library are often the ones least able to buy tooling — the paying customer is more likely a platform team with an auth service they can't fully audit.
- Established JWT libraries are free and entrenched. Replacing one is a security-sensitive migration, which is exactly the kind teams defer. A hardening wrapper or a strict mode contributed upstream may reach further than a new library, at the cost of a weaker business.
- Static analysis lives or dies on false positives. A rule loose enough to catch indirect flows will fire on safe code; one tight enough to stay quiet will miss real bugs. This trade-off is the actual product, and it isn't solved by having the idea.
How to validate this further
Read the underlying DevSecOps signals in the Pain Point Browser, and check whether the maintainers filing them would pay or only adopt. Related security wedges in this data: MCP server SSRF and DNS rebinding protection and self-hosted CVE exposure response. To pressure-test the buyer question before writing code, run it through the Idea Validator and the checklist in how to validate a startup idea.