feat: fix confirmed findings during scans with native agents - #1365
yoni-at-strix wants to merge 39 commits into
Conversation
Strix Security ReviewAll previously reported security findings have been resolved. 2 resolved findingsReview summaryReviewed the new verified fix-preparation subsystem (strix/fix/contracts.py, locations.py, prepare.py, workspace.py, runtime.py, scan.py), the agent/runtime plumbing it introduces (strix/runtime/agent_session.py, core/execution.py, core/runner.py, core/hooks.py, tools/finish, tools/reporting, tools/processes, session_manager, docker_client, backends), the fix CLI entry points, report/state/SARIF changes, and secret-file handling. The change is defensively constructed: all subprocess and git invocations use argv lists (no shell interpolation); source and checkpoint paths are containment-checked with resolve()+is_relative_to() and reject traversal; tar/zip archives are unpacked via getmember/extractfile rather than extractall; network isolation is enforced at the Docker layer via network_mode="none" with port removal; and secret outputs use an atomic 0600 write path. The two previously reported issues — unenforced network_allowed on the command sandbox and symlink-following path traversal — are resolved in the current code. New prompt surfaces for the Fix agent and independent verifier fence repository/finding/tool data as untrusted with randomized boundaries. No confirmed vulnerabilities were identified in the changed code. Updated for Reviewed by Strix |
|
Comments Outside DiffThese findings could not be posted inline.
|
- Resolve edit/anchor/manifest paths and require workspace containment so committed symlinks cannot redirect reads or writes outside the checkout. - Treat unreadable or non-UTF-8 anchor targets as missing instead of raising, and never let candidate anchoring block report persistence. - Enforce the declared command policy: subprocess env is an allowlist plus credentials_allowed, and commands run in a network namespace (unshare) when network_allowed is false, or are rejected when isolation is unavailable. - Require a clean worktree in addition to a matching HEAD commit so pre-existing uncommitted changes are not attributed to the fix. - Expand untracked directories into per-file manifest entries. - Surface failed optional checks as gaps instead of silent readiness. - SARIF fixes emit only the verified candidate (digest must match the recorded fix_candidate), not the stale draft locations.
|
Fixed in 49eca20. Every consumer path now resolves and containment-checks before touching the filesystem: |
|
Fixed in 49eca20. |
|
Fixed in 49eca20. |
|
Fixed in 49eca20. |
|
Fixed in 49eca20. Non-required checks that did not pass now contribute |
|
Fixed in 49eca20. The request's policy is now threaded into the default command runner: the subprocess environment is an allowlist ( |
|
Fixed in 49eca20. |
|
Fixed in 49eca20 — same change as the thread on |
|
Fixed in 49eca20. |
|
Fixed in 49eca20. |
|
This gate is the point of the PR, not a bug: SARIF |
A report revision whose locations can no longer form a candidate now still supersedes any recorded preparation instead of leaving a ready result pointing at superseded locations. Preparation results carry the candidate that was actually verified so SARIF emits the anchor-corrected edits rather than comparing the stored draft's digest against a re-anchored one.
|
Fixed in 2b413da. |
|
Fixed in 2b413da. |
Repair can change files beyond the candidate's draft edits while the manifest still verifies. Comparing the applied draft hashes against the final manifest now demotes the result to ready_with_gaps, so SARIF and other auto-apply consumers never offer a fix that omits verified changes.
|
Fixed in be1c2e4. Right after |
Summary
Make fix preparation a deterministic scan-runtime responsibility: persisted source-backed findings enqueue exactly once per
(finding_id, candidate_digest), dispatch safely from worker threads onto the owning event loop, replay after restart, and reschedule revised candidates.Before an artifact becomes
READY, a separate reviewer adversarially checks the reported security invariant, bypasses, behavior compatibility, and dependency/toolchain constraints. Readiness is bound to the unchanged final workspace digest, so reviewer mutations or approvals for a stale snapshot fail closed.For open-source source scans, automatic fixes are enabled by default and can be disabled with
--no-auto-fix. After assessment and Fix reconciliation finish, each current approved artifact becomes an idempotent local branch based on the exact scanned commit. Strix does not change the active checkout or push the branch. Final CLI output andrun.jsonlist prepared branches and any publication errors.Validation: 103 affected tests passed; Ruff, mypy, Bandit, formatting, and pre-commit hooks passed. Repository-wide checks still encounter existing unrelated Ruff and Pyright baseline failures.
Part of STR-738
Link to Devin session: https://app.devin.ai/sessions/34237f615e7747eeb6473128f0ab86e3
Open in Devin Desktop: https://app.devin.ai/desktop/session/34237f615e7747eeb6473128f0ab86e3?variant=devin
Requested by: @yoni-at-strix