Summary
Adversarial test sweep of api/rss-proxy.js found the existing 5 tests have teeth, but the test file is not wired into CI, and several adversary-reachable seams are uncovered.
CI status
api/rss-proxy.test.mjs is not included in test:data or test:sidecar.
- Fix: add it to
test:sidecar in package.json; no workflow change needed.
Confirmed gaps
Critical
- SSRF hostname/userinfo confusion —
api/rss-proxy.js:135-139, api/_rss-allowed-domain-match.js:24-32
- Subdomains like
techcrunch.com.attacker.example or https://[email protected]/feed may bypass the allowlist.
- Mutation: disabling
isAllowedDomain(hostname) returned 502 instead of 403 and fetched the attacker host.
High
- Missing/invalid API keys not tested before fetch —
api/rss-proxy.js:105-108
- Mutation disabling the invalid-key return let a bad key reach upstream fetch (502 instead of 401).
- Rate-limit block not tested —
api/rss-proxy.js:110-111
- Mutation ignoring
rateLimitResponse continued into the feed fetch (200 instead of 429).
- Non-http initial URL guard not tested —
api/rss-proxy.js:74-77, api/rss-proxy.js:132-133
file:///etc/passwd should return 400; mutation changed status to 403 and test stayed red.
Medium
- Missing/malformed
url parameter — api/rss-proxy.js:113-130
- Method/OPTIONS handling —
api/rss-proxy.js:97-103
- Disallowed origin —
api/rss-proxy.js:91-95
- Relay-only routing + cache policy —
api/rss-proxy.js:13-32, api/rss-proxy.js:141, api/rss-proxy.js:178-215
- Google News timeout selection —
api/rss-proxy.js:66-71, api/rss-proxy.js:143-145
- Timeout
AbortError → 504 mapping — api/_relay.js:26-33, api/rss-proxy.js:219-235
- Non-2xx direct-response relay fallback —
api/rss-proxy.js:193-198
- Content-type fallback + cache headers —
api/rss-proxy.js:201-218
Suggested fix
- Add
api/rss-proxy.test.mjs to test:sidecar.
- Add regression tests for the critical/high gaps; prove each fails before the fix and passes after.
Summary
Adversarial test sweep of
api/rss-proxy.jsfound the existing 5 tests have teeth, but the test file is not wired into CI, and several adversary-reachable seams are uncovered.CI status
api/rss-proxy.test.mjsis not included intest:dataortest:sidecar.test:sidecarinpackage.json; no workflow change needed.Confirmed gaps
Critical
api/rss-proxy.js:135-139,api/_rss-allowed-domain-match.js:24-32techcrunch.com.attacker.exampleorhttps://[email protected]/feedmay bypass the allowlist.isAllowedDomain(hostname)returned 502 instead of 403 and fetched the attacker host.High
api/rss-proxy.js:105-108api/rss-proxy.js:110-111rateLimitResponsecontinued into the feed fetch (200 instead of 429).api/rss-proxy.js:74-77,api/rss-proxy.js:132-133file:///etc/passwdshould return 400; mutation changed status to 403 and test stayed red.Medium
urlparameter —api/rss-proxy.js:113-130api/rss-proxy.js:97-103api/rss-proxy.js:91-95api/rss-proxy.js:13-32,api/rss-proxy.js:141,api/rss-proxy.js:178-215api/rss-proxy.js:66-71,api/rss-proxy.js:143-145AbortError→ 504 mapping —api/_relay.js:26-33,api/rss-proxy.js:219-235api/rss-proxy.js:193-198api/rss-proxy.js:201-218Suggested fix
api/rss-proxy.test.mjstotest:sidecar.