The Problem with JWT
JSON Web Tokens (JWT) are the most widely used token format on the web. They are also one of the most misused. The JWT specification (RFC 7519) is flexible by design — it supports multiple algorithms, multiple key types, and multiple serialization formats. This flexibility has produced a long history of security vulnerabilities, many of which are structural rather than implementation bugs.
For a typical web application session token, these issues are manageable with careful implementation. But for AI agent authorization proofs — tokens that serve as cryptographic evidence that a specific action was authorized by a specific owner at a specific time — the stakes are higher. A forged or manipulated proof token could authorize an agent to spend money, access sensitive data, or perform irreversible actions. The token format needs to be secure by default, not secure if configured correctly.
JWT's Structural Vulnerabilities
The security issues with JWT are well-documented and have been exploited repeatedly in production systems. The most critical are structural — they exist because of how the specification was designed, not because of implementation errors.
The alg Header Attack
JWT includes the signing algorithm in the token header. The verifier reads this header to determine
how to verify the signature. This means an attacker can change the algorithm to one the verifier
does not expect. The most famous variant: if a server uses RSA to sign tokens but the verifier
also accepts HMAC, an attacker can take the server's RSA public key (which is public), use it as
an HMAC secret to sign a forged token, and set alg: HS256. The verifier uses the
"public key" as the HMAC secret, the signature validates, and the forged token is accepted.
The none Algorithm
The JWT specification includes an alg: none option that produces unsigned tokens.
This was intended for contexts where the token integrity is guaranteed by other means (like TLS).
In practice, many JWT libraries accepted none tokens by default, allowing attackers
to strip the signature entirely and present an unsigned token that the verifier accepted as valid.
Key Confusion Attacks
JWT's support for multiple key types (symmetric and asymmetric) within the same verification flow creates confusion vulnerabilities. If a system is configured for asymmetric signing (RS256) but the library also supports symmetric verification, an attacker can exploit the overlap. These attacks are subtle and difficult to detect through code review alone.
Weak Default Configurations
Many JWT libraries ship with permissive defaults: accepting multiple algorithms, not validating expiration claims, allowing unsigned tokens in development mode. Each permissive default is a potential vulnerability in production. Securing JWT requires explicitly disabling features — a negative security model where forgetting a configuration option creates an exploit.
How PASETO Solves These Problems
PASETO (Platform-Agnostic Security Tokens) was designed explicitly to fix JWT's structural issues. Created by Scott Arciszewski in 2018, PASETO takes a different approach: instead of being flexible, it is opinionated. Instead of letting the developer choose (and potentially mischoose) algorithms, PASETO prescribes exactly one algorithm per version and purpose.
No Algorithm Negotiation
PASETO tokens do not contain an algorithm header. The version and purpose are encoded in the token
prefix (e.g., v4.public), and each prefix maps to exactly one algorithm. There is no
mechanism for an attacker to change the algorithm because the algorithm is not specified in the token —
it is determined by the protocol version. The alg header attack is structurally impossible.
No none Option
PASETO does not have an unsigned token mode. Every token is either encrypted (local) or signed (public). There is no way to produce a valid PASETO token without a key. This eliminates an entire class of vulnerabilities by simply not offering the dangerous option.
Strict Purpose Separation
PASETO separates symmetric encryption (local) from asymmetric signing (public)
at the protocol level. A v4.local token can only be verified with symmetric decryption.
A v4.public token can only be verified with asymmetric signature verification. The key
types cannot be confused because they use different token prefixes and different verification code paths.
Modern Cryptography
PASETO v4 uses Ed25519 for public tokens and XChaCha20-Poly1305 for local tokens. These are modern, well-analyzed primitives with strong security margins. There is no option to use SHA-1, RSA with PKCS#1 v1.5 padding, or any of the legacy algorithms that JWT supports and that have known weaknesses.
Why v4.public with Ed25519 for Agent Proofs
OpenLeash uses PASETO v4.public tokens for authorization proofs. This choice is driven
by the specific requirements of AI agent authorization:
- Offline verification. Counterparties (the services receiving agent requests) need to verify proof tokens without calling back to the authorization server. Public-key signatures enable this — anyone with the public key can verify, but only the key holder can sign.
- Non-repudiation. A signed proof token is evidence that the owner's key authorized the action. Unlike symmetric tokens (where anyone who can verify can also forge), asymmetric tokens provide non-repudiation: the verifier cannot create fake proofs.
- Performance. Ed25519 signatures are fast — roughly 50,000 signatures per second on modest hardware. Verification is even faster. For an authorization sidecar that evaluates every agent action, signature performance matters.
- Small keys and signatures. Ed25519 public keys are 32 bytes. Signatures are 64 bytes. This keeps proof tokens compact, which matters when tokens are included in HTTP headers or passed between services.
What a Proof Token Looks Like
An OpenLeash proof token is a standard PASETO v4.public token. The payload contains
the authorization decision, the action that was evaluated, constraints that were applied, and
metadata for auditing:
The token is signed with the owner's Ed25519 private key. A counterparty receiving this token
can verify the signature using the public key (available at GET /v1/public-keys)
and confirm that the agent was authorized to send a payment of up to $50 USD. No trust in the
agent itself is required — the trust is in the cryptographic signature.
Side-by-Side Comparison
alg header) No (fixed per version) alg: none) Not possible When JWT Is Still Appropriate
JWT is not universally bad. For web application session tokens in a controlled environment where you own both the issuer and the verifier, JWT with a pinned algorithm (e.g., ES256) and strict validation works fine. The ecosystem is mature, every language has libraries, and the interoperability is excellent.
The case for PASETO is strongest when tokens cross trust boundaries — when a token issued by one party is verified by a different party, when tokens serve as evidence rather than session state, or when the cost of a forged token is high. AI agent proof tokens meet all three criteria. The token issuer (OpenLeash) is different from the verifier (the counterparty). The token is evidence of authorization. And a forged token could authorize unauthorized spending, data access, or actions.
Further Reading
Learn more about how OpenLeash uses PASETO tokens in the PASETO proof tokens concept page. For a hands-on walkthrough, see our getting started guide. To understand the broader context of why agents need authorization, read why AI agents need authorization in 2026. For the full specification, visit the PASETO website.