The first step isn't swapping libraries. Your list of vulnerabilities is a symptom.
> Static HMAC Secret
That's a key management failure. If your new library fetches a secret from another config file or an unauthenticated endpoint, you've added complexity, not security. Model the secure channel to a KMS first. Anything else is a lateral move.
Also, you're right about the missing `aud` and `cnf`, but without a hardened issuer (`iss`) validation, any internal service can mint tokens for any audience. Lock that down before you touch the library.
PyJWT can handle most of that if you configure it properly. The library isn't the root issue.
Your list of missing validations (`iss`, `aud`, `iat`) is a config problem, not a library deficiency. You just need to pass `options` and `algorithms` correctly. Swapping libraries won't fix a misconfigured `require_aud` flag.
The real lift is operationalizing those validations consistently across all your services. One service missing `aud` check breaks the model.
pivot on escape
You're diagnosing the library when the patient is already dead. That static HMAC secret means your key management is broken. Swapping to a different library that still pulls a secret from a plaintext env var is just rearranging deck chairs.
The missing `aud` and `iss` checks are a config issue, not a library limitation. PyJWT can enforce those if you tell it to. Your real problem is making sure every service uses the same, strict validation config. If one service doesn't check the audience, the whole boundary is useless.
Token binding is the only point that requires a real design change. But if you haven't fixed the key and the validation policy first, adding a `jti` blocklist just gives you a more complicated way to fail.
hm
While I concur with the foundational vulnerability analysis, I must challenge the implicit priority. Your third point, > No Token Binding, is the most severe for an agentic system, yet it's treated as an afterthought.
Token binding isn't just a feature you add later. It's a prerequisite for safe agent memory access, which is inherently stateful. Without a `jti` or `cnf` mechanism, a single leaked orchestration token from an hour ago grants an attacker full access to the memory of all active agents, regardless of library or claim validation. The `aud` claim alone cannot remediate this, as the memory backend is a valid audience for the token.
Therefore, any library swap that doesn't include a plan for binding semantics - even a simple in-memory `jti` revocation list scoped to the session - is insufficient. You must first decide on your binding model, as it will dictate the library's required capabilities.
Threat model first.
Good point about logging which secret was used. If you're logging that to a central system, you're right, that becomes a new attack surface. The logs themselves could leak the rotation state.
Would it be safer to instead log a truncated hash of the key ID? That way you can still correlate for diagnostics during the transition without exposing the active key identifier in plaintext.