Problem
exchangeSetupToken in src/server/lib/simple-fin/tokens.ts base64-decodes a user-provided token into a URL and fetches it with no validation:
const setupUrl = Buffer.from(setupToken, "base64").toString();
const response = await fetch(setupUrl, { method: "POST", ... });
A user could craft a token encoding an internal URL like http://localhost:5432, http://169.254.169.254/latest/meta-data/ (cloud metadata), or other internal services.
Impact
- SSRF: Server can be tricked into making requests to internal network resources
- Info disclosure: Cloud metadata endpoints can expose IAM credentials
- Severity: Low-medium (requires authenticated access), but still a real vector in production
Fix
Validate the decoded URL before fetching:
- Must use
https:// scheme
- Must resolve to a public IP (not
127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16)
- Optionally: allowlist SimpleFin's known domain (
beta-bridge.simplefin.org)
Problem
exchangeSetupTokeninsrc/server/lib/simple-fin/tokens.tsbase64-decodes a user-provided token into a URL and fetches it with no validation:A user could craft a token encoding an internal URL like
http://localhost:5432,http://169.254.169.254/latest/meta-data/(cloud metadata), or other internal services.Impact
Fix
Validate the decoded URL before fetching:
https://scheme127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16)beta-bridge.simplefin.org)