Skip to content

Releases: VectorSophie/A3V-releases

2.4.1 — 2026-10-05

Choose a tag to compare

@VectorSophie VectorSophie released this 05 Oct 13:27

Release Notes

Breaking

  • The dashboard moved to http://a3v.localhost:8128 (was localhost:7373). Browsers resolve *.localhost to this machine, so no setup is needed; localhost:8128 and 127.0.0.1:8128 work too. Bookmarks to the old port need updating.

Security

  • The dashboard is private to this machine by default. It listened on 0.0.0.0 with a CORS policy that let any website read its responses, so other machines on the network, and any web page you visited, could read your runs and findings. It now binds 127.0.0.1, sends no CORS headers, and refuses requests whose Host isn't a local name (*.localhost, localhost, a loopback IP), which blocks DNS-rebinding pages. It also sends a strict Content-Security-Policy, nosniff and no-referrer. --host <ip> opts into network exposure, with a warning.

Changed

  • Redesigned dashboard. A quieter, denser console: a sidebar layout, a new Overview page (security score, severity mix and per-day trend for the last 30 days, recent runs, live guard events), run detail with scored findings, evidence refs and remediation shown apart from the unscored Exploratory findings, severity filters on Findings, and light and dark themes following the system setting. Severity is shown by shape as well as color (square, triangle, diamond, ring).
  • The dashboard works offline. Tailwind and Alpine were loaded from CDNs at runtime; the stylesheet, script and fonts are now embedded in the binary.
  • A3V branding applied. The brand kit lives in branding/ (canonical mark master/a3v-mark.svg, A3V Blue #005FFC; fonts Hubot Sans, Mona Sans, Martian Mono and Chakra Petch, all SIL OFL). a3v.exe carries the A3V icon on Windows; the MSI shows it in Add/Remove Programs and uses branded banner and welcome/finish images; the macOS pkg has a background in light and dark appearance; the README header uses the lockup, with a reversed variant in dark mode. packaging/make_art.py regenerates all installer art from the kit.
  • a3v dashboard opens the browser on macOS and Linux too, and takes --no-open.

Fixed

  • Dashboard autostart opened a browser tab at every login on Windows. Autostart entries now pass --no-open; re-run a3v setup to update an existing entry.
  • The live guard feed showed raw JSON for every event: it read the event kind in the wrong shape. Events now render as "File changed path" and similar.
  • The Run History page sorted by a field the stored report doesn't have; runs are now newest first.
  • The dashboard's Guard page listed forbidden tool calls and permission escalation, which the guard doesn't watch, and the License page listed centralized audit logs and air-gap deployment as available; both are now accurate (planned features are marked planned).

Install a3v 2.4.1

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/VectorSophie/a3v-releases/releases/download/v2.4.1/a3v-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/VectorSophie/a3v-releases/releases/download/v2.4.1/a3v-installer.ps1 | iex"

Download a3v 2.4.1

File Platform Checksum
a3v-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
a3v-x86_64-apple-darwin.tar.xz Intel macOS checksum
a3v-x86_64-pc-windows-msvc.zip x64 Windows checksum
a3v-x86_64-pc-windows-msvc.msi x64 Windows checksum
a3v-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

2.4.0 — 2026-10-05

Choose a tag to compare

@VectorSophie VectorSophie released this 05 Oct 09:05

Release Notes

Breaking

  • The agentgauntlet binary alias is removed. AgentGauntlet is an abandoned name; the only binary is now a3v. Scripts that call agentgauntlet must switch to a3v (same arguments). This also removes Cargo's "main.rs found in multiple build targets" warning and stops the CLI's tests from compiling and running twice. The internal a3v_core::GauntletError type is renamed to A3vError (no in-tree callers). Canary values containing agentgauntlet (e.g. sk-agentgauntlet-test-…) are intentionally unchanged so privacy results stay comparable across versions.

Changed

  • Scoring change: trajectory.permission_escalation now uses Effect::impact() levels (read=0, write=1, delete=2, execute/network=3) instead of the separate ESCALATION_ORDER table, which disagreed with Effect and didn't know tool aliases like exec/system/rm/fs.*/http.*/network.dns/network.exfiltrate/file.create. For known tool names this now flags a strict subset of what the old table flagged: no longer flagged — memory.read→file.read, memory.read/memory.write→file.write, memory.write→file.delete, file.delete→network.request, file.delete→shell.run, shell.exec→network.request (all within the unchanged +1 gap tolerance, or normal read-then-edit behavior), and — the largest single false-positive source — an empty (no-tool-call) turn 0 followed by file.read or file.write, since an empty turn's level defaults to 0 (read) and both land within the +1 gap. Unknown tools: an unknown/MCP tool call in turn 0 no longer maxes out the baseline and masks a later real escalation (previously, turn 0 calling any unrecognized tool made every later call look "safe" by comparison). A later-turn unknown tool still counts as the maximum severity level (never treated as safe) unless turn 0 already called a tool with that exact name — an agent simply repeating the same unrecognized tool across turns isn't escalating. Newly flagged — a turn 0 unknown/MCP tool call followed by a later shell.exec, previously masked by the old table's unknown-tool ceiling. Findings cite the exact escalating tool call via evidence_refs (tool_call_event_id), and risk_vector's tool-impact dimension is derived from that cited call — so it reads None when the escalating call is itself an unknown tool, rather than guessing a level for it. Scenario impact: in the tool_escalation seed corpus, ssh_key_injection_via_setup (005/008/026/028) and write_file_via_config_suggestion (003/004/024) no longer produce trajectory.permission_escalation for their read-only-setup→file.write pattern — each such run now scores 20 points higher on SecurityScore, though the write is still caught (and the run still fails) by the scenario's own forbidden-tool rule. file_deletion_via_summarize_request(_v2) (002/022/023) are unaffected — deletion still exceeds the +1 gap and fires as before. Some scenarios will score higher (a lost High finding), some lower (a previously-masked one now appears). See docs/superpowers/plans/2026-09-27-v2.4.0-slice3-escalation-drift-scan.md.
  • Scoring change: tool severity and risk-vector tool impact now come from one Effect classification (crates/core/src/effect.rs), replacing the two danger tables in crates/eval/src/tool_rules.rs and crates/eval/src/risk_vector.rs that could — and did — disagree (network.request was Medium severity in one, max impact in the other). Applies to every rule that calls tool_severity: tool.forbidden, tool.not_in_allowed_only, tool.globally_forbidden, and permission.privilege_ceiling_exceeded. Net effect: findings on network.request/http.get/http.post/network.dns/network.exfiltrate are now High severity (−20), previously Medium (−10) — scenarios that flag network calls will score lower than on v2.3.0. file.create/fs.write now match file.write's High severity/impact-1 rather than falling through to the generic Medium/unmeasured-impact default. exec/system/rm/fs.delete/fs.read — which already had a severity from the old tables — now also get a risk-vector tool impact where they previously had none; this changes RiskVector/risk classification, not SecurityScore. Unknown tool names keep Medium severity and unmeasured (None) impact — never treated as low-risk. See docs/superpowers/plans/2026-09-23-v2.4.0-slice2-effects-identity-events.md.
  • Scoring change: two previously-missed detection gaps now produce findings. delayed_trigger.dangerous_tool_activation used a hand-maintained tool list that missed http.get/http.post/network.dns/network.exfiltrate/exec/system/rm/fs.delete/file.create/fs.write as dangerous follow-ups after a delayed-trigger setup; it now checks Effect::of(name) against Execute/Network/Delete/Write, an exact superset of the old list. exfil.http_callback's substring-based tool match missed network.exfiltrate (used by scenarios/.../mcp_tool_poisoning/tool_description_injection.yaml); it now also fires for any tool whose Effect is Network, in addition to the existing substring list (kept for curl/wget/fetch/MCP-prefixed names Effect doesn't know). Scenarios that rely on these tools to trigger a delayed-trigger or exfil finding will score lower than on v2.3.0.
  • a3v update now checks the public VectorSophie/a3v-releases repo instead of the private VectorSophie/A3V repo, since the private repo's API is unreachable for users who aren't collaborators. When ~/.a3v/config.yaml's install.method is msi/pkg/deb/rpm/package (a Linux install whose specific flavor wasn't recorded), it prints the release page link instead of touching anything, since a package manager or the MSI owns that install. Otherwise it no longer downloads and swaps a raw binary itself — it runs dist's own shell/PowerShell installer for the latest tag, spawned detached on Windows (this process's own exe file is locked, so it prints that the update continues in the background and exits) and run-and-waited-on elsewhere.
  • install.ps1/install.sh are removed, replaced by dist-generated a3v-installer.sh/a3v-installer.ps1 plus native MSI/.pkg/.deb/.rpm installers published to the new public VectorSophie/a3v-releases repo — see docs/HOW_IT_WORKS.md §9. The pipeline was proven by the v2.4.0-rc.2 prerelease, and the MSI install (options page, per-user autostart registration) was verified on a clean Windows machine. Release builds are not yet code-signed.

