Visual Factory
repo: ~/Projects/visual-factory · 10 commits · 0 in last 24h, 0 in last 7d ·
Skills used
- /runs2
- /external1
- /post-ig1
Creative ideas + design notes
Commits with substantial prose (≥120 chars) — the rationale behind each move.
26fb67d · 2026-05-19 · refactor: add .bak/.pre-/.orig 404 guard + broaden .gitignore snapshot patterns
Express middleware now hard-404s any request for snapshot artifacts before
the static handler can serve them. .gitignore picks up the same patterns so
auto-gitify won't sweep them into the repo.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ee44a36 · 2026-05-01 · fix(ssrf): IPv6 reserved-range blocklist now catches in-range forms (codex P2)
The textual prefix checks at server.js:190-194 missed valid in-range IPv6
forms because they only matched specific shapes:
- 100::1 sits inside 100::/64 but failed /^100:0?:0?:0?:/
- fed0::1 and fee0::1 sit inside fec0::/10 but didn't match /^fec/
- any compressed (::) form drifted from the prefix regex
Replaced with proper expand-then-bit-prefix-match:
_expandIPv6(addr) — normalize to 8-group, 4-hex-char-each canonical form
_ipv6InRange(addr, prefix, bits) — CIDR mask comparison
7 RFC reserved ranges checked: fe80::/10, fc00::/7, 100::/64, 64:ff9b::/96,
2001:db8::/32, fec0::/10, ff00::/8.
Verified with node test: 100::1, fed0::1, fee0::1, 2001:db8::1 all now
return true; IPv4 + hostnames return null (untouched).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
19c935e · 2026-04-30 · prefetch: agent:false to force fresh socket per request
The default global Agent pools sockets keyed by host:port. A pooled socket
opened on a previously-validated IP could be reused by a future request
without the lookup callback firing — which is safe (the pooled IP was
validated) but obscures the pin. agent:false forces a one-shot Agent so
the lookup callback runs every prefetch, leaving no ambiguity about
whether DNS pinning was honored.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
05edcc6 · 2026-04-30 · harden prefetchAndRehost: pin DNS, stream size, magic bytes, realpath
- Replace whatwg fetch() with safeFetchToBuffer using http(s).request +
custom lookup callback. Hostname resolves once, validated IP gets pinned;
the actual TCP connection lands on that IP, so DNS rebinding between
validation and fetch can't redirect us into private space.
- Stream-read body with running total; abort mid-stream once the chunks
exceed _MAX_PREFETCH_BYTES (25MB). A server lying about Content-Length
(or omitting it) can no longer OOM us.
- _detectImageMagic: verify PNG / JPEG / GIF / WebP signatures in the
body bytes. Reject when Content-Type and bytes disagree -- don't trust
the header alone.
- /runs/:id/external/:fname: fs.realpath() then re-assert containment in
SANDBOX_OUTPUT before sendFile, so a future symlink can't escape.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
File tree
22 files tracked. Click any to browse the source at HEAD.
rendered in 0ms