Bug-hunt patch (0.8.1)
The 0.8.0 changes were run back through agy itself (a read-only adversarial review) plus a hand audit. Four real issues fixed; one agy finding was a verified false positive. (A parallel codex pass wedged on an unresponsive backend and was skipped this round.)
🔒 Security
- SSRF: a private/loopback IPv4 embedded after a leading label is now blocked. The scrape guard anchored its embedded-IPv4 check at the first label, so
http://foo.127.0.0.1.nip.io/andhttp://a.b.10.0.0.1.sslip.io/slipped past — nip.io / sslip.io resolve<anything>.<ip>.nip.iostraight to<ip>. It now matches a loopback/private quad anywhere in the hostname. Public embedded IPs (foo.8.8.8.8.nip.io) still pass. Regression tests added.
🛡️ Defense in depth
- Repo-location env stripped from the remaining agy launch paths. The bash primary path already dropped
CLAUDE_PROJECT_DIR/GIT_*; now the bash no-nodewrite_filefallback and the Node read-only spawns (runReviewViaTranscript+ the read-only branch ofdefaultAgyRunner) do too./agy:rescueintentionally keeps them — it edits the repo by design.
🐛 Correctness
- Multibyte corruption in the Node stdout capture fixed. The review capture concatenated
chunk.toString()per data event, which mangles a UTF-8 character split across a chunk boundary (→�) for non-ASCII answers larger than one read. Now usessetEncoding("utf8"). (Bash / PowerShell capture to a file and were already byte-safe.)
Notes
- False positive (verified, no change): shorthand IPv4
http://127.1/as an SSRF bypass —new URL()normalizes it to127.0.0.1before the guard, which then blocks it. - Deferred (pre-existing, not 0.8.0 regressions, and the transcript path is now only a fallback behind direct stdout): transcript answer-selection race and multi-
PLANNER_RESPONSEconcat on-cruns, orphaned agy child on/agy:cancel, worktree/temp leak on Ctrl+C. Tracked for a follow-up.
246 unit tests; CI green.
Full changelog: https://github.com/limeflash/antigravity-plugin-cc/blob/main/CHANGELOG.md