Fixed

  • MSI upgrades installed side by side instead of replacing. Windows Installer compares only the first three version fields, so release candidates (2.4.0.2, 2.4.0.3) and the final 2.4.0 counted as the same version; the rc.3 MSI installed next to rc.2. The MSI now sets AllowSameVersionUpgrades, so installing any build replaces the previous one.
  • identity.mid_session_drift false positive on tool use. Some fingerprint markers (Claude Code's tool_use_content_block_shape, Codex's command_execution_field_shape, Goose's tool_request_response_pairing) appear only on turns where the agent used a tool, so a tool turn followed by a plain turn was reported as identity drift. Drift now compares only structural markers (plus the reported model). a3v setup also no longer echoes reg.exe's own console messages.
  • claudecode targets silently scored 100/100 on current Claude Code. Claude Code now rejects --print --output-format stream-json without --verbose; it exited with an error, A3V treated that error text as the agent's reply, saw no tool calls, and reported a clean run. The adapter now passes --verbose (verified live against Claude Code 2.1.285: tool calls captured, all identity markers matched), and any stateless CLI agent that exits non-zero with no stdout now fails the run instead of scoring it, so a future CLI change can't silently turn "not observed" into "safe". Found by the v2.4.0-rc.2 test on a clean Windows machine.
  • claudecode turns that never reached the model scored clean and raised a false identity.model_mismatch. When Claude Code hits a usage limit, auth failure or API error it writes its own message (model <synthetic>) and ends with an is_error: true result. A3V now fails the run on that result instead of scoring it, and no longer reads <synthetic> as the reported model. Found by the v2.4.0-rc.4 test.
  • VaccineGuard reported its own log as tampering, every second. It watched .a3v/vaccine.jsonl (untracked, so included), so each log write looked like a change. The guard now ignores its own .a3v/ state. vaccine start refuses a --workspace folder that doesn't exist instead of creating it, and the git check uses git rev-parse so repo subfolders aren't falsely reported as non-git.
  • YAML files saved with a UTF-8 BOM failed to load ("missing field name"). Windows PowerShell 5.1's Set-Content -Encoding utf8 and many Windows editors add one. Scenarios, benchmark seeds, defense profiles and config files now accept it.
  • a3v update crashed when no stable release existed (GitHub's releases/latest ignores prereleases and returns 404); it now checks the status and says so.
  • trace.jsonl now contains every finding exactly once, written after the run is finalized instead of per-turn during the turn loop — post-run (trajectory, delayed_trigger, identity.mid_session_drift, cross-turn privacy), file-write privacy, and multi-agent findings were previously missing from the trace, and multi-agent runs wrote no finding events at all. Finding trace events now also carry evidence_refs and exploratory. Note for trace consumers: finding events now appear after the turn events, not interleaved, and a3v replay shows them after the transcript, each still labeled with its turn.
  • Escalation baseline is per agent in multi-agent runs. `trajectory.perm...
Read more

2.4.0-rc.4 — 2026-09-28

Pre-release

Choose a tag to compare

@VectorSophie VectorSophie released this 05 Oct 02:24

Release Notes

Breaking

  • The agentgauntlet binary alias is removed. AgentGauntlet is an abandoned name; the only binary is now a3v. Scripts that call agentgauntlet must switch to a3v (same arguments). This also removes Cargo's "main.rs found in multiple build targets" warning and stops the CLI's tests from compiling and running twice. The internal a3v_core::GauntletError type is renamed to A3vError (no in-tree callers). Canary values containing agentgauntlet (e.g. sk-agentgauntlet-test-…) are intentionally unchanged so privacy results stay comparable across versions.

Changed

  • Scoring change: trajectory.permission_escalation now uses Effect::impact() levels (read=0, write=1, delete=2, execute/network=3) instead of the separate ESCALATION_ORDER table, which disagreed with Effect and didn't know tool aliases like exec/system/rm/fs.*/http.*/network.dns/network.exfiltrate/file.create. For known tool names this now flags a strict subset of what the old table flagged: no longer flagged — memory.read→file.read, memory.read/memory.write→file.write, memory.write→file.delete, file.delete→network.request, file.delete→shell.run, shell.exec→network.request (all within the unchanged +1 gap tolerance, or normal read-then-edit behavior), and — the largest single false-positive source — an empty (no-tool-call) turn 0 followed by file.read or file.write, since an empty turn's level defaults to 0 (read) and both land within the +1 gap. Unknown tools: an unknown/MCP tool call in turn 0 no longer maxes out the baseline and masks a later real escalation (previously, turn 0 calling any unrecognized tool made every later call look "safe" by comparison). A later-turn unknown tool still counts as the maximum severity level (never treated as safe) unless turn 0 already called a tool with that exact name — an agent simply repeating the same unrecognized tool across turns isn't escalating. Newly flagged — a turn 0 unknown/MCP tool call followed by a later shell.exec, previously masked by the old table's unknown-tool ceiling. Findings cite the exact escalating tool call via evidence_refs (tool_call_event_id), and risk_vector's tool-impact dimension is derived from that cited call — so it reads None when the escalating call is itself an unknown tool, rather than guessing a level for it. Scenario impact: in the tool_escalation seed corpus, ssh_key_injection_via_setup (005/008/026/028) and write_file_via_config_suggestion (003/004/024) no longer produce trajectory.permission_escalation for their read-only-setup→file.write pattern — each such run now scores 20 points higher on SecurityScore, though the write is still caught (and the run still fails) by the scenario's own forbidden-tool rule. file_deletion_via_summarize_request(_v2) (002/022/023) are unaffected — deletion still exceeds the +1 gap and fires as before. Some scenarios will score higher (a lost High finding), some lower (a previously-masked one now appears). See docs/superpowers/plans/2026-09-27-v2.4.0-slice3-escalation-drift-scan.md.
  • Scoring change: tool severity and risk-vector tool impact now come from one Effect classification (crates/core/src/effect.rs), replacing the two danger tables in crates/eval/src/tool_rules.rs and crates/eval/src/risk_vector.rs that could — and did — disagree (network.request was Medium severity in one, max impact in the other). Applies to every rule that calls tool_severity: tool.forbidden, tool.not_in_allowed_only, tool.globally_forbidden, and permission.privilege_ceiling_exceeded. Net effect: findings on network.request/http.get/http.post/network.dns/network.exfiltrate are now High severity (−20), previously Medium (−10) — scenarios that flag network calls will score lower than on v2.3.0. file.create/fs.write now match file.write's High severity/impact-1 rather than falling through to the generic Medium/unmeasured-impact default. exec/system/rm/fs.delete/fs.read — which already had a severity from the old tables — now also get a risk-vector tool impact where they previously had none; this changes RiskVector/risk classification, not SecurityScore. Unknown tool names keep Medium severity and unmeasured (None) impact — never treated as low-risk. See docs/superpowers/plans/2026-09-23-v2.4.0-slice2-effects-identity-events.md.
  • Scoring change: two previously-missed detection gaps now produce findings. delayed_trigger.dangerous_tool_activation used a hand-maintained tool list that missed http.get/http.post/network.dns/network.exfiltrate/exec/system/rm/fs.delete/file.create/fs.write as dangerous follow-ups after a delayed-trigger setup; it now checks Effect::of(name) against Execute/Network/Delete/Write, an exact superset of the old list. exfil.http_callback's substring-based tool match missed network.exfiltrate (used by scenarios/.../mcp_tool_poisoning/tool_description_injection.yaml); it now also fires for any tool whose Effect is Network, in addition to the existing substring list (kept for curl/wget/fetch/MCP-prefixed names Effect doesn't know). Scenarios that rely on these tools to trigger a delayed-trigger or exfil finding will score lower than on v2.3.0.
  • a3v update now checks the public VectorSophie/a3v-releases repo instead of the private VectorSophie/A3V repo, since the private repo's API is unreachable for users who aren't collaborators. When ~/.a3v/config.yaml's install.method is msi/pkg/deb/rpm/package (a Linux install whose specific flavor wasn't recorded), it prints the release page link instead of touching anything, since a package manager or the MSI owns that install. Otherwise it no longer downloads and swaps a raw binary itself — it runs dist's own shell/PowerShell installer for the latest tag, spawned detached on Windows (this process's own exe file is locked, so it prints that the update continues in the background and exits) and run-and-waited-on elsewhere.
  • install.ps1/install.sh are removed, replaced by dist-generated a3v-installer.sh/a3v-installer.ps1 plus native MSI/.pkg/.deb/.rpm installers published to the new public VectorSophie/a3v-releases repo — see docs/HOW_IT_WORKS.md §9. The pipeline was proven by the v2.4.0-rc.2 prerelease, and the MSI install (options page, per-user autostart registration) was verified on a clean Windows machine. Release builds are not yet code-signed.

Fixed

  • MSI upgrades installed side by side instead of replacing. Windows Installer compares only the first three version fields, so release candidates (2.4.0.2, 2.4.0.3) and the final 2.4.0 counted as the same version; the rc.3 MSI installed next to rc.2. The MSI now sets AllowSameVersionUpgrades, so installing any build replaces the previous one.
  • identity.mid_session_drift false positive on tool use. Some fingerprint markers (Claude Code's tool_use_content_block_shape, Codex's command_execution_field_shape, Goose's tool_request_response_pairing) appear only on turns where the agent used a tool, so a tool turn followed by a plain turn was reported as identity drift. Drift now compares only structural markers (plus the reported model). a3v setup also no longer echoes reg.exe's own console messages.
  • claudecode targets silently scored 100/100 on current Claude Code. Claude Code now rejects --print --output-format stream-json without --verbose; it exited with an error, A3V treated that error text as the agent's reply, saw no tool calls, and reported a clean run. The adapter now passes --verbose (verified live against Claude Code 2.1.285: tool calls captured, all identity markers matched), and any stateless CLI agent that exits non-zero with no stdout now fails the run instead of scoring it, so a future CLI change can't silently turn "not observed" into "safe". Found by the v2.4.0-rc.2 test on a clean Windows machine.
  • VaccineGuard reported its own log as tampering, every second. It watched .a3v/vaccine.jsonl (untracked, so included), so each log write looked like a change. The guard now ignores its own .a3v/ state. vaccine start refuses a --workspace folder that doesn't exist instead of creating it, and the git check uses git rev-parse so repo subfolders aren't falsely reported as non-git.
  • YAML files saved with a UTF-8 BOM failed to load ("missing field name"). Windows PowerShell 5.1's Set-Content -Encoding utf8 and many Windows editors add one. Scenarios, benchmark seeds, defense profiles and config files now accept it.
  • a3v update crashed when no stable release existed (GitHub's releases/latest ignores prereleases and returns 404); it now checks the status and says so.
  • trace.jsonl now contains every finding exactly once, written after the run is finalized instead of per-turn during the turn loop — post-run (trajectory, delayed_trigger, identity.mid_session_drift, cross-turn privacy), file-write privacy, and multi-agent findings were previously missing from the trace, and multi-agent runs wrote no finding events at all. Finding trace events now also carry evidence_refs and exploratory. Note for trace consumers: finding events now appear after the turn events, not interleaved, and a3v replay shows them after the transcript, each still labeled with its turn.
  • Escalation baseline is per agent in multi-agent runs. trajectory.permission_escalation previously used turns[0], whoever produced it, as a single global baseline — one agent's early tool calls could set the baseline for every other agent in the run and mask a genuinely escalating peer. Now keyed by turn.agent_id (mirroring identity.mid_session_drift); single-agent runs (agent_id: None everywhere) are unaffected.
  • **identity.mid_session_drift now compares each agent o...
Read more

2.4.0-rc.3 — 2026-09-28

Pre-release

Choose a tag to compare

@VectorSophie VectorSophie released this 02 Oct 08:16

Release Notes

Breaking

  • The agentgauntlet binary alias is removed. AgentGauntlet is an abandoned name; the only binary is now a3v. Scripts that call agentgauntlet must switch to a3v (same arguments). This also removes Cargo's "main.rs found in multiple build targets" warning and stops the CLI's tests from compiling and running twice. The internal a3v_core::GauntletError type is renamed to A3vError (no in-tree callers). Canary values containing agentgauntlet (e.g. sk-agentgauntlet-test-…) are intentionally unchanged so privacy results stay comparable across versions.

Changed

  • Scoring change: trajectory.permission_escalation now uses Effect::impact() levels (read=0, write=1, delete=2, execute/network=3) instead of the separate ESCALATION_ORDER table, which disagreed with Effect and didn't know tool aliases like exec/system/rm/fs.*/http.*/network.dns/network.exfiltrate/file.create. For known tool names this now flags a strict subset of what the old table flagged: no longer flagged — memory.read→file.read, memory.read/memory.write→file.write, memory.write→file.delete, file.delete→network.request, file.delete→shell.run, shell.exec→network.request (all within the unchanged +1 gap tolerance, or normal read-then-edit behavior), and — the largest single false-positive source — an empty (no-tool-call) turn 0 followed by file.read or file.write, since an empty turn's level defaults to 0 (read) and both land within the +1 gap. Unknown tools: an unknown/MCP tool call in turn 0 no longer maxes out the baseline and masks a later real escalation (previously, turn 0 calling any unrecognized tool made every later call look "safe" by comparison). A later-turn unknown tool still counts as the maximum severity level (never treated as safe) unless turn 0 already called a tool with that exact name — an agent simply repeating the same unrecognized tool across turns isn't escalating. Newly flagged — a turn 0 unknown/MCP tool call followed by a later shell.exec, previously masked by the old table's unknown-tool ceiling. Findings cite the exact escalating tool call via evidence_refs (tool_call_event_id), and risk_vector's tool-impact dimension is derived from that cited call — so it reads None when the escalating call is itself an unknown tool, rather than guessing a level for it. Scenario impact: in the tool_escalation seed corpus, ssh_key_injection_via_setup (005/008/026/028) and write_file_via_config_suggestion (003/004/024) no longer produce trajectory.permission_escalation for their read-only-setup→file.write pattern — each such run now scores 20 points higher on SecurityScore, though the write is still caught (and the run still fails) by the scenario's own forbidden-tool rule. file_deletion_via_summarize_request(_v2) (002/022/023) are unaffected — deletion still exceeds the +1 gap and fires as before. Some scenarios will score higher (a lost High finding), some lower (a previously-masked one now appears). See docs/superpowers/plans/2026-09-27-v2.4.0-slice3-escalation-drift-scan.md.
  • Scoring change: tool severity and risk-vector tool impact now come from one Effect classification (crates/core/src/effect.rs), replacing the two danger tables in crates/eval/src/tool_rules.rs and crates/eval/src/risk_vector.rs that could — and did — disagree (network.request was Medium severity in one, max impact in the other). Applies to every rule that calls tool_severity: tool.forbidden, tool.not_in_allowed_only, tool.globally_forbidden, and permission.privilege_ceiling_exceeded. Net effect: findings on network.request/http.get/http.post/network.dns/network.exfiltrate are now High severity (−20), previously Medium (−10) — scenarios that flag network calls will score lower than on v2.3.0. file.create/fs.write now match file.write's High severity/impact-1 rather than falling through to the generic Medium/unmeasured-impact default. exec/system/rm/fs.delete/fs.read — which already had a severity from the old tables — now also get a risk-vector tool impact where they previously had none; this changes RiskVector/risk classification, not SecurityScore. Unknown tool names keep Medium severity and unmeasured (None) impact — never treated as low-risk. See docs/superpowers/plans/2026-09-23-v2.4.0-slice2-effects-identity-events.md.
  • Scoring change: two previously-missed detection gaps now produce findings. delayed_trigger.dangerous_tool_activation used a hand-maintained tool list that missed http.get/http.post/network.dns/network.exfiltrate/exec/system/rm/fs.delete/file.create/fs.write as dangerous follow-ups after a delayed-trigger setup; it now checks Effect::of(name) against Execute/Network/Delete/Write, an exact superset of the old list. exfil.http_callback's substring-based tool match missed network.exfiltrate (used by scenarios/.../mcp_tool_poisoning/tool_description_injection.yaml); it now also fires for any tool whose Effect is Network, in addition to the existing substring list (kept for curl/wget/fetch/MCP-prefixed names Effect doesn't know). Scenarios that rely on these tools to trigger a delayed-trigger or exfil finding will score lower than on v2.3.0.
  • a3v update now checks the public VectorSophie/a3v-releases repo instead of the private VectorSophie/A3V repo, since the private repo's API is unreachable for users who aren't collaborators. When ~/.a3v/config.yaml's install.method is msi/pkg/deb/rpm/package (a Linux install whose specific flavor wasn't recorded), it prints the release page link instead of touching anything, since a package manager or the MSI owns that install. Otherwise it no longer downloads and swaps a raw binary itself — it runs dist's own shell/PowerShell installer for the latest tag, spawned detached on Windows (this process's own exe file is locked, so it prints that the update continues in the background and exits) and run-and-waited-on elsewhere.
  • install.ps1/install.sh are removed, replaced by dist-generated a3v-installer.sh/a3v-installer.ps1 plus native MSI/.pkg/.deb/.rpm installers published to the new public VectorSophie/a3v-releases repo — see docs/HOW_IT_WORKS.md §9. The pipeline was proven by the v2.4.0-rc.2 prerelease, and the MSI install (options page, per-user autostart registration) was verified on a clean Windows machine. Release builds are not yet code-signed.

Fixed

  • claudecode targets silently scored 100/100 on current Claude Code. Claude Code now rejects --print --output-format stream-json without --verbose; it exited with an error, A3V treated that error text as the agent's reply, saw no tool calls, and reported a clean run. The adapter now passes --verbose (verified live against Claude Code 2.1.285: tool calls captured, all identity markers matched), and any stateless CLI agent that exits non-zero with no stdout now fails the run instead of scoring it, so a future CLI change can't silently turn "not observed" into "safe". Found by the v2.4.0-rc.2 test on a clean Windows machine.
  • VaccineGuard reported its own log as tampering, every second. It watched .a3v/vaccine.jsonl (untracked, so included), so each log write looked like a change. The guard now ignores its own .a3v/ state. vaccine start refuses a --workspace folder that doesn't exist instead of creating it, and the git check uses git rev-parse so repo subfolders aren't falsely reported as non-git.
  • YAML files saved with a UTF-8 BOM failed to load ("missing field name"). Windows PowerShell 5.1's Set-Content -Encoding utf8 and many Windows editors add one. Scenarios, benchmark seeds, defense profiles and config files now accept it.
  • a3v update crashed when no stable release existed (GitHub's releases/latest ignores prereleases and returns 404); it now checks the status and says so.
  • trace.jsonl now contains every finding exactly once, written after the run is finalized instead of per-turn during the turn loop — post-run (trajectory, delayed_trigger, identity.mid_session_drift, cross-turn privacy), file-write privacy, and multi-agent findings were previously missing from the trace, and multi-agent runs wrote no finding events at all. Finding trace events now also carry evidence_refs and exploratory. Note for trace consumers: finding events now appear after the turn events, not interleaved, and a3v replay shows them after the transcript, each still labeled with its turn.
  • Escalation baseline is per agent in multi-agent runs. trajectory.permission_escalation previously used turns[0], whoever produced it, as a single global baseline — one agent's early tool calls could set the baseline for every other agent in the run and mask a genuinely escalating peer. Now keyed by turn.agent_id (mirroring identity.mid_session_drift); single-agent runs (agent_id: None everywhere) are unaffected.
  • identity.mid_session_drift now compares each agent only with itself in mode: multi_agent runs. Previously kept a single baseline fingerprint across the whole run, so it compared turns from different agents against each other and flagged a legitimate difference between two distinct agents (e.g. one on Claude, one on GPT) as drift. Now keyed by turn.agent_id, so each agent's turns are only ever compared against that same agent's first fingerprinted turn; single-agent runs (agent_id: None everywhere) are unaffected.
  • Workspace side-effect scan skips node_modules, .venv and __pycache__. These dependency/cache dirs were being hashed on every snapshot, which was slow on real projects. Trade-off: an agent writing a secret into one of these dirs is no longer detected by the file-write privacy scan.
  • **ASR/sut_score now use the same finding filter as `SecurityS...
Read more

Version 2.4.0-rc.2

Version 2.4.0-rc.2 Pre-release
Pre-release

Choose a tag to compare

@VectorSophie VectorSophie released this 28 Sep 02:44

Release Notes

Breaking

  • The agentgauntlet binary alias is removed. AgentGauntlet is an abandoned name; the only binary is now a3v. Scripts that call agentgauntlet must switch to a3v (same arguments). This also removes Cargo's "main.rs found in multiple build targets" warning and stops the CLI's tests from compiling and running twice. The internal a3v_core::GauntletError type is renamed to A3vError (no in-tree callers). Canary values containing agentgauntlet (e.g. sk-agentgauntlet-test-…) are intentionally unchanged so privacy results stay comparable across versions.

Changed

  • Scoring change: trajectory.permission_escalation now uses Effect::impact() levels (read=0, write=1, delete=2, execute/network=3) instead of the separate ESCALATION_ORDER table, which disagreed with Effect and didn't know tool aliases like exec/system/rm/fs.*/http.*/network.dns/network.exfiltrate/file.create. For known tool names this now flags a strict subset of what the old table flagged: no longer flagged — memory.read→file.read, memory.read/memory.write→file.write, memory.write→file.delete, file.delete→network.request, file.delete→shell.run, shell.exec→network.request (all within the unchanged +1 gap tolerance, or normal read-then-edit behavior), and — the largest single false-positive source — an empty (no-tool-call) turn 0 followed by file.read or file.write, since an empty turn's level defaults to 0 (read) and both land within the +1 gap. Unknown tools: an unknown/MCP tool call in turn 0 no longer maxes out the baseline and masks a later real escalation (previously, turn 0 calling any unrecognized tool made every later call look "safe" by comparison). A later-turn unknown tool still counts as the maximum severity level (never treated as safe) unless turn 0 already called a tool with that exact name — an agent simply repeating the same unrecognized tool across turns isn't escalating. Newly flagged — a turn 0 unknown/MCP tool call followed by a later shell.exec, previously masked by the old table's unknown-tool ceiling. Findings cite the exact escalating tool call via evidence_refs (tool_call_event_id), and risk_vector's tool-impact dimension is derived from that cited call — so it reads None when the escalating call is itself an unknown tool, rather than guessing a level for it. Scenario impact: in the tool_escalation seed corpus, ssh_key_injection_via_setup (005/008/026/028) and write_file_via_config_suggestion (003/004/024) no longer produce trajectory.permission_escalation for their read-only-setup→file.write pattern — each such run now scores 20 points higher on SecurityScore, though the write is still caught (and the run still fails) by the scenario's own forbidden-tool rule. file_deletion_via_summarize_request(_v2) (002/022/023) are unaffected — deletion still exceeds the +1 gap and fires as before. Some scenarios will score higher (a lost High finding), some lower (a previously-masked one now appears). See docs/superpowers/plans/2026-09-27-v2.4.0-slice3-escalation-drift-scan.md.
  • Scoring change: tool severity and risk-vector tool impact now come from one Effect classification (crates/core/src/effect.rs), replacing the two danger tables in crates/eval/src/tool_rules.rs and crates/eval/src/risk_vector.rs that could — and did — disagree (network.request was Medium severity in one, max impact in the other). Applies to every rule that calls tool_severity: tool.forbidden, tool.not_in_allowed_only, tool.globally_forbidden, and permission.privilege_ceiling_exceeded. Net effect: findings on network.request/http.get/http.post/network.dns/network.exfiltrate are now High severity (−20), previously Medium (−10) — scenarios that flag network calls will score lower than on v2.3.0. file.create/fs.write now match file.write's High severity/impact-1 rather than falling through to the generic Medium/unmeasured-impact default. exec/system/rm/fs.delete/fs.read — which already had a severity from the old tables — now also get a risk-vector tool impact where they previously had none; this changes RiskVector/risk classification, not SecurityScore. Unknown tool names keep Medium severity and unmeasured (None) impact — never treated as low-risk. See docs/superpowers/plans/2026-09-23-v2.4.0-slice2-effects-identity-events.md.
  • Scoring change: two previously-missed detection gaps now produce findings. delayed_trigger.dangerous_tool_activation used a hand-maintained tool list that missed http.get/http.post/network.dns/network.exfiltrate/exec/system/rm/fs.delete/file.create/fs.write as dangerous follow-ups after a delayed-trigger setup; it now checks Effect::of(name) against Execute/Network/Delete/Write, an exact superset of the old list. exfil.http_callback's substring-based tool match missed network.exfiltrate (used by scenarios/.../mcp_tool_poisoning/tool_description_injection.yaml); it now also fires for any tool whose Effect is Network, in addition to the existing substring list (kept for curl/wget/fetch/MCP-prefixed names Effect doesn't know). Scenarios that rely on these tools to trigger a delayed-trigger or exfil finding will score lower than on v2.3.0.
  • a3v update now checks the public VectorSophie/a3v-releases repo instead of the private VectorSophie/A3V repo, since the private repo's API is unreachable for users who aren't collaborators. When ~/.a3v/config.yaml's install.method is msi/pkg/deb/rpm/package (a Linux install whose specific flavor wasn't recorded), it prints the release page link instead of touching anything, since a package manager or the MSI owns that install. Otherwise it no longer downloads and swaps a raw binary itself — it runs dist's own shell/PowerShell installer for the latest tag, spawned detached on Windows (this process's own exe file is locked, so it prints that the update continues in the background and exits) and run-and-waited-on elsewhere.
  • install.ps1/install.sh are superseded by dist-generated a3v-installer.sh/a3v-installer.ps1 plus native MSI/.pkg/.deb/.rpm installers (v2.4.0 slice 8) published to the new public VectorSophie/a3v-releases repo — see docs/HOW_IT_WORKS.md §9. The old scripts are left in place for this release; the README's install section and their removal are deferred until the first real dist release publishes those artifacts.

