[fix] - post-security-audit robustness + accuracy follow-ups (4 small nits)#653
Draft
cgfixit wants to merge 2 commits into
Draft
[fix] - post-security-audit robustness + accuracy follow-ups (4 small nits)#653cgfixit wants to merge 2 commits into
cgfixit wants to merge 2 commits into
Conversation
From the Phase-2 security scan; all low-severity, each traceable to a finding: - utils/ops_runner.py: _write_body created the temp file before writing, but run_agentic_op only unlinks the name _write_body RETURNS — a mid-write failure (disk full, un-encodable body) orphaned a cyclaw_skill_*.md. Clean up the orphan on the write-error path (close-then-unlink, Windows-safe). Regression test forces a write failure and asserts no orphan survives. - harness/sessions.py: SessionStore.list() sorted by getmtime BEFORE the per-file skip loop, so a session file removed between glob and sort raised OSError straight out of a listing path meant to tolerate missing/corrupt files (would 500 /api/sessions + /api/status). Sort via a getmtime helper that returns 0.0 on OSError. Regression test races a vanishing file. - llm/client.py: replaced a dead `if not _is_loopback_url(primary_url): pass` (computed a check, did nothing) with a plain comment; the non-loopback primary allowance is intentional, just no longer disguised as control flow. - utils/logger.py: module docstring claimed query hashing is unconditional, but it is gated on logging.audit_fields.include_query_hash (shipped true; the scoped guarantee is already pinned in test_due_diligence_invariants). Docstring now states the toggle and that disabling it is privacy-affecting. Verified: ruff clean; 104 passed (ops_runner + harness + audit); both regression tests revert-proven; invariant-guard 28/0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0138hmScu3tFU4v1jzvFUwVT
Replace the _safe_mtime helper (added a module member -> WPS202 8>7, and a 0.0 float literal -> WPS358; staticmethod hits WPS214, nested def hits WPS430) with a contextlib.suppress(OSError) around paths.sort. Same behavior — a file vanishing mid-sort no longer 500s the listing — with a dead-plain shape and clearer intent. Regression test unchanged and still revert-proven. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0138hmScu3tFU4v1jzvFUwVT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed changes
Four low-severity follow-ups from the Phase 2 security scan (the audit found no high-severity issues; the codebase is heavily hardened). Each traces to a specific finding and is independently trivial:
utils/ops_runner.py_write_body): the file is created (NamedTemporaryFile(delete=False)) beforehandle.write(body);run_agentic_oponly unlinks the name_write_bodyreturns, so a mid-write failure (disk full, un-encodable body) orphaned acyclaw_skill_*.mdin the OS temp dir. Now cleans up its own orphan on the write-error path (close-then-unlink, Windows-safe). Regression test forces the write to raise and asserts no orphan survives.harness/sessions.pySessionStore.list()): sorted bygetmtimebefore the per-filetry/except SessionStoreErrorskip loop, so a session file removed betweenglobandsortraisedOSErrorstraight out of a path meant to tolerate missing/corrupt files — 500-ing/api/sessions+/api/status. Sort now uses agetmtimehelper returning0.0onOSError. Regression test races a vanishing file.llm/client.py):if not _is_loopback_url(primary_url): passcomputed a loopback check and did nothing — reads like enforcement but is a no-op. Replaced with a plain comment (the non-loopback-primary allowance is intentional).utils/logger.py): the module docstring claimed query hashing is unconditional, but it's gated onlogging.audit_fields.include_query_hash(shippedtrue; the scoped guarantee is already pinned intest_due_diligence_invariants.py). Docstring now states the toggle and that disabling it is privacy-affecting — doc fixed to match tested behavior, not a behavior change.Invariant / Governance Impact: None — no graph edge, gate auth, sanitizer, or soul path touched.
invariant-guard28/0.#4/#3are the security-relevant ones and neither weakens a control (temp-file hygiene; a doc that now correctly describes an already-tested privacy toggle).Types of changes
Scope note: Out-of-band + support code (ops_runner, harness, llm client, logger docstring).
Benefits / why
Risks to monitor
_write_body's except catches(OSError, UnicodeError)— the realistic write-failure modes; aKeyboardInterruptmid-write still won't clean up (accepted, matches the surrounding code's exception discipline).Further comments
Verified:
ruffclean on all 6 files; 104 passed (test_ops_runner+test_harness+test_audit); both regression tests revert-proven (fail against origin/main source, pass on the fix);invariant-guard28/0. Shares onlytests/test_harness.pywith the open #651 (both append tests, non-adjacent) — trial-merge verified clean, noted below.🤖 Generated with Claude Code
https://claude.ai/code/session_0138hmScu3tFU4v1jzvFUwVT
Generated by Claude Code