We shipped Wayforth — a search and payment rail
for AI agents — and before expanding the managed
services catalog we ran a full security audit.
Here's how we fixed it.
The Stack
FastAPI · PostgreSQL · Railway · Base blockchain
Supabase Auth · Stripe · Fernet AES-128 · BSL 1.1
uvx wayforth-mcp
Critical Findings (5)
C1 — JWT not cryptographically verified
Fix: JWKS-based ES256 verification via Supabase's
public endpoint — no shared secret needed.
def verify_supabase_jwt(token: str) -> dict:
jwks = get_jwks() # cached 1hr
header = jwt.get_unverified_header(token)
key = next(k for k in jwks if k["kid"] == header["kid"])
public_key = ECAlgorithm.from_jwk(key)
return jwt.decode(token, public_key,
algorithms=["ES256"], audience="authenticated")
C2 — CORS wildcard + credentials
Fix: Explicit origins only.
allow_origins=[
"https://wayforth.io",
"https://www.wayforth.io",
"http://localhost:3000",
"http://localhost:5173",
]
C3 — Admin key timing oracle
Fix: secrets.compare_digest() in all 11 places.
C4 — BYOK silent plaintext fallback
Fix: Both now raise HTTP 500 instead of
silently degrading security.
C5 — Webhook IDOR
Fix: Ownership verified before delete.
High Findings (5)
-
H1 — Fernet key entropy: invalid keys now
raise
ValueErrorat call time - H2/H3 — BYOK encrypt/decrypt fail silently: both raise HTTP 500
-
H4 — No security headers: added
X-Frame-Options,X-Content-Type-Options,HSTS,Referrer-Policy,Permissions-Policy -
H5 —
supabase_idechoed in 401 body: removed (account enumeration vector)
Frontend Findings
- API key written to
localStorageon signup → moved tosessionStorage - Admin token in
localStorage→sessionStorage - No expired session handler → global 401
interceptor now redirects to
/login -
innerHTMLwith API responses → escaped
What Was Already Clean
SQL injection — parameterized everywhere, zero
string concatenation. No eval() or exec().
API keys — SHA-256 hashed, never logged.
Admin passwords — bcrypt.
Key generation — secrets.token_urlsafe().
.env in .gitignore.
Result
20 findings. All resolved.
Zero open findings before expanding the catalog.
Try it: uvx wayforth-mcp
GitHub: github.com/WayforthOfficial/wayforth
Docs: wayforth.io

Top comments (0)