Skip to content

Commit eeb713a

Browse files
committed
chore: update progress for US-110
1 parent 5c989e9 commit eeb713a

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

scripts/ralph/prd.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1992,7 +1992,7 @@
19921992
"Tests pass"
19931993
],
19941994
"priority": 118,
1995-
"passes": false,
1995+
"passes": true,
19961996
"notes": "Audit H6 — HIGH. permissions.ts:228-234, node/driver.ts:241-278. Permission checks validate the original URL but fetch follows redirects by default. A URL that 302-redirects to http://169.254.169.254/ passes the check."
19971997
},
19981998
{

scripts/ralph/progress.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ PRD: ralph/kernel-hardening (46 stories)
106106
- NodeExecutionDriver split into 5 modules in src/node/: isolate-bootstrap.ts (types+utilities), module-resolver.ts, esm-compiler.ts, bridge-setup.ts, execution-lifecycle.ts; facade is execution-driver.ts (<300 lines)
107107
- Source policy tests (isolate-runtime-injection-policy, bridge-registry-policy) read specific source files by path — update them when moving code between files
108108
- esmModuleCache has a sibling esmModuleReverseCache (Map<ivm.Module, string>) for O(1) module→path lookup — both must be updated together and cleared together in execution.ts
109+
- Network adapter SSRF: isPrivateIp() + assertNotPrivateHost() in driver.ts; fetch uses redirect:'manual' with per-hop re-validation; httpRequest has pre-flight check only (no auto-redirect); data:/blob: URLs skip SSRF check
109110

110111
---
111112

@@ -1497,3 +1498,19 @@ PRD: ralph/kernel-hardening (46 stories)
14971498
- Mock command executor pattern (createCapturingExecutor) captures spawn args/env without needing real child processes — useful for bridge-level security tests
14981499
- filterEnv in permissions.ts is permission-based filtering; dangerous env var stripping is a separate concern applied at the bridge boundary
14991500
---
1501+
1502+
## 2026-03-18 - US-110
1503+
- What was implemented: SSRF protection for network adapter — blocks requests to private/reserved IP ranges and re-validates redirect targets
1504+
- Files changed:
1505+
- packages/secure-exec-node/src/driver.ts — added isPrivateIp(), assertNotPrivateHost(), MAX_REDIRECTS; modified fetch() to use redirect:'manual' with re-validation; modified httpRequest() with pre-flight IP check
1506+
- packages/secure-exec-node/src/index.ts — exported isPrivateIp
1507+
- packages/secure-exec/src/node/driver.ts — re-exported isPrivateIp
1508+
- packages/secure-exec/tests/runtime-driver/node/ssrf-protection.test.ts — new test file with 37 tests
1509+
- **Learnings for future iterations:**
1510+
- isPrivateIp must handle IPv4-mapped IPv6 (::ffff:a.b.c.d) by stripping the prefix before checking
1511+
- assertNotPrivateHost must skip non-network URL schemes (data:, blob:) — existing test suite uses data: URLs
1512+
- fetch redirect following uses redirect:'manual' and manually follows up to 20 hops, re-validating each target URL against the private IP blocklist
1513+
- httpRequest (node http module) doesn't follow redirects by default, so only pre-flight check needed
1514+
- DNS rebinding is documented as a known limitation — would require pinning resolved IPs to the connection, not possible with native fetch
1515+
- 5 pre-existing test failures in index.test.ts (http.Agent, upgrade, server termination) are NOT caused by SSRF changes — they fail identically on the pre-SSRF commit
1516+
---

0 commit comments

Comments
 (0)