From ec128d54b4eec5e2b712aca4b26416d57b11a1bc Mon Sep 17 00:00:00 2001 From: claude code agent 227 Date: Sat, 20 Jun 2026 18:00:43 +0300 Subject: [PATCH] test(ssrf): add IP-level bypass-vector cases (ported from GLM branch) Adds explicit isIpAllowed cases for the CGNAT, ULA (fd00::/8) and IPv4-mapped IPv6 loopback (::ffff:127.0.0.1) sample addresses from the parallel safety-coverage branch. The mapped-loopback case is genuinely new (the existing table only covered the mapped *private* variant); CGNAT and ULA ranges were already covered with other samples and are kept here as explicit regression guards for these specific addresses. Co-Authored-By: Claude Opus 4.8 --- .../core/ai-chat/external-mcp/ssrf-guard.spec.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/server/src/core/ai-chat/external-mcp/ssrf-guard.spec.ts b/apps/server/src/core/ai-chat/external-mcp/ssrf-guard.spec.ts index bd115129..b4f3e32e 100644 --- a/apps/server/src/core/ai-chat/external-mcp/ssrf-guard.spec.ts +++ b/apps/server/src/core/ai-chat/external-mcp/ssrf-guard.spec.ts @@ -46,6 +46,20 @@ describe('isIpAllowed', () => { expect(isIpAllowed(ip).ok).toBe(false); }); + // IP-level bypass vectors ported from the safety-coverage branch. CGNAT + // (100.64/10) and the ULA range (fc00::/7) are already exercised above with + // other sample addresses; the genuinely distinct case is the IPv4-mapped + // IPv6 *loopback* (::ffff:127.0.0.1) — the table above only had the mapped + // *private* variant. fd00::/8 is the commonly-assigned ULA prefix, kept as an + // explicit regression guard. + it.each([ + ['CGNAT', '100.64.0.1'], + ['ULA fd00::/8', 'fd00::1'], + ['IPv4-mapped IPv6 loopback', '::ffff:127.0.0.1'], + ])('blocks bypass vector %s (%s)', (_label, ip) => { + expect(isIpAllowed(ip).ok).toBe(false); + }); + it('allows a public IPv4 (8.8.8.8)', () => { expect(isIpAllowed('8.8.8.8').ok).toBe(true); });