You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
jwt.sign algorithm option only matches inline string literals — const refs fall back to HS256 #1074
`crates/perry-codegen/src/lower_call/native.rs::lower_jsonwebtoken_sign` only routes when the option value is an inline string literal:
```rust
"algorithm" => {
if let Expr::String(algorithm) = val { // ← only matches inline literals
runtime = match algorithm.as_str() {
"ES256" => "js_jwt_sign_es256",
"RS256" => "js_jwt_sign_rs256",
_ => "js_jwt_sign",
};
} else {
let _ = lower_expr(ctx, val)?; // ← const ref + spread + computed all fall here
}
}
```
`Expr::Identifier` (const reference), spread fields (`...opts`), and any non-literal expression all silently fall through to `js_jwt_sign` (HS256). Mirror bug on `verify`'s `algorithms: [...]` branch.
export function issueAccessToken(claims: AccessTokenClaims): string {
return jwt.sign(claims, loadKey(), {
algorithm: ALG, // ← falls back to HS256
expiresIn: ACCESS_TOKEN_TTL_SEC,
issuer: ISSUER,
});
}
```
The server boots fine and tokens validate (sign/verify both fall through to HS256 the same way), but the ES256 P-256 PEM is used as an HMAC secret instead of an EC key. The application thinks it's using ES256 — TypeScript types say so — but the on-wire tokens are HS256.
Suggested fix
Resolve simple const references at compile time before the literal match. Most TS-bound `const X = "literal"` is statically known. A small symbol-table lookup in `lower_jsonwebtoken_sign` (and the verify variants) would catch the common case. The general `Expr` may need full constant-folding — out of scope for this issue.
Activity
fix(jwt): #1074 — algorithm option resolves const-bound ident before …