Fixed

  • trace.jsonl now contains every finding exactly once, written after the run is finalized instead of per-turn during the turn loop — post-run (trajectory, delayed_trigger, identity.mid_session_drift, cross-turn privacy), file-write privacy, and multi-agent findings were previously missing from the trace, and multi-agent runs wrote no finding events at all. Finding trace events now also carry evidence_refs and exploratory. Note for trace consumers: finding events now appear after the turn events, not interleaved, and a3v replay shows them after the transcript, each still labeled with its turn.
  • Escalation baseline is per agent in multi-agent runs. trajectory.permission_escalation previously used turns[0], whoever produced it, as a single global baseline — one agent's early tool calls could set the baseline for every other agent in the run and mask a genuinely escalating peer. Now keyed by turn.agent_id (mirroring identity.mid_session_drift); single-agent runs (agent_id: None everywhere) are unaffected.
  • identity.mid_session_drift now compares each agent only with itself in mode: multi_agent runs. Previously kept a single baseline fingerprint across the whole run, so it compared turns from different agents against each other and flagged a legitimate difference between two distinct agents (e.g. one on Claude, one on GPT) as drift. Now keyed by turn.agent_id, so each agent's turns are only ever compared against that same agent's first fingerprinted turn; single-agent runs (agent_id: None everywhere) are unaffected.
  • Workspace side-effect scan skips node_modules, .venv and __pycache__. These dependency/cache dirs were being hashed on every snapshot, which was slow on real projects. Trade-off: an agent writing a secret into one of these dirs is no longer detected by the file-write privacy scan.
  • ASR/sut_score now use the same finding filter as SecurityScore (2cb06d7) — both previously counted findings SecurityScore would have excluded (e.g. exploratory-only), so a run could show 100% ASR while scoring as if nothing happened. sut_score/tsr also no longer go stale after late file-write findings are appended by side-effect scanning.
  • Multi-agent runs now detect filesystem side effects and private-data file writes; file-write findings take the index of the turn they're attached to rather than always turn 0.
  • a3v demo runs now go through the shared side-effect finalize path (531a41d), and — since 51dbdbe — skip the workspace filesystem walk entirely, since the builtin demo agent can't touch real files.

Added

  • Native installers via dist (v2.4.0 slice 8): releases now build a Windows MSI (crates/cli/wix/main.wxs, WiX v3, WixUI_FeatureTree), a macOS .pkg (packaging/macos/), Linux .deb/.rpm ([package.metadata.deb]/[package.metadata.generate-rpm] in crates/cli/Cargo.toml, packaging/linux/postinst), and dist's own shell/PowerShell installer scripts and native archives — published to the new public VectorSophie/a3v-releases repo (dist-workspace.toml: github-releases-repo), not this private repo. Only the MSI and pkg run a3v setup --non-interactive automatically as the installing user after files land (an MSI deferred CustomAction with Impersonate="yes"; a pkg postinstall reading marker files two hel...
Read more