Skip to content

fix(security): valida JWT ES256 de Supabase (desbloquea producción)#56

Merged
gonzaloMorenoc merged 1 commit into
mainfrom
fix/mnemo-jwt-es256
Jun 30, 2026
Merged

fix(security): valida JWT ES256 de Supabase (desbloquea producción)#56
gonzaloMorenoc merged 1 commit into
mainfrom
fix/mnemo-jwt-es256

Conversation

@gonzaloMorenoc

Copy link
Copy Markdown
Owner

El bug (producción rota)

Crear una organización en prod daba 500 (directo al backend) / 504 (vía Vercel). Causa: el path de validación de JWT por JWKS en src/security.py asumía RSA:

public_key = jwt.algorithms.RSAAlgorithm.from_jwk(...)   # ← lanza con claves EC
"algorithms": ["RS256"]

Supabase emite JWT ES256 (claves EC). RSAAlgorithm.from_jwk con una clave EC lanza InvalidKeyError: Not an RSA key fuera del try/except500 en toda ruta autenticada. Reproducido contra el JWKS real (kty=EC alg=ES256).

En local no aparecía porque con SUPABASE_JWT_SECRET se toma el path HS256 (simétrico). En prod (sin ese secret) se usa el path JWKS → el bug. Era justo el path que la auditoría marcó como no testeado.

El fix

  • jwt.PyJWK(key).key detecta el tipo de clave (EC/RSA) desde el JWK.
  • algorithms = ["RS256", "ES256"] (sigue aceptando RSA; añade EC). No acepta none ni downgrade.
  • tests/test_security_jwks.py (nuevo): ES256 valida, RS256 regresión, firma inválida → 401.

Plan de pruebas

  • Test nuevo: 3/3 verde sin .env. Regresión auth/security: 49 passed.
  • Causa confirmada reproduciendo contra el JWKS real de Supabase (EC/ES256).

Para desplegar el fix

  1. Mergear este PR a main.
  2. En el Space de HF: Factory rebuild (re-clona main con el fix).
  3. Reintentar crear la organización → debe funcionar.

https://claude.ai/code/session_0198KfgRWvAM8BhiVz24uTok

El path JWKS asumía RSA (RSAAlgorithm.from_jwk + algorithms=["RS256"]); Supabase emite
JWT ES256 (claves EC) → InvalidKeyError "Not an RSA key" FUERA del try/except → 500 en
toda ruta autenticada en prod (crear org → 500 directo / 504 vía Vercel). En local no
salía porque con SUPABASE_JWT_SECRET se usa el path HS256.

Fix: jwt.PyJWK(key).key detecta EC/RSA desde el JWK; algorithms=["RS256","ES256"].
Test nuevo (gap de la auditoría): ES256 valida, RS256 regresión, firma inválida → 401.

Claude-Session: https://claude.ai/code/session_0198KfgRWvAM8BhiVz24uTok
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mnemo Ready Ready Preview, Comment Jun 30, 2026 12:41pm

@gonzaloMorenoc gonzaloMorenoc merged commit 0d4a49c into main Jun 30, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant