You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
fix(review): J1 — real bugs surfaced by post-refactor review sweep (#168)
Five concrete findings from the code-review + security-review pass after the
route-extraction series. Each verified against source + pinned by a new test
(tests/test_review_fixes_j1.py, 17 tests).
1. SSRF guard on chat URL auto-fetch (CWE-918, routes/chat.py)
_enrich_messages auto-fetches URLs found in chat content — the prompt-
injection vector. Added _url_host_is_public(): resolves the host and rejects
loopback / private / link-local (incl. 169.254.169.254 metadata) / reserved
/ multicast / non-http. _fetch_url_content now validates pre-fetch AND
follows redirects manually (≤5 hops, re-validating each Location) so a
public URL can't 30x-redirect to an internal one. Keeps the
dashboard_host:0.0.0.0 opt-in safe.
2. UnboundLocalError on POST /api/chat {"tools": false} (routes/chat.py)
last_user_text / has_attachment were bound only inside `if use_tools:`, but
_build_chat_system_prompt(...) is called with both regardless → opaque 500.
Hoisted both before the gate.
3. _enrich_messages repo_dir was one dirname too shallow (routes/chat.py)
After the H1 move into routes/, os.path.dirname(abspath(__file__)) resolves
to routes/, not the repo root where codec_search.py lives. Now climbs two
levels (matches the web_search.py extraction). Was masked only because the
dashboard already has repo root on sys.path.
4. _shutdown_services NameError (codec_dashboard.py)
The handler declared `global _qchat_conn, _vibe_conn` and read them, but
those singletons moved to routes/qchat.py + routes/vibe.py in D1/D2 — they
were never module-level names in codec_dashboard anymore, so shutdown raised
NameError before closing anything. Now closes them in their real modules.
5. /api/run_code ran unsupported languages as python (routes/vibe_exec.py)
ext_map listed java/cpp/sql but cmd_map didn't, so cmd_map.get(lang, [python3.13])
silently fed them to python3.13. Now returns 400 "Unsupported language: X".
Also dropped the dead `body.get("filename", ...)` bare expression.
Bonus parity: the non-stream post-LLM path now strips a non-allowlisted
[SKILL:...] tag from the answer (the streaming path already did) — cosmetic,
the execution-gating invariant was already intact on both paths.
Full suite: 2,072 passed / 77 skipped (+17 new J1 tests). ruff clean.
Co-authored-by: Mickael Farina <farina.mickael@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
0 commit comments