From e1456b17c6c99d7a0b99135962509b8472b5a520 Mon Sep 17 00:00:00 2001 From: chaksaray Date: Thu, 5 Nov 2026 06:03:34 +0700 Subject: [PATCH 1/5] docs: AIVSS v0.8 conformance statement and pilot (#446) Signed-off-by: chaksaray --- docs/audits/aivss-v0.8-pilot.json | 311 +++++++++++++++++++++++++ docs/audits/aivss-v0.8-pilot.md | 208 +++++++++++++++++ docs/specs/aivss-v0.8-conformance.md | 328 +++++++++++++++++++++++++++ 3 files changed, 847 insertions(+) create mode 100644 docs/audits/aivss-v0.8-pilot.json create mode 100644 docs/audits/aivss-v0.8-pilot.md create mode 100644 docs/specs/aivss-v0.8-conformance.md diff --git a/docs/audits/aivss-v0.8-pilot.json b/docs/audits/aivss-v0.8-pilot.json new file mode 100644 index 0000000..236205d --- /dev/null +++ b/docs/audits/aivss-v0.8-pilot.json @@ -0,0 +1,311 @@ +{ + "metadata": { + "system_name": "AVE catalog pilot: reference deployment profile (S01)", + "system_version": "AVE develop 0753b2d", + "assessment_date": "2026-11-04", + "assessor_id": "ave-s01-pilot", + "notes": "Class-level assessment of ten AVE records for the AIVSS v0.8 conformance pilot; see docs/audits/aivss-v0.8-pilot.md." + }, + "vulnerabilities": [ + { + "id": "AVE-2026-00001", + "title": "Metamorphic payload via external config fetch", + "description": "A skill or MCP component fetches its instructions from an external URL at runtime. The fetched content replaces the original instructions, allowing an attacker to change the component's behavior after it passes a security review. The attack is invisible to static scanners because the malicious payload does not exist at scan time.", + "owasp_category": "Agent Supply Chain & Dependency Risk", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N", + "score": 9.3 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 1, + "language": 1, + "context": 1, + "non_determinism": 0.5, + "opacity": 1, + "persistence": 0.5, + "identity": 0, + "multi_agent": 0, + "self_mod": 1 + }, + "threat_multiplier": 0.97, + "scores": { + "factor_sum": 7.0, + "aars": 0.4753, + "mitigation_factor": 1.0, + "aivss": 9.8, + "severity": "Critical" + } + }, + { + "id": "AVE-2026-00019", + "title": "Agent Memory Poisoning", + "description": "Many agentic systems maintain persistent memory across conversations - storing user preferences, past decisions, and learned facts. A component that can write to this memory store can plant false beliefs or malicious instructions that will influence the agent's behaviour in all subsequent sessions, long after the initial attack.", + "owasp_category": "Agent Memory & Context Manipulation", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N", + "score": 7.0 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 0.5, + "language": 1, + "context": 1, + "non_determinism": 0.5, + "opacity": 1, + "persistence": 1, + "identity": 0, + "multi_agent": 0, + "self_mod": 1 + }, + "threat_multiplier": 0.97, + "scores": { + "factor_sum": 7.0, + "aars": 2.037, + "mitigation_factor": 1.0, + "aivss": 9.0, + "severity": "Critical" + } + }, + { + "id": "AVE-2026-00020", + "title": "Cross-Agent Prompt Injection (A2A)", + "description": "In agentic pipelines where one agent delegates tasks to sub-agents (A2A - Agent to Agent), the output of the first agent becomes the input of the second. A malicious component in the first agent's context can craft output that contains instructions designed to be interpreted as commands by the sub-agent, bypassing the orchestrator's safety controls. This record shares its underlying failure with AVE-2026-00002, AVE-2026-00016, AVE-2026-00028, AVE-2026-00041, AVE-2026-00043, AVE-2026-00044, and AVE-2026-00065: the same missing content-versus-instruction boundary, realized here at a sub-agent's input, where one agent's output becomes the next agent's trusted instruction stream in an A2A delegation chain.", + "owasp_category": "Agent Orchestration & Multi-Agent Exploitation", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:H/SI:H/SA:N", + "score": 8.3 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 0.5, + "language": 1, + "context": 1, + "non_determinism": 1, + "opacity": 1, + "persistence": 0, + "identity": 0.5, + "multi_agent": 1, + "self_mod": 0 + }, + "threat_multiplier": 0.97, + "scores": { + "factor_sum": 7.0, + "aars": 1.1543, + "mitigation_factor": 1.0, + "aivss": 9.5, + "severity": "Critical" + } + }, + { + "id": "AVE-2026-00024", + "title": "Supply Chain - Content Type Mismatch (Magika)", + "description": "This record covers supply chain attacks where an executable payload is disguised as a skill file (`.md`, `.yaml`, `.json`, `.txt`). Unlike all other AVE records which are detected by text pattern matching, this record is detected exclusively by the **Magika engine (Stage 0)** - Google's ML-based file type classifier - because the file contains no readable text instructions to match against. Detection requires a scanning tool integrated with Magika or an equivalent ML-based file type classifier.", + "owasp_category": "Agent Supply Chain & Dependency Risk", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N", + "score": 7.5 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 1, + "language": 0, + "context": 0, + "non_determinism": 0, + "opacity": 1, + "persistence": 0.5, + "identity": 0, + "multi_agent": 0, + "self_mod": 0 + }, + "threat_multiplier": 0.5, + "scores": { + "factor_sum": 3.5, + "aars": 0.4375, + "mitigation_factor": 1.0, + "aivss": 7.9, + "severity": "High" + } + }, + { + "id": "AVE-2026-00039", + "title": "Covert Channel - Steganographic Data Exfiltration", + "description": "Direct exfiltration attempts (HTTP requests to attacker-controlled endpoints) are relatively easy to detect. Covert channels are harder to spot: an attacker can instruct the agent to encode sensitive data in the first letter of each sentence, encode secrets in whitespace patterns, or vary response timing to transmit bits through a side channel. The output looks benign to a human reviewer.", + "owasp_category": "Agent Goal & Instruction Manipulation", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:A/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N", + "score": 5.9 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 0.5, + "language": 0.5, + "context": 0.5, + "non_determinism": 0.5, + "opacity": 1, + "persistence": 0, + "identity": 0, + "multi_agent": 0, + "self_mod": 0 + }, + "threat_multiplier": 0.5, + "scores": { + "factor_sum": 4.0, + "aars": 0.82, + "mitigation_factor": 1.0, + "aivss": 6.7, + "severity": "Medium" + } + }, + { + "id": "AVE-2026-00044", + "title": "Prompt injection via poisoned async task result injected into future agent context", + "description": "Agentic workflows increasingly use async task queues where the agent dispatches a task, continues other work, and later reads the result. An attacker who controls the task result delivery mechanism (a queue, webhook, or polling endpoint) injects malicious instructions into the result payload. When the agent reads the result in a future turn, the injected content is interpreted as trusted context from a completed task - not as external untrusted input. The temporal gap between task dispatch and result consumption bypasses synchronous safety checks. This record shares its underlying failure with AVE-2026-00002, AVE-2026-00016, AVE-2026-00020, AVE-2026-00028, AVE-2026-00041, AVE-2026-00043, and AVE-2026-00065: the same missing content-versus-instruction boundary, realized here at an async task result payload, read across a temporal gap as trusted completed-task context rather than external input.", + "owasp_category": "Agent Goal & Instruction Manipulation", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N", + "score": 9.1 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 1, + "language": 1, + "context": 1, + "non_determinism": 1, + "opacity": 1, + "persistence": 0.5, + "identity": 0.5, + "multi_agent": 0.5, + "self_mod": 0.5 + }, + "threat_multiplier": 1.0, + "scores": { + "factor_sum": 8.0, + "aars": 0.72, + "mitigation_factor": 1.0, + "aivss": 9.8, + "severity": "Critical" + } + }, + { + "id": "AVE-2026-00046", + "title": "MCP tool hook hijacking - redirect tool execution to attacker-controlled callback", + "description": "A malicious skill file or MCP component registers hooks that intercept or redirect tool execution calls to attacker-controlled callbacks before or instead of the legitimate tool handler. Because MCP clients dispatch tool calls through a central registry, a hook registered early in the session can silently intercept all subsequent tool invocations including those from other skills and system tools. The agent continues to believe it is calling the legitimate tool. The hook may pass calls through to the real handler as a transparent proxy or drop them silently.", + "owasp_category": "Agentic AI Tool Misuse", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L", + "score": 9.3 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 1, + "language": 1, + "context": 1, + "non_determinism": 0.5, + "opacity": 1, + "persistence": 0.5, + "identity": 0.5, + "multi_agent": 0.5, + "self_mod": 1 + }, + "threat_multiplier": 0.5, + "scores": { + "factor_sum": 8.0, + "aars": 0.28, + "mitigation_factor": 1.0, + "aivss": 9.6, + "severity": "Critical" + } + }, + { + "id": "AVE-2026-00058", + "title": "Deceptive skill trigger or activation-scope manipulation via misleading manifest description", + "description": "A skill's manifest-declared description, trigger phrases, or activation keywords misrepresent the skill's actual scope or purpose, causing the agent or its orchestrator to invoke the skill in a broader range of contexts than its real behavior warrants, or to invoke it implicitly when the user did not intend to engage it. Distinct from AVE-2026-00002 and AVE-2026-00041, which cover instructions embedded in a description that target the agent's behavior once read; this class is about the description misrepresenting when and why the skill activates in the first place, expanding blast radius at the invocation layer rather than the instruction layer.", + "owasp_category": "Agentic AI Tool Misuse", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N", + "score": 5.1 + }, + "amplification_factors": { + "autonomy": 0.5, + "tools": 0.5, + "language": 1, + "context": 0.5, + "non_determinism": 0.5, + "opacity": 0.5, + "persistence": 0, + "identity": 0, + "multi_agent": 0, + "self_mod": 0 + }, + "threat_multiplier": 0.5, + "scores": { + "factor_sum": 3.5, + "aars": 0.8575, + "mitigation_factor": 0.83, + "aivss": 4.9, + "severity": "Medium" + } + }, + { + "id": "AVE-2026-00063", + "title": "Human approval gate bypassed via declarative configuration, distinct from AVE-2026-00048", + "description": "A component's configuration declares a flag or setting that disables or bypasses a required human-approval step for high-risk actions, independent of any instruction text or runtime delegation behavior. This is a static configuration weakness, not the instruction-driven delegation mechanism covered by AVE-2026-00048: a config file can set 'auto_approve: true' or an equivalent flag with no accompanying instruction text at all, silently removing a safety control that a reviewer inspecting only the component's declared instructions would never see.", + "owasp_category": "Agent Access Control Violation", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:H/VA:L/SC:N/SI:N/SA:N", + "score": 7.2 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 1, + "language": 0, + "context": 0, + "non_determinism": 0, + "opacity": 0.5, + "persistence": 0.5, + "identity": 0, + "multi_agent": 0, + "self_mod": 0 + }, + "threat_multiplier": 0.97, + "scores": { + "factor_sum": 3.0, + "aars": 0.8148, + "mitigation_factor": 0.83, + "aivss": 6.7, + "severity": "Medium" + } + }, + { + "id": "AVE-2026-00066", + "title": "Hallucinated skill-name squatting (HalluSquatting)", + "description": "An attacker precomputes which plausible-but-nonexistent package, repository, or skill names large language models are statistically likely to generate when asked about a well-known or trending resource, then preemptively registers those exact names on a public registry with malicious content. When an agent hallucinates one of these names in response to an ordinary user request and proceeds to fetch, clone, or install it, no attacker-controlled instruction or injected content is present anywhere in the interaction; the entry point is the model's own hallucinated belief that the resource exists, not a component-level compromise reached through prompt injection or tampering of a real package. Published research demonstrates the hallucination is reliably predictable and transferable across different foundation models and prompt phrasings, letting an attacker precompute a fixed, reusable set of squatted names that yield a scalable, low-cost distribution channel for malware across heterogeneous platforms.", + "owasp_category": "Agent Supply Chain & Dependency Risk", + "cvss_base": { + "vector_string": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N", + "score": 8.7 + }, + "amplification_factors": { + "autonomy": 1, + "tools": 1, + "language": 1, + "context": 0, + "non_determinism": 0.5, + "opacity": 1, + "persistence": 0.5, + "identity": 0, + "multi_agent": 0, + "self_mod": 0 + }, + "threat_multiplier": 0.97, + "scores": { + "factor_sum": 5.0, + "aars": 0.6305, + "mitigation_factor": 1.0, + "aivss": 9.3, + "severity": "Critical" + } + } + ] +} diff --git a/docs/audits/aivss-v0.8-pilot.md b/docs/audits/aivss-v0.8-pilot.md new file mode 100644 index 0000000..c3780c4 --- /dev/null +++ b/docs/audits/aivss-v0.8-pilot.md @@ -0,0 +1,208 @@ +# AIVSS v0.8 pilot: ten records assessed under the conformance statement + +Tests `docs/specs/aivss-v0.8-conformance.md` (S01, #399, issue #446) on ten real records. Report only: no record, schema file or script changed, and none of these scores is proposed for publication. The data is in `docs/audits/aivss-v0.8-pilot.json`, in the format of OWASP's Appendix A report schema. + +**Date:** 2026-11-04. **Records:** `develop` at `0753b2d`. **Assessor:** one (the author of this report). No second assessment was made. + +## Summary + +- Under the statement, the ten move from **1 CRITICAL, 2 HIGH, 6 MEDIUM, 1 LOW** to **6 CRITICAL, 1 HIGH, 3 MEDIUM, 0 LOW**. All ten scores rise; the mean Factor_Sum is 5.6 (OWASP's own examples: 7.65). +- The classes that end CRITICAL are those that give the attacker broad control of what an agent does or runs (AVE-2026-00001, 00019, 00020, 00044, 00046, 00066). The classes with a bounded effect stay MEDIUM (00039, 00058, 00063) or HIGH (00024). That is the separation the plain-language check asks for (below). +- **The result is not robust to reasonable alternative choices.** 6 of 10 records change band under at least one alternative (a different vector, ThM rule, mitigation level, or half a point on every factor). The four that never do (00001, 00044, 00046, 00066) have a CVSS base of 8.7 to 9.3 and Factor_Sum of 5.0 to 8.0. The CVSS vector is the most influential input: using the vector in the record today changes the band of 4 of the 9 records that have a valid one. +- **The re-derived CVSS bases are lower on average than the ones in the records**: 0.7 below the stored `cvss_base` (10 records, from 2.6 lower to 0.9 higher) and 0.7 below the base of the stored vector (9 records, from 2.4 lower to 2.8 higher). So the corpus-wide estimate that uses the stored vectors probably overstates severity. +- The earlier corpus estimate put 6 of the ten in the same band as the pilot. It was one band too high for three (00024, 00039, 00063) and one band too low for one (00019). +- The statement changed in three places while piloting (end of this report). + +## Selection rule (written before any record was assessed) + +1. The maintainer's six: AVE-2026-00001, 00019, 00039, 00044, 00063 and 00066. (00039 has the largest estimated jump under the S01 task's two scenarios, 4.3 and 4.0; with ThM mapped by definition, AVE-2026-00072 is larger at 4.0 against 3.8, and it has a pending lifecycle decision.) +2. One record from each current band not yet represented. LOW has two records (00014 at 3.7, 00058 at 3.1): take the lower, **00058**. CRITICAL has one: **00046**. +3. Two more, to widen how the class enters the agent (`provenance_vector.entry_class`): the two most frequent entry classes not yet represented, `runtime` (12 records) and `skill_file` (4), taking from each the lowest `ave_id` with no pending lifecycle decision: **00020** and **00024**. Excluded as pending: 00035, 00049, 00052, 00053, 00054, 00060, 00061, 00062 and 00072. + +Coverage is partial and the limits matter: 8 of 13 entry classes (not `tool_schema`, `retrieved_document`, `user_input`, `transport`, `operator_config`); 9 records are `skill` components, 1 is `mcp_server` and none is `agent`; all are `active`. + +## Method + +For each record, in the order the statement gives: + +1. Choose the nearest OWASP Core Risk as the calibration anchor (section 3.6). +2. Derive the CVSS v4.0 base vector from the class's described impact (statement section 4), and score it with two implementations: the Red Hat `cvss` library 3.6 and FIRST's `cvss-v4-calculator` scoring files at commit `c5b0d409ae9f57c44264c6ce5f27d89298e1d32a` (run unchanged in a context with no file, network or DOM access). They agree on all ten. +3. Assign the ten factors by the statement's Table in section 6, with one line of basis for each non-zero factor taken from the record's description, fingerprint, `security_boundary`/`missing_control` text or references. +4. Choose the ThM tier from the evidence the record cites, and the mitigation level against Table 4b. +5. Compute AARS and the score in exact decimal arithmetic (the reference form in the statement's section 3), rounded half up, and band it. +6. Write down every uncertain call, and score the plausible alternative. + +The arithmetic was checked first against OWASP's ten worked examples (all reproduce, including each example's CVSS base from its vector in both implementations). The input files are `records/` at the commit above. + +## Before and after + +"Stored base" is the record's `aivss.cvss_base`; "stored vector" is the base score its own `cvss_base_vector` computes to (S00); "pilot base" is the base of the vector derived here. "Old" values are the schema 1.3.0 ones. Level names for ThM: A attacked, P proof of concept, U unreported; for mitigation: N none, P partial. + +| Record | Class (entry class) | Stored base | Stored vector | Pilot base | Old factor sum | Pilot Factor_Sum | Old ThM | Pilot ThM | Old mit. | Pilot mit. | AARS (uplift) | Old score and band | Pilot score and band | +|---|---|---|---|---|---|---|---|---|---|---|---|---|---| +| 00001 | Metamorphic payload via external config fetch (content) | 8.5 | 9.5 | 9.3 | 7.5 | 7.0 | 1 | P 0.97 | 1 | N 1.00 | 0.4753 | 8.0 HIGH | **9.8 CRITICAL** | +| 00019 | Agent memory poisoning (memory) | 8.0 | 9.4 | 7.0 | 7.0 | 7.0 | 0.75 | P 0.97 | 1 | N 1.00 | 2.0370 | 5.6 MEDIUM | **9.0 CRITICAL** | +| 00020 | Cross-agent prompt injection, A2A (runtime) | 8.7 | 9.4 | 8.3 | 7.0 | 7.0 | 0.75 | P 0.97 | 1 | N 1.00 | 1.1543 | 5.9 MEDIUM | **9.5 CRITICAL** | +| 00024 | Content type mismatch (skill_file) | 8.5 | 9.0 | 7.5 | 5.0 | 3.5 | 1 | U 0.50 | 1 | N 1.00 | 0.4375 | 6.8 MEDIUM | **7.9 HIGH** | +| 00039 | Steganographic covert channel (content) | 8.5 | 7.0 | 5.9 | 4.5 | 4.0 | 0.75 | U 0.50 | 1 | N 1.00 | 0.8200 | 4.9 MEDIUM | **6.7 MEDIUM** | +| 00044 | Async task result poisoning (tool_response) | 8.2 | 8.9 | 9.1 | 8.0 | 8.0 | 1 | A 1.00 | 1 | N 1.00 | 0.7200 | 8.1 HIGH | **9.8 CRITICAL** | +| 00046 | MCP tool hook hijacking (server_card_document) | 10.0 | 10.0 | 9.3 | 8.5 | 8.0 | 1.0 | U 0.50 | 1 | N 1.00 | 0.2800 | 9.2 CRITICAL | **9.6 CRITICAL** | +| 00058 | Trigger scope deception (registry_metadata) | 6.5 | 2.3 | 5.1 | 3.5 | 3.5 | 0.75 | U 0.50 | 0.83 | P 0.83 | 0.8575 | 3.1 LOW | **4.9 MEDIUM** | +| 00063 | Approval gate bypass by configuration (registry_metadata) | 8.5 | 9.3 | 7.2 | 3.0 | 3.0 | 1 | P 0.97 | 0.83 | P 0.83 | 0.8148 | 4.8 MEDIUM | **6.7 MEDIUM** | +| 00066 | Hallucinated skill-name squatting (model_generated) | 9.0 | invalid | 8.7 | 4.75 | 5.0 | 0.9 | P 0.97 | 1 | N 1.00 | 0.6305 | 6.2 MEDIUM | **9.3 CRITICAL** | + +Bands: before 1 CRITICAL, 2 HIGH, 6 MEDIUM, 1 LOW; after 6, 1, 3, 0. + +## The assessments + +Factor order: Autonomy, Tools, Language, Context, Non-Determinism, Opacity, Persistence, Identity, Multi-Agent, Self-Mod. "Anchor" is the nearest Core Risk and its factor vector in OWASP's example. + +### AVE-2026-00001 Metamorphic payload via external config fetch + +- **Anchor:** Agent Supply Chain and Dependency Risk (3.6.8), 1, 1, 0, 0, 1, 1, 0.5, 1, 1, 0 (sum 6.5). +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N`, base 9.3 (library 9.3, FIRST 9.3). The stored vector is `AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L` (9.5). Changes: AT `P` to `N` (the model following the fetched content is the mechanism, not a named deployment condition); `SC/SI/SA` to `N` (the description states no propagation beyond the component's own behaviour). From the anchor: `VA:L` and not `H` (the description replaces behaviour and states no loss of availability). +- **Factors:** Autonomy 1.0, the replaced behaviour runs with no co-sign once the component is approved ("change the component's behavior after it passes a security review"). Tools 1.0, the fetch uses network tools and the replaced instructions then drive the agent's tools (IoC: `fetch()`, `requests.get()`, `curl`, `wget`). Language 1.0, the fetched content is natural-language instructions replacing the component's own (the anchor scores 0 because its mechanism is code). Context 1.0, remote content fetched at runtime is runtime content. Non-Determinism 0.5, the swap is deterministic and the model follows explicit instructions. Opacity 1.0, "invisible to static scanners because the malicious payload does not exist at scan time". Persistence 0.5, the content is fetched in every session while the component stays installed, outside the agent's own memory. Self-Mod 1.0, the fetched content replaces the component's own behavioural instructions (fingerprint: "fetch and execute remote content"). Identity 0 and Multi-Agent 0: the text names neither. **Sum 7.0.** +- **ThM:** Proof of Concept. Greshake et al. 2023 (arXiv 2302.12173) demonstrates indirect injection through attacker-controlled retrieved content; the other references (ATLAS AML.T0010, CWE-494) classify. No in-the-wild source is cited. Old value 1. +- **Mitigation:** none. The record's `mitigation` names pinning and egress blocking, but none is cited as default-on or validated. Old value 1. +- **Result:** AARS 0.4753, **9.8 CRITICAL** (was 8.0 HIGH). +- **Uncertain:** whether installation counts as the victim's action (`UI:A`: base 8.6, 9.6, still CRITICAL). CRITICAL under all seven alternatives tried. + +### AVE-2026-00019 Agent Memory Poisoning + +- **Anchor:** Agent Memory and Context Manipulation (3.6.6), 1, 0.5, 1, 1, 0.5, 1, 1, 0, 0.5, 1 (sum 7.5). +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N`, base 7.0 (library 7.0, FIRST 7.0). Stored vector `AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N` (9.4). The anchor scores an insider with database privileges (`AV:A/AC:H/PR:H`, 5.8); here the attacker is a component that can write memory, with no privilege: `AV:N`, `AC:L`, `PR:N`, and `UI:A` because the user installs the component. `VC:L/VI:H/VA:N` as in 3.6.6: the corruption is of the agent's beliefs and disclosure is incidental. Subsequent systems `N`: the effect crosses sessions, not systems. +- **Factors:** Autonomy 1.0, the agent acts on poisoned beliefs in later sessions with no co-sign. Tools 0.5, the write uses the memory interface and later actions use the agent's scoped tools (as 3.6.6). Language 1.0, instructions or facts in natural language are stored and followed. Context 1.0, persistent memory is the agent's context source (as 3.6.6). Non-Determinism 0.5, influence on later behaviour is reliable but not certain (as 3.6.6). Opacity 1.0, "no provenance or integrity check gates writes", so entries cannot be traced to their writer. Persistence 1.0, "in all subsequent sessions". Self-Mod 1.0, the component writes the agent's own standing context (as 3.6.6). Identity 0. Multi-Agent 0: the description names no other agent (the anchor's 0.5 is for limited downstream interaction this text does not state). **Sum 7.0.** +- **ThM:** Proof of Concept. Cohen et al. 2024 (arXiv 2403.02817) and Zou et al. 2024 (PoisonedRAG, arXiv 2402.07867) demonstrate poisoning of stored or retrieved context; no in-the-wild source. Old value 0.75. +- **Mitigation:** none (remediation advice only). Old value 1. +- **Result:** AARS 2.0370, **9.0 CRITICAL** (was 5.6 MEDIUM). +- **Uncertain:** it sits exactly on the CRITICAL edge. It is HIGH with ThM mapped by the old value (8.1) and with every factor 0.5 lower (7.9). `VC:H` instead of `VC:L` gives base 8.5 and 9.5; `UI:N` gives 8.8 and 9.6. + +### AVE-2026-00020 Cross-Agent Prompt Injection (A2A) + +- **Anchor:** Agent Orchestration and Multi-Agent Exploitation (3.6.4), 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5 (sum 9.5). +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:H/SI:H/SA:N`, base 8.3 (library 8.3, FIRST 8.3). Stored vector `AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N` (9.4). The malicious component sits in the first agent's context, so that agent is the vulnerable system (its output is attacker-controlled, `VI:H`) and the sub-agent that obeys it is the subsequent system (`SC:H/SI:H`, the propagation the description states). `AC:L`: no defence is beaten; the missing control is the boundary itself. `UI:A`: the component is installed. +- **Factors:** Autonomy 1.0, the sub-agent acts on the instruction "bypassing the orchestrator's safety controls". Tools 0.5, sub-agent tools are typically scoped by the orchestrator and the class is message passing. Language 1.0, crafted natural language read as commands. Context 1.0, one agent's output arrives as the next agent's input. Non-Determinism 1.0, an LLM sub-agent interprets injected text with no boundary (3.6.3 scores 1.0). Opacity 1.0, attacker text is indistinguishable from orchestrator-intended output. Identity 0.5, the message is read as coming from the orchestrator, a claim of identity within a scope (3.6.3 scores 0.5). Multi-Agent 1.0, definitional. Persistence 0 (a single handoff; the text states no state), Self-Mod 0. **Sum 7.0.** +- **ThM:** Proof of Concept. Cohen et al. 2024 (the worm propagates between GenAI agents) and Greshake et al. 2023 demonstrate; no in-the-wild source. Old value 0.75. +- **Mitigation:** none. Old value 1. +- **Result:** AARS 1.1543, **9.5 CRITICAL** (was 5.9 MEDIUM). +- **Uncertain:** which system is the vulnerable one. Taking the sub-agent as vulnerable with no subsequent impact gives base 8.5 and the same 9.5. It falls to HIGH with ThM by old value (8.9) and with every factor 0.5 lower (8.8). + +### AVE-2026-00024 Supply Chain - Content Type Mismatch + +- **Anchor:** Agent Supply Chain and Dependency Risk (3.6.8), sum 6.5. +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N`, base 7.5 (library 7.5, FIRST 7.5). Stored vector `AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:H/VA:N/SC:L/SI:H/SA:N` (9.0). Impact as the anchor: "arbitrary executable content runs under the guise of a benign skill file". `AT:P` because a loader must execute the file as code; `UI:A` because the user installs the skill. +- **Factors:** Autonomy 1.0 (the file is loaded and run without review, as 3.6.8). Tools 1.0 (code runs with the host's privileges, as 3.6.8). Opacity 1.0 ("invisible to text-pattern scanners"; the extension hides the content). Persistence 0.5 (the file stays while the skill is installed; outside the agent's memory). Language 0 (byte-level mismatch, no natural-language step). Context 0. Non-Determinism 0 (a binary executes deterministically; 3.6.8 scores 1.0 for probabilistic backdoor triggers, which this class does not state). Identity 0 (3.6.8 scores 1.0 for inheriting the agent's identity; Table 2 scores a fixed identity 0; see U4). Multi-Agent 0 (a single file; no spread to other agents stated). Self-Mod 0. **Sum 3.5** (anchor 6.5). +- **ThM:** Unreported. The references (CWE-434, ATLAS AML.T0010, CWE-20) classify; none demonstrates a skill-file content-type mismatch. Old value 1. +- **Mitigation:** none (a classifier and an allowlist are advised; none is cited as default-on). Old value 1. +- **Result:** AARS 0.4375, **7.9 HIGH** (was 6.8 MEDIUM). +- **Uncertain:** the ThM tier. With the specification's default (PoC) the score is 8.3 HIGH. With `AT:N` and `UI:N` the base is 9.3 and the score 9.4 CRITICAL (a band change); with `AT:N` alone 8.6 and 8.8 HIGH. + +### AVE-2026-00039 Covert Channel - Steganographic Data Exfiltration + +- **Anchor:** Agent Goal and Instruction Manipulation (3.6.10), 0.5, 0, 1, 1, 1, 1, 1, 0, 0, 1 (sum 6.5). A weak anchor: the class is exfiltration, not a change of goal. +- **Vector:** `CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:A/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N`, base 5.9 (library 5.9, FIRST 5.9). Stored vector `AV:N/AC:H/AT:P/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N` (7.0). Disclosure only: nothing is changed or lost. `AC:H` and `AT:P` because the encoding must survive the model's compliance and a channel to the attacker must exist (the description: output is reviewed by humans and the network is monitored; trifecta `external_comms`). `UI:A`: the component is installed. No propagation is stated. +- **Factors:** Autonomy 1.0, the agent encodes and emits with no co-sign (the point is that human review sees benign output). Tools 0.5, read tools and the output channel. Language 0.5, natural language sets the encoding but the exploit drives output formatting, not tool execution. Context 0.5, the secrets present in context are one narrow source. Non-Determinism 0.5, the model must follow an explicit encoding rule. Opacity 1.0, "output looks benign to a human reviewer" and content-level exfiltration "has no detection surface at all". The rest 0. **Sum 4.0.** +- **ThM:** Unreported. CWE-514, CWE-385 and the OWASP LLM sensitive-information page classify; none demonstrates. Old value 0.75. +- **Mitigation:** none (detection ideas only). Old value 1. +- **Result:** AARS 0.8200, **6.7 MEDIUM** (was 4.9 MEDIUM). +- **Uncertain:** the most fragile record. It is HIGH with ThM PoC (7.5), every factor 0.5 higher (7.5), the stored vector's base (7.6) or the stored base (8.8). It is LOW (3.7) if `VC` is `L` because a covert channel's bandwidth is small (base 2.1). `AC:L` instead of `AC:H` gives the same base (5.9). + +### AVE-2026-00044 Prompt injection via poisoned async task result + +- **Anchor:** Agent Goal and Instruction Manipulation (3.6.10), sum 6.5; also Tool Misuse (3.6.1), sum 9.0. +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N`, base 9.1 (library 9.1, FIRST 9.1). Stored vector `AV:N/AC:H/AT:P/PR:L/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L` (8.9). `AT:P`: the product uses async task queues (a deployment condition the description names). `AC:L`: no defence is beaten. `PR:N`: the attacker controls the result delivery mechanism, not an account on the agent. The next action is attacker-steered (`VC:H/VI:H`). Subsequent systems `N`: the description states no propagation; the downstream effect of the cited incident is evidence for ThM and is not scored here (including it gives base 9.4). +- **Factors:** Autonomy 1.0, the agent acts on the result in a later turn, and "the temporal gap ... bypasses synchronous safety checks". Tools 1.0, the steered action uses the agent's broad tools. Language 1.0, "imperative language" in the payload. Context 1.0, the result is read as trusted context. Non-Determinism 1.0, an LLM follows injected text with weak guardrails (as 3.6.1). Opacity 1.0, injected content is treated as trusted completed-task context and the gap hides its origin. Persistence 0.5, the poisoned result persists in the queue until read. Identity 0.5, it is read as the output of a completed task, a claim of identity within a scope. Multi-Agent 0.5, the task goes to a worker or service. Self-Mod 0.5, the result steers the agent's next goal, once (as 3.6.1). **Sum 8.0.** +- **ThM:** Attacked. Clinejection (Adnan Khan, February 2026) is documented exploitation in the wild (credential theft and a tampered npm package). The record's own notes say its delivery was a synchronous workflow event and not the async queue, so the evidence is for a sibling entry surface of the same missing boundary; AVE raised `thm` to 1 on that basis on 2026-09-27, and that is kept. Old value 1. +- **Mitigation:** none (schemas and signing are advised; none is cited in place). Old value 1. +- **Result:** AARS 0.7200, **9.8 CRITICAL** (was 8.1 HIGH). +- **Uncertain:** the ThM tier rests on a sibling surface. With PoC the score is the same, 9.8, because the base is 9.1; the base is the floor. + +### AVE-2026-00046 MCP tool hook hijacking + +- **Anchor:** Agentic AI Tool Misuse (3.6.1), sum 9.0. +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L`, base 9.3 (library 9.3, FIRST 9.3). Stored vector `AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H` (10.0, equal to the stored base). Changes: `UI:A` (the component is installed) and `VA/SA:L` and not `H` (the hook "may drop them silently": partial loss of function). `SC/SI:H` kept: the intercepted calls belong to other skills and system tools and reach downstream services (the description). A base of 10.0 would give an uplift of 0 whatever the factors. +- **Factors:** Autonomy 1.0, the hook intercepts all later calls with no co-sign. Tools 1.0, it intercepts every tool call, including system tools. Language 1.0, the skill instructs the agent in natural language to register the hook. Context 1.0, the hook sees all tool traffic. Non-Determinism 0.5, the hook is deterministic once registered; registration depends on the agent following the instruction. Opacity 1.0, "the agent continues to believe it is calling the legitimate tool". Persistence 0.5, the hook lasts the session. Identity 0.5, it stands in for the legitimate handler. Multi-Agent 0.5, it affects other components' calls. Self-Mod 1.0, it alters the agent's tool dispatch ("tools, control flow"). **Sum 8.0.** +- **ThM:** Unreported. CWE-601, CWE-918, the MCP security best practices and the OWASP MCP Top 10 (Tool Poisoning) describe the area; none demonstrates hook interception. The writeup says the 1.0 "reflects ... an in-the-wild threat maturity", and the record cites no incident. Old value 1.0. +- **Mitigation:** none (denying hook registration is advised; none is cited default-on). Old value 1. +- **Result:** AARS 0.2800, **9.6 CRITICAL** (was 9.2 CRITICAL). +- **Uncertain:** the ThM tier. If an in-the-wild source is cited, ThM 1.00 gives 9.9. Without subsequent impact the base is 8.6 and the score 9.2, still CRITICAL. + +### AVE-2026-00058 Deceptive skill trigger or activation-scope manipulation + +- **Anchor:** Agentic AI Tool Misuse (3.6.1), sum 9.0. A weak anchor. +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N`, base 5.1 (library 5.1, FIRST 5.1). Stored vector `AV:N/AC:H/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N` (2.3). The class is "a reach-amplifier" (the record's own notes): over-broad invocation, whose harm depends on what the skill then does, hence `L/L`. `AC:L`: the misleading description beats no defence (the stored vector's `AC:H/AT:P` has no stated reason). `UI:A`: the skill is installed. +- **Factors:** Autonomy 0.5, implicit invocation without the user's intent, while the invoked skill's actions still pass normal confirmations. Tools 0.5, the skill's declared tools, scoped. Language 1.0, natural-language triggers and description decide routing. Context 0.5, one declared source, the manifest. Non-Determinism 0.5, LLM routing varies, bounded by the manifest. Opacity 0.5, the manifest is readable but why a skill was invoked is not traceable. The rest 0. **Sum 3.5.** +- **ThM:** Unreported. CWE-451 classifies and the Cisco skill-scanner page lists a category. Old value 0.75. +- **Mitigation:** partial 0.83. A scanner flags the category but is not validated against adversarial use. Old value 0.83. +- **Result:** AARS 0.8575, **4.9 MEDIUM** (was 3.1 LOW). +- **Uncertain:** the vector. `AC:H` gives base 2.1 and 2.9 LOW; the stored vector's base (2.3) gives 3.0 LOW. This is the one pilot record that can fall to LOW; at 4.9 it is 0.9 above the edge. + +### AVE-2026-00063 Human approval gate bypassed via declarative configuration + +- **Anchor:** Agent Access Control Violation (3.6.2), 1, 1, 1, 1, 0.5, 1, 1, 1, 0.5, 0 (sum 8.0). +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:H/VA:L/SC:N/SI:N/SA:N`, base 7.2 (library 7.2, FIRST 7.2). Stored vector `AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:L/SI:L/SA:N` (9.3). The class is an enabler: it removes a control, and the harm is what the removed gate would have stopped, so `VI:H` (the integrity of the control and of the actions it guards) with `VC:L/VA:L`. `UI:P`: the nearest documented instance (CVE-2026-33068) needs the user only to open a repository. +- **Factors:** Autonomy 1.0, the class removes the human co-sign. Tools 1.0, the gate guards high-risk actions (shell, writes, network). Opacity 0.5, the flag is readable in configuration but nothing signals its use ("a reviewer inspecting only the component's declared instructions would never see it"). Persistence 0.5, a committed configuration persists outside the agent's memory. Language 0 ("no accompanying instruction text at all"), Context 0, Non-Determinism 0, Identity 0, Multi-Agent 0, Self-Mod 0. **Sum 3.0.** +- **ThM:** Proof of Concept. The advisory for CVE-2026-33068 (GHSA-mmgp-wc2j-qcv7) describes the exploit ("a malicious repository could set `permissions.defaultMode` to `bypassPermissions` in its committed `.claude/settings.json`"). The record calls it the nearest instance and not an exact match; the advisory states no exploitation. Old value 1. +- **Mitigation:** partial 0.83. The vendor fixed the nearest instance (2.1.53), not the class. Old value 0.83. +- **Result:** AARS 0.8148, **6.7 MEDIUM** (was 4.8 MEDIUM). +- **Uncertain:** 0.3 below the HIGH edge. It is HIGH with `VC:H` (base 8.7, 7.5), with mitigation none (8.0), with the stored vector's base (7.9) or with every factor 0.5 higher (7.6). + +### AVE-2026-00066 Hallucinated skill-name squatting (HalluSquatting) + +- **Anchor:** Agent Supply Chain and Dependency Risk (3.6.8), sum 6.5. +- **Vector:** `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N`, base 8.7 (library 8.7, FIRST 8.7). The stored vector is invalid (`UI:R` is a CVSS 3.1 value); the stored base is 9.0. Impact as the anchor (installed content executes: "malware", "botnet formation"). `UI:P`: the victim makes an ordinary request and the interaction holds no attacker content. `AT:N`: the hallucination is the mechanism. Subsequent systems `N`: the description is about distribution across victims, not propagation from one (all `H`, as the stored vector had, gives 9.4). +- **Factors:** Autonomy 1.0, the agent fetches, clones or installs with no co-sign (fingerprint). Tools 1.0, installing uses shell and package tools. Language 1.0, an ordinary natural-language request is resolved to a name. Non-Determinism 0.5, the hallucination is predictable and transferable, not deterministic (the record's own 0.25 is off the 0, 0.5, 1 scale and goes to the nearest point, ties up). Opacity 1.0, the model's belief that the resource exists is not auditable and squatted content looks legitimate. Persistence 0.5, an installed package persists outside the agent's memory (as 3.6.8). Context 0 (model memory, as 3.6.8), Identity 0 (see U4), Multi-Agent 0, Self-Mod 0. **Sum 5.0.** +- **ThM:** Proof of Concept. arXiv 2607.07433 demonstrates up to 85% success in repository cloning and up to 100% in skill installation against production applications; arXiv 2607.12340 measures the hallucinated names; no real campaign is reported. Old value 0.9. +- **Mitigation:** none (registry checks and allowlists are advised; none is in place). Old value 1. +- **Result:** AARS 0.6305, **9.3 CRITICAL** (was 6.2 MEDIUM). +- **Uncertain:** `UI:N` gives base 9.3 and 9.6. This also replaces the invalid vector. + +## Sensitivity + +Score (and band) under each alternative, other inputs as in the pilot. A star marks a band different from the pilot's. + +| Alternative | 00001 | 00019 | 00020 | 00024 | 00039 | 00044 | 00046 | 00058 | 00063 | 00066 | +|---|---|---|---|---|---|---|---|---|---|---| +| **Pilot** | 9.8 C | 9.0 C | 9.5 C | 7.9 H | 6.7 M | 9.8 C | 9.6 C | 4.9 M | 6.7 M | 9.3 C | +| Base from the stored vector | 9.8 C | 9.8 C | 9.8 C | 9.2 C* | 7.6 H* | 9.8 C | 10.0 C | 3.0 L* | 7.9 H* | invalid | +| Base from the stored `cvss_base` | 9.5 C | 9.4 C | 9.6 C | 8.8 H | 8.8 H* | 9.6 C | 10.0 C | 5.9 M | 7.4 H* | 9.5 C | +| ThM PoC for every record | 9.8 C | 9.0 C | 9.5 C | 8.3 H | 7.5 H* | 9.8 C | 9.8 C | 5.6 M | 6.7 M | 9.3 C | +| ThM mapped from the old value | 9.8 C | 8.1 H* | 8.9 H* | 8.4 H | 6.7 M | 9.8 C | 9.9 C | 4.9 M | 6.7 M | 9.3 C | +| Mitigation none for every record | 9.8 C | 9.0 C | 9.5 C | 7.9 H | 6.7 M | 9.8 C | 9.6 C | 6.0 M | 8.0 H* | 9.3 C | +| Every factor 0.5 lower | 9.5 C | 7.9 H* | 8.8 H* | 7.7 H | 6.1 M | 9.4 C | 9.4 C | 4.3 M | 6.2 M | 9.0 C | +| Every factor 0.5 higher (cap 1) | 9.9 C | 9.6 C | 9.8 C | 8.4 H | 7.5 H* | 10.0 C | 9.7 C | 5.9 M | 7.6 H* | 9.7 C | + +Band changes per alternative: stored vector 4 (of the 9 valid), stored base 2, ThM PoC 1, ThM by old value 2, mitigation none 1, factors lower 2, factors higher 2. **Six records change band at least once** (00019, 00020, 00024, 00039, 00058, 00063). Four never do (00001, 00044, 00046, 00066). + +The corpus estimate used before this pilot (stored base, the eight factors v0.8 shares with AVE, ThM mapped by definition) agrees with the pilot's band for 6 of the 10. + +## Plain-language check + +The test: a class that sounds severe and a class that sounds narrow should not both be CRITICAL without a reason. + +- **CRITICAL (6).** 00001: whoever controls a URL can rewrite a reviewed component's behaviour at will, with the agent's privileges. 00046: a component can silently sit between the agent and every tool it calls. 00066: an ordinary request leads the agent to install attacker-controlled code. 00044: an injected task result steers the agent's next action, and a real incident exists. 00020: one agent's output is taken as another's instructions. 00019: a poisoned memory steers the agent in every later session. These are classes where the attacker gets broad control of what the agent does, so CRITICAL has a reason in each. Two are marginal: 00019 is exactly on the edge (9.0) and 00020 is 0.5 above it. +- **HIGH (1).** 00024: an executable is disguised as a skill file. If it is loaded it is code execution, but the ThM is Unreported (the cited sources demonstrate nothing), so it stays below CRITICAL; with the specification's default it is 8.3, still HIGH. +- **MEDIUM (3).** 00039 leaks data through a channel with an explicit set of conditions and no effect on integrity or availability. 00063 removes a safety control but does nothing by itself: the harm is what the missing control then permits. 00058 only widens when a skill is invoked. None sounds as severe as the six, and none is CRITICAL. +- **No LOW.** 00058 was LOW and is now MEDIUM, because a base of 5.1 is a floor under it: with its own Factor_Sum, ThM and mitigation, 00058 stays LOW only for a base of 3.6 or less. The record's own notes say its base and factors sit lower than the direct-injection classes, and it is the lowest-scoring class in the pilot. +- **One rank inversion, and what the specification says about it.** 00044 (9.8) outscores 00046 (9.6), although 00046 intercepts every tool call and 00044 steers one action. The cause is the ThM tier (Attacked against Unreported). Section 3.2 of the specification says scores within the same band are equivalent for prioritisation and should not be ranked by decimal, so by the specification's own guidance there is no inversion; the conformance statement keeps that reading and AVE tooling should not rank by decimal within a band. +- **Where the check fails.** The six CRITICAL classes are not distinguished from one another by anything but a few tenths. The six sit between 9.0 and 9.8, separated by a few tenths that section 3.2 says not to rank on, and at a Factor_Sum of 6.5 or more every base of 7.0 or more scores 8.9 or higher. That follows from the equation (the conformance statement's section 5.4), not from the pilot's choices. + +## What the pilot changed in the statement + +1. **Persistence.** The first pass scored a committed configuration (00063) 1.0 and installed components 0.5, following OWASP's 3.6.2 and 3.6.8 inconsistently. The statement now reserves 1.0 for the agent's own memory or retained state, and 00063 was re-scored (Persistence 0.5, 6.7 MEDIUM instead of 6.8). +2. **Subsequent systems.** The literal reading of 3.1.1 set `SC:H/SI:H` for every steering class, with bases near 9.4. OWASP's other nine examples do not, and the statement now scores them only for propagation the class states (decision D2). +3. **Context.** Adopted from draft PR #401's rule: 1.0 when runtime content carries the exploit, 0.5 for one static source, 0 when independent of what the agent reads. It decided 00001, 00020 and 00044. + +Separately, the S01 task's `aivss_v08.py` was found to misround 36 of 19,089 grid inputs (see the statement's section 3). No pilot score was affected, because all pilot scores were computed in exact decimal arithmetic. + +## Limits + +- Ten records, one assessor, no independent second assessment. The vectors and the factors are judgements; section "Sensitivity" shows how much a different judgement can move a band. +- The ten are not a sample: six were named, two chosen to cover bands, two to cover entry classes. Their frequencies must not be scaled up to the 89 records. +- Coverage is partial (see the selection rule): one `mcp_server`, no `agent` component, 8 of 13 entry classes. +- The ThM tiers rest on the references each record cites today. Four of the ten (00024, 00039, 00046, 00058) cite nothing that demonstrates the class; the tier would change if a primary source is found (the quality queue has the 22 records that have none). +- Nothing was checked against NVD or against a vendor's own CVSS vector for the nearest instances (for example CVE-2026-33068). + +## Reproduction + +The data file `docs/audits/aivss-v0.8-pilot.json` holds, for each record, the vector, the base score, the ten factors, ThM, Mitigation_Factor, Factor_Sum, AARS, the score and the band, in Appendix A's shape; it validates against that schema as transcribed from the specification. To recompute: score each `vector_string` with both CVSS v4.0 implementations named above; compute `AARS = (10 - base) x (factor_sum / 10) x threat_multiplier` and `score = RoundHalfUp((base + AARS) x mitigation_factor, 1)` in decimal arithmetic (the statement's section 3 has the reference form). The harness used here (arithmetic module, tests, mutation check, Appendix A validator) is not part of this change; S02 adds the arithmetic and its tests to the repository. diff --git a/docs/specs/aivss-v0.8-conformance.md b/docs/specs/aivss-v0.8-conformance.md new file mode 100644 index 0000000..6ec1238 --- /dev/null +++ b/docs/specs/aivss-v0.8-conformance.md @@ -0,0 +1,328 @@ +# AIVSS v0.8 conformance statement for AVE + +**Status: draft for the maintainer's decision.** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, script or `dist/` file changes. Nothing here becomes AVE's rule until the maintainer approves the decision list in section 13. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. + +**Date:** 2026-11-04. **Repository state:** `develop` at `0753b2d`. + +## 1. What this statement is for + +OWASP AIVSS v0.8 scores one vulnerability in one deployment. AVE catalogues classes of vulnerability, each defined once and detected many times. A score in an AVE record therefore has to answer a question the specification does not ask: for which deployment? This statement says how AVE answers it, so that two assessors scoring the same class get the same inputs, and so that a record can be exported into OWASP's own report format (Appendix A of the specification). + +It covers: the equations and constants (section 3), the CVSS input (4), the class-level assessment rule (5), the ten factors (6), the threat multiplier (7), the mitigation factor (8), rounding and bands (9), the proposed schema 2.0.0 `aivss` object (10), every place the sources differ (11), the deviations and open questions (12), and the decisions the maintainer must make (13). + +## 2. Source, and how it was read + +- Document: *AIVSS Scoring System For OWASP Agentic AI Core Security Risks v0.8*, Part 2, `https://aivss.owasp.org/assets/publications/AIVSS%20Scoring%20System%20For%20OWASP%20Agentic%20AI%20Core%20Security%20Risks%20v0.8.pdf`. 98 pages, SHA-256 `a2abbd215f0d7790d273c30a893a09c0dc37a6c109765eb0363c01af897fd9af`. OWASP announced v0.8 on 2026-03-19. +- Read in full, from the PDF text and not from a summary: sections 1 to 4 (including Tables 1 to 5 and the ten worked examples of 3.6), sections 5 to 7, and Appendices A to D. Every section number below was checked against that text. +- Re-derived rather than trusted: for each of the ten worked examples in 3.6, the factor sum, AARS, raw score, rounded score and band; and each example's CVSS v4.0 base score from its vector, with two independent implementations (section 4). All ten agree with the specification. +- Appendix A (the report JSON schema) was transcribed into a JSON Schema file and used as a validator: OWASP's ten examples validate in that shape, and the AVE pilot is exported in it (section 10). Four negative controls (a factor of 0.3, a threat multiplier of 0.9, an unknown category, a missing factor) are refused. + +Where a secondary source, a task file or an AVE document differs from the specification, the specification wins and the difference is listed in section 11. + +## 3. The equations and constants + +| Quantity | Specification | Section | AVE 2.0.0 | +|---|---|---|---| +| Factors | Ten, each 0.0, 0.5 or 1.0: Autonomy, Tools, Language, Context, Non-Determinism, Opacity, Persistence, Identity, Multi-Agent, Self-Mod | 2.1, 2.2, Table 1 | Same ten, same three levels | +| Factor_Sum | Sum of the ten, 0.0 to 10.0 | 3.3.1 | Stored as `factor_sum` | +| Agentic Risk Gap | `10 - CVSS_Base` | 3.3.1 | Same | +| AARS (the uplift) | `(10 - CVSS_Base) x (Factor_Sum / 10) x ThM` | 3.3.1 | Same. Optional intermediate in the specification (3.3.3, 3.5) | +| ThM | Attacked 1.00, Proof-of-Concept 0.97, Unreported 0.50. Default 0.97 | 3.3.2, Table 4a | Same values; see section 7 | +| Primary equation | `AIVSS = (CVSS_Base + AARS) x Mitigation_Factor` | 3.4, 3.4.0 | Same | +| Mitigation_Factor | No/Weak 1.00, Partial 0.83, Strong 0.67. Default 1.0. 0.67 is a provisional floor | 3.4.1, Table 4b | Same values; see section 8 | +| Rounding | `RoundHalfUp(AIVSS_raw, 1)`; 8.64 becomes 8.6, 8.65 becomes 8.7 | 3.4.0, 3.5.1 | Same, in exact decimal arithmetic | +| Bands | Critical 9.0 to 10.0, High 7.0 to 8.9, Medium 4.0 to 6.9, Low 0.1 to 3.9 | 3.5.2 | Same; a score below 0.1 has no band | +| CVSS baseline | CVSS v4.0 only; v3.1 scores must not be used | 3.1.1 | Same; see section 4 | +| Reading scores | Ordinal, not interval. Do not average. Read by band, not by decimal | 3.2 | Same; AVE tooling must not average scores | + +The score is computed from the unrounded AARS (3.4.0, step 3). AARS has at most five decimal places for every legal input (CVSS to one decimal, Factor_Sum in steps of 0.5, ThM to two decimals; checked by enumerating the whole input grid), so an exact stored AARS needs five places. + +**Arithmetic must be exact decimal.** A float product misrounds raw values that are exact ties. Over the full grid (CVSS 0.0 to 10.0 in steps of 0.1, Factor_Sum 0.0 to 10.0 in steps of 0.5, three ThM levels, three mitigation levels: 19,089 inputs) a float implementation rounds 36 results, every one exactly one tenth low, and 2 of those cross a band: for example CVSS 3.9, Factor_Sum 5.0, ThM 1.00, Mitigation_Factor 1.0 has raw score 6.95, which the specification's rule makes 7.0 HIGH and a float product makes 6.9 MEDIUM. The reference arithmetic below is exact; it is the form S02 should adopt. + +```python +from decimal import Decimal as D, ROUND_HALF_UP +THM = {"attacked": D("1.00"), "poc": D("0.97"), "unreported": D("0.50")} +MITIGATION = {"none": D("1.00"), "partial": D("0.83"), "strong": D("0.67")} +BANDS = (("CRITICAL", D("9.0")), ("HIGH", D("7.0")), ("MEDIUM", D("4.0")), ("LOW", D("0.1"))) + +def aars(cvss_base, factor_sum, thm): # 3.3.1, exact + return (10 - D(str(cvss_base))) * (D(str(factor_sum)) / 10) * THM[thm] + +def aivss(cvss_base, factor_sum, thm, mitigation): # 3.4.0 steps 1 to 4 + raw = (D(str(cvss_base)) + aars(cvss_base, factor_sum, thm)) * MITIGATION[mitigation] + return raw.quantize(D("0.1"), rounding=ROUND_HALF_UP) + +def band(score): # 3.5.2; below 0.1 the specification defines no band + for name, floor in BANDS: + if score >= floor: + return name + raise ValueError("no band below 0.1") +``` + +## 4. How `cvss_base` is determined + +v0.8 takes a CVSS v4.0 base score as input (3.1.1). The audit in `docs/audits/cvss-input-reconciliation.md` (S00, #403) found that the stored `cvss_base` equals the score of the record's own vector for 3 of 88 valid vectors, and that one vector (AVE-2026-00066) is not valid CVSS v4.0. Because v0.8 adds the uplift to the base, the base is the floor of the score (section 5.4). This statement therefore makes the vector the input and the number a derived value. + +1. **The vector is authoritative.** `cvss_base_vector` is the assessment; `aivss.cvss_base` is the score computed from it. A validator rule recomputes it and fails on a mismatch. +2. **Base metrics only.** The vector carries the eleven base metrics. Threat (`E`) and environmental metrics are not used: exploit maturity is already ThM, and counting it in both would count it twice. The specification's own examples are base vectors (3.6). +3. **Two named implementations**, pinned in the development requirements, and a test that fails if they disagree on any record: the Red Hat Product Security `cvss` Python library (3.6 used here) and the scoring files of FIRST's `FIRSTdotorg/cvss-v4-calculator` at commit `c5b0d409ae9f57c44264c6ce5f27d89298e1d32a`, run unchanged in a context with no file, network or DOM access. They agreed on all 88 valid vectors in S00. In this work they also agree on the three reference vectors (9.3, 10.0, 0.0), on the ten vectors of OWASP's examples (each equals the base the specification states), and on all ten vectors derived for the pilot. +4. **How a class's vector is derived.** Start from the vector OWASP gives for the nearest Core Risk in 3.6 and change a metric only where the class's description or sources state a difference, writing the reason. The metric rules: + +| Metric | Rule for a class | +|---|---| +| AV | `N` when the attacker's input reaches the agent over a network or registry. `L` only when the class needs a file placed by someone with local access | +| AC | `L` unless the class's text says the attacker must defeat an existing defence or meet a hard-to-meet condition | +| AT | `P` only for a deployment precondition the class names that is not part of its own mechanism (for example, the product uses async task queues). The model following the injected content is the mechanism and is scored in Non-Determinism, so it is `N` | +| PR | `N` unless the text says the attacker needs an account on the vulnerable system | +| UI | `A` when the victim must knowingly install, enable or approve something the attacker supplied for the class to apply. `P` when the victim only uses the product normally (opens a repository, asks an ordinary question). `N` when no victim action is needed | +| VC, VI, VA | The agent runtime and its host. `H` when the class lets the attacker cause the outcome in full without a further vulnerability, `L` when only partially or for a subset, `N` when the described mechanism does not | +| SC, SI, SA | Systems beyond the agent that the class itself propagates to (another agent, a downstream service, another tenant), as its description states. Reach through the agent's tools is scored once, in the Tools factor, and not again here (decision D2) | + +The specification's wording on subsequent systems (3.1.1: assess them "based on the full scope of systems the compromised agent can reach through its tool access, delegation chains, and inter-agent communication paths") can be read literally, and then every class that steers an agent with default tools gets `SC:H/SI:H`, as in OWASP's 3.6.1. OWASP's other nine examples do not do that: they set subsequent impacts only where the scenario states propagation (cascade, orchestration, connected internal tools). The rule above follows the nine and is decision D2. + +## 5. The class-level assessment rule + +### 5.1 The problem + +Section 3.6 scores ten scenarios. Each is a deployment: "an externally available agent ... possessing high autonomy and access to internal code generation tools" (3.6.1), "a central orchestration agent" (3.6.4), "a water treatment agent" (3.6.7). Its factors describe that deployment. A catalogue entry has no scenario of its own, so something must stand in for it. + +### 5.2 What OWASP's own examples show + +| Section | Core Risk | Aut | Tools | Lang | Ctx | NonD | Opac | Pers | Ident | Multi | SelfM | Sum | CVSS | AIVSS | +|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| +| 3.6.1 | Agentic AI Tool Misuse | 1 | 1 | 1 | 1 | 1 | 1 | 0.5 | 1 | 1 | 0.5 | 9.0 | 9.4 | 9.9 | +| 3.6.2 | Agent Access Control Violation | 1 | 1 | 1 | 1 | 0.5 | 1 | 1 | 1 | 0.5 | 0 | 8.0 | 8.7 | 9.7 | +| 3.6.3 | Agent Cascading Failures | 1 | 0.5 | 1 | 1 | 1 | 1 | 0.5 | 0.5 | 1 | 0.5 | 8.0 | 7.1 | 9.4 | +| 3.6.4 | Agent Orchestration and Multi-Agent Exploitation | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0.5 | 9.5 | 9.4 | 10.0 | +| 3.6.5 | Agent Identity Impersonation | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0.5 | 0 | 7.5 | 7.4 | 9.3 | +| 3.6.6 | Agent Memory and Context Manipulation | 1 | 0.5 | 1 | 1 | 0.5 | 1 | 1 | 0 | 0.5 | 1 | 7.5 | 5.8 | 8.9 | +| 3.6.7 | Insecure Agent Critical Systems Interaction | 1 | 1 | 0.5 | 1 | 0.5 | 1 | 0.5 | 0 | 1 | 1 | 7.5 | 6.9 | 9.2 | +| 3.6.8 | Agent Supply Chain and Dependency Risk | 1 | 1 | 0 | 0 | 1 | 1 | 0.5 | 1 | 1 | 0 | 6.5 | 9.3 | 9.7 | +| 3.6.9 | Agent Untraceability | 1 | 1 | 0 | 0 | 1 | 1 | 0.5 | 0.5 | 1 | 0.5 | 6.5 | 5.3 | 8.3 | +| 3.6.10 | Agent Goal and Instruction Manipulation | 0.5 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 6.5 | 2.1 | 7.1 | + +All ten use ThM 0.97 and Mitigation_Factor 1.0 (3.6, introduction). What they show: + +- **Factor sums run from 6.5 to 9.5 (mean 7.65).** No example is below 6.5. All ten land HIGH or CRITICAL, including a CVSS 2.1 that becomes 7.1 (3.7 says this is the intended behaviour). +- **Autonomy is 1.0 in nine, Opacity 1.0 in all ten, Language 1.0 in seven, Context 1.0 in eight.** The deployment-dependent factors sit at or near the top because the scenarios are chosen to have them. +- **Mechanism factors follow the mechanism, not the deployment.** Language is 0 for supply chain and untraceability because "the attack is code-level; natural language plays no role" (3.6.8, 3.6.9). Context is 0 where the attack is "triggered at import time with no context dependency". Persistence is 0 for a single deepfake interaction (3.6.5). So the examples are scenario-specific, not worst case: Tools is 0.5 for cascading failures and memory manipulation, 0 for goal manipulation. +- **Subsequent-system impacts are set only where the scenario propagates** (3.6.1, 3.6.3, 3.6.4); in the other seven they are all `N`. +- **One internal inconsistency.** 3.6.8 scores Identity 1.0 because "the attacker inherits the agent's full system identity", but Table 2 defines Identity as runtime role or identity change (0.0 for a fixed identity or service account). AVE follows Table 2 (section 12, U4). + +### 5.3 The rule + +1. **Reference deployment profile (RDP).** A class is assessed as deployed this way: one agent of the kind the record's `component_type` names (skill, mcp_server, agent), operated by one user, with the tools and permissions its ecosystem grants by default, with its ecosystem's default confirmation behaviour, and with no hardening beyond those defaults. A multi-agent deployment applies only to a class whose mechanism is multi-agent. Hardening is credited once, in Mitigation_Factor, and never inside the factors. +2. **Two kinds of factor.** *Mechanism factors* (Language, Context, Persistence, Identity, Multi-Agent, Self-Mod) are taken from what the class does, as its description and fingerprint state it, whatever the deployment. *Deployment factors* (Autonomy, Tools, Non-Determinism, Opacity) are taken from the RDP. Table 6 in section 6 says what each level means for each factor. +3. **Typical, not worst case.** Deployment factors take the value that is typical for the component type as shipped. Worst case is not used for three reasons. OWASP's own examples are not worst case. A worst-case rule would set the four deployment factors to 1.0 for nearly every class and remove the factors' power to tell a broad class from a narrow one. And "typical as shipped" can be checked by a second assessor, whereas "worst imaginable" cannot. +4. **Calibration anchors.** Each class is compared with the nearest Core Risk in 3.6 (Table 3 lists each Core Risk's high-impact factors). Copy that example's factor vector, then change a factor only for a reason written from the class's description or sources. The anchor is recorded (section 10, `core_risk`; Appendix A requires an `owasp_category`). Where no Core Risk fits well, say so. In the pilot the anchor was weak for AVE-2026-00039 and 00058. +5. **Evidence is stated for every non-zero factor**: one line, citing the record's description, fingerprint or a reference. A factor with no stated basis is 0.0 (no inflation without a reason, the same discipline as the existing "do not inflate" rule in `references/aivss-scoring.md`). +6. **Do not force a band.** The honest computed result is reported. Where it feels wrong, the notes say so, and the inputs are not adjusted. + +### 5.4 What the rule cannot do + +Because v0.8 adds the uplift to the CVSS base, the base is a floor. With OWASP's factor sums the floor is high: + +| Factor_Sum | Score at CVSS 2.0 | 4.0 | 6.0 | 8.0 | Lowest base that scores HIGH | Lowest base that scores CRITICAL | +|---|---|---|---|---|---|---| +| 2.5 | 3.9 | 5.5 | 7.0 | 8.5 | 6.0 | 8.7 | +| 3.5 | 4.7 | 6.0 | 7.4 | 8.7 | 5.4 | 8.5 | +| 5.0 | 5.9 | 6.9 | 7.9 | 9.0 | 4.1 | 8.0 | +| 6.5 | 7.0 | 7.8 | 8.5 | 9.3 | 1.8 | 7.2 | +| 8.0 | 8.2 | 8.7 | 9.1 | 9.6 | 0.0 | 5.4 | +| 9.5 | 9.4 | 9.5 | 9.7 | 9.8 | 0.0 | 0.0 | + +(ThM 0.97, Mitigation_Factor 1.0.) At OWASP's lowest sum, a class is HIGH from a base of 1.8. The only things that keep a class with a high base out of HIGH or CRITICAL are a low Factor_Sum and a Mitigation_Factor below 1. For the corpus this means the CVSS vectors, not the factors, decide most of the severity distribution (decision D14). + +## 6. The ten factors for a catalogue entry + +Adapted from Table 2. "Mechanism" factors come from the class; "deployment" factors come from the RDP. + +| Factor | Kind | 0.0 | 0.5 | 1.0 | +|---|---|---|---|---| +| 1 Autonomy | Deployment | A human performs or approves the harmful step every time | The step runs unattended only in non-critical or sandboxed paths, or behind a confirmation users routinely accept | The step is committed without a human co-sign in the RDP, or the class itself removes the co-sign | +| 2 Tools | Deployment | The exploit path needs no tool, or read-only tools only | Mixed read and write tools, scoped or allowlisted | The exploit path uses or reaches broad, high-authority tools (shell, filesystem write, cloud, CI/CD, SQL, network egress) | +| 3 Language | Mechanism | Structural mechanism (configuration, bytes, protocol); no natural-language step | Natural language is used for retrieval, description or question answering but does not itself drive tool execution in the exploit | Natural-language content (instruction, description, result) directly drives tool selection, execution or planning in the exploit | +| 4 Context | Mechanism | The exploit is independent of what the agent has read or sensed | One narrow or static source (a manifest, a configuration, one declared input) | Broad runtime content carries the exploit: tool results, retrieved or user content, memory, history, shared state, several components | +| 5 Non-Determinism | Deployment | Deterministic once triggered (rule-based or fixed) | Variance bounded by explicit rules or strict guardrails | An LLM-driven step with weak guardrails, whose outcome varies run to run | +| 6 Opacity | Mechanism and deployment | The effect is traceable end to end in logs or a reviewable artifact | An artifact or log exists, but why the agent acted is a black box | The effect cannot be traced to its cause, or is built to evade review (hidden from scanners, no audit signal) | +| 7 Persistence | Mechanism | Stateless | Session state only, or an artifact that persists outside the agent's own memory (an installed component, a committed configuration, remote content fetched each session) | The agent's own memory or retained state carries the effect across sessions (a memory store, retained credentials) | +| 8 Identity | Mechanism | One fixed identity or service account on the exploit path | Limited identity change (scoped to one tool), or a claim of identity within a scope | The exploit assumes roles or crosses tenant boundaries dynamically | +| 9 Multi-Agent | Mechanism | One isolated instance | Limited coordination with one or two known agents or services | Orchestration or swarm patterns are the exploit's path | +| 10 Self-Mod | Mechanism | None | Can change its own prompts or configuration only | Can alter tools, control flow, or generate and execute code | + +Three clarifications were made while piloting, and the pilot lists where they applied: Persistence (1.0 only for the agent's own state, consistent with OWASP's 3.6.2 against 3.6.8), Context (the rule PR #401 also used), and Self-Mod for a single injected instruction (0.5, as in 3.6.1; 1.0 only for repeated goal conditioning, as in 3.6.10). + +AVE's current factors map as follows (they were assigned against AVE's own definitions, not Table 2): `autonomy`, `non_determinism` and `multi_agent` keep their names; `tool_use` is Tools; `natural_language_input` is Language; `persistent_memory` is Persistence; `dynamic_identity` is Identity; `self_modification` is Self-Mod; `data_access` and `external_dependencies` have no counterpart; Context and Opacity are new. Carrying the eight over by value would carry definitions that differ from Table 2 (this is why the S01 plan says not to). + +## 7. The threat multiplier + +| Tier | Specification (Table 4a) | Evidence an AVE record must cite | +|---|---|---| +| Attacked, 1.00 | "Vulnerability is being actively exploited in the wild" | A primary source documenting exploitation outside a research setting: an incident report, an advisory that states exploitation, a vendor confirmation | +| Proof-of-Concept, 0.97 | "Functional exploit code or detailed walkthrough exists" | A primary source with exploit code, a reproduction, or a detailed walkthrough of this class's mechanism: a paper that demonstrates it, an advisory with reproduction steps | +| Unreported, 0.50 | "No known exploit; theoretical vulnerability only" | The cited sources only classify or describe the weakness (a taxonomy page, a CWE, a standard) and none demonstrates it | + +The specification's default is 0.97 and argues that for agentic exploits the distance from proof of concept to attack is negligible (3.3.2). AVE therefore uses PoC when the evidence tier cannot be told apart, and records the tier and its source in the notes. + +**What happens to today's `thm` (1, 0.9, 0.75).** The plan in #399 maps them by definition (0.75 to Unreported, 0.9 to PoC, 1.0 to Attacked). That is wrong for 1.0, because AVE's own documents define it two ways. `CONTRIBUTING.md` says 1.0 is "exploited in the wild or weaponised". `references/aivss-scoring.md` says 1 is "real and demonstrated (a disclosed CVE, published research, a working exploit description)" and that "every record in this corpus so far has scored 1". In the pilot, mapping by value agrees with the tier the cited evidence supports for 4 of 10 records. Of the five pilot records stored at 1.0, one cites an in-the-wild source (AVE-2026-00044); two are PoC; two cite nothing that demonstrates the class (and AVE-2026-00046's writeup says its 1.0 "reflects ... an in-the-wild threat maturity" while the record cites no incident). Two of the four stored at 0.75 are demonstrated in cited research and are PoC. This is decision D3. + +## 8. The mitigation factor + +| Level | Specification (Table 4b) | Rule for a class | +|---|---|---| +| None / Weak, 1.00 | Mitigations absent or ineffective | No mitigation that is effective, validated and enforceable exists in the RDP as shipped. Advice in the record's `remediation` alone is not a mitigation | +| Partial, 0.83 | Some mitigations exist, but they are incomplete, not reliably enforceable, or not validated against realistic misuse | A mitigation exists and is in use (a vendor fix for the nearest instance, a scanner that flags the class) but does not cover the class, is off by default, or has not been validated | +| Strong, 0.67 | Effective, validated, consistently enforceable under real operating conditions, fail-closed where applicable | Default-on in the RDP, with a cited validation. A class is by definition a missing control, so Strong should be rare | + +AVE's current 0.83 is defined differently ("a simple, well-known, standard mitigation exists and is reasonably expected to be applied"), but the values and the groups of records line up: in the pilot, carrying 1.0 to None and 0.83 to Partial agrees with an assessment against Table 4b for 10 of 10 records (decision D4). The specification calls the 0.67 floor "a provisional anchor ... subject to empirical calibration" (3.4.1); it may change in a later version. + +## 9. Rounding and bands + +Half up, to one decimal, on the unrounded product (3.4.0, 3.5.1). Bands as in 3.5.2. A score below 0.1 has no band in the specification, so the validator rejects it instead of assigning one; in practice no class reaches it, because a class with any impact has a CVSS base well above 0 and the uplift only adds. The record's `severity` is the band in AVE's upper-case spelling and must agree with `aivss.aivss_score` (CLAUDE.md hard rule 6); Appendix A's `severity` is title case, a mapping done at export. The legacy rounding (Python `round()` on a float, ties to even) stays in the frozen 1.x records and is not used for 2.0.0. + +## 10. The schema 2.0.0 `aivss` object + +Appendix A defines the report format OWASP uses: per finding, `id`, `title`, `description`, `owasp_category`, `cvss_base {vector_string, score}`, `amplification_factors` (ten keys), `threat_multiplier`, and `scores {factor_sum, aars, mitigation_factor, aivss, severity}`. The AVE object is aligned with it where that costs nothing and departs from it where an AVE record needs something else. + +```json +"aivss": { + "spec_version": "0.8", + "cvss_base": 9.3, + "aarf": { + "autonomy": 1.0, "tools": 1.0, "language": 1.0, "context": 1.0, "non_determinism": 0.5, + "opacity": 1.0, "persistence": 0.5, "identity": 0.0, "multi_agent": 0.0, "self_mod": 1.0 + }, + "factor_sum": 7.0, + "threat_maturity": "poc", + "thm": 0.97, + "aars": 0.47530, + "mitigation": "none", + "mitigation_factor": 1.0, + "aivss_score": 9.8, + "aivss_severity": "CRITICAL", + "core_risk": "Agent Supply Chain & Dependency Risk", + "notes": "..." +} +``` + +(The values are the pilot's for AVE-2026-00001.) + +| AVE field | Appendix A field | Rule and departure | +|---|---|---| +| `cvss_base_vector` (record level, unchanged) | `cvss_base.vector_string` | Kept at record level: it is an existing field that consumers read. The exporter nests it | +| `aivss.cvss_base` | `cvss_base.score` | Derived from the vector (section 4); the validator checks equality | +| `aivss.aarf` with Appendix A's ten key names | `amplification_factors` | The inner keys follow Appendix A (`tools`, `language`, `persistence`, `identity`, `self_mod` replace five AVE names), so the object exports without a mapping table. The container keeps AVE's name `aarf`: the specification never uses that word (it does not occur in v0.8; it is a v0.5-era term), but renaming a container is a second break for readers of `aivss.aarf` on top of the changes in its content (D5) | +| `aivss.factor_sum` | `scores.factor_sum` | Stored, validated | +| `aivss.threat_maturity` and derived `aivss.thm` | `threat_multiplier` | Appendix A stores only the number. AVE stores the tier an assessor decides (`attacked`, `poc`, `unreported`) and the number it implies, and the validator checks they agree | +| `aivss.aars` | `scores.aars` | The uplift, up to five decimals, exact. This is a different meaning from today's `aars` (a factor sum), which is why 2.0.0 is a major version. The specification makes AARS optional (3.3.3, 3.5) and Appendix A makes it required; AVE stores it | +| `aivss.mitigation` and derived `aivss.mitigation_factor` | `scores.mitigation_factor` | As for the threat multiplier | +| `aivss.aivss_score` | `scores.aivss` | Name kept (existing field) | +| `aivss.aivss_severity` | `scores.severity` | Upper case (existing), title-cased on export | +| `aivss.core_risk` (new, optional) | `owasp_category` | The nearest Core Risk, the calibration anchor, one of Appendix A's ten names. Appendix A requires it, so an AVE record cannot be exported without it (D8) | +| `ave_id`, `title`, `description` (record level) | `id`, `title`, `description` | Mapped on export | +| `aivss.spec_version` | none | Kept, and no longer a constant: it names the specification the numbers follow (D13) | +| `aivss.notes` | `metadata.notes` | Kept | + +The exporter is not part of this work. The pilot data file shows the export is possible: the ten pilot records are written in Appendix A shape and validate against the transcribed schema. + +The validator for 2.0.0 should recompute and compare: the CVSS vector is valid v4.0; `cvss_base` equals its score under the two named implementations; every factor is 0.0, 0.5 or 1.0 and all ten are present; `factor_sum`; `thm` and `mitigation_factor` against their level names; `aars` exactly; `aivss_score` exactly; the band and the record's `severity`. + +## 11. Where the sources differ + +I found no difference between the specification and #395's reading of it. The differences are in the S01 task file, in AVE's documents, and in the draft PR. + +| # | Source | It says | The specification says | What was done | +|---|---|---|---|---| +| 1 | S01 task, `test_published_worked_example` | A "published worked example": CVSS 6.0, Factor_Sum 7.0, PoC, partial mitigation, AARS 2.716, AIVSS 7.2 | There is no such example. The only worked examples are the ten in 3.6, all with ThM 0.97 and Mitigation_Factor 1.0. The arithmetic of the task's example is right (2.716; 7.234 rounds to 7.2) | Test renamed. Consequence: no published example exercises ThM 1.00 or 0.50, or Mitigation_Factor 0.83 or 0.67, so those paths rest on the equation text alone | +| 2 | S01 task, `aivss_v08.score` | Float arithmetic | Round half up: "8.65 becomes 8.7" (3.5.1) | 36 of 19,089 grid inputs misround and 2 cross a band (section 3). Corrected to exact decimal; tests added for four tie inputs | +| 3 | S01 task, `BANDS` and `band(0.0) == "LOW"` | Low floor 0.0 | Low is 0.1 to 3.9 (3.5.2); 0.0 has no band | Floor set to 0.1; `band(0.0)` raises; test changed | +| 4 | S01 task, factor key names | `tools`, `language`, `persistence`, `identity`, `self_mod` | Same as Appendix A | Kept | +| 5 | `CONTRIBUTING.md` ("AIVSS v0.8 calculation"), `references/aivss-scoring.md`, `docs/specs/researcher-process.md` Step 5, `check_aivss_arithmetic` | `((CVSS_Base + AARS) / 2) x ThM x Mitigation_Factor` with AARS a factor sum | `(CVSS_Base + AARS) x Mitigation_Factor` with AARS an uplift (3.3.1, 3.4) | Known since #395; changes with 2.0.0 | +| 6 | `CONTRIBUTING.md` and `references/aivss-scoring.md` on `thm` | Two definitions of 1.0 (in the wild; demonstrated) | Table 4a | Section 7 | +| 7 | #399 | `cvss_base` is kept as the record states it; no catalog v1.3.0 | S00 shows the stored base differs from its vector for 85 of 88 valid vectors; the plan since decided v1.3.0 | #399's text is out of date on both and should be updated | +| 8 | Draft PR #401 | See below | | See below | +| 9 | The specification itself | Section 2.2: the factors "are listed in the exact order required for the calculation vector in Section 3" | Section 3 defines no vector string | Not a deviation; no vector format is proposed (U2) | +| 10 | The specification itself | Appendix D refers to "the scoring methodology described in Sections 4.1 to 4.8" | The methodology is Section 3; Section 4 has only 4.1 and 4.2 | Harmless dangling reference | +| 11 | The specification itself | 3.3.3 and 3.5: AARS "may be recorded", not the primary output | Appendix A requires `scores.aars` | AVE stores it | +| 12 | The specification itself | 3.6.8 scores Identity 1.0 for "inherits the agent's full system identity" | Table 2 defines Identity as role or identity change | AVE follows Table 2 (U4) | + +**Draft PR #401 (labelled design; seed material only).** Its claim to reproduce OWASP's ten worked examples holds. Its table of the ten (CVSS base, Factor_Sum, AARS, score) equals my transcription of the specification, its `aivss_v08` function reproduces all ten, and it agrees with exact decimal arithmetic on all 19,089 grid inputs. Its tests use only the base and the sum, so they do not check the vectors or the factor values; those were verified here separately. Its ThM values (0.5, 0.97, 1), Mitigation_Factor values (0.67, 0.83, 1), equations and rounding are the same as this file's. The differences: + +- **Factor keys.** It keeps AVE's eight names (`tool_use`, `natural_language_input`, `persistent_memory`, `dynamic_identity`, `self_modification` and three unchanged) and adds `context` and `opacity`. This statement uses Appendix A's names (D5). It carried eight factors over by value and kept the stored `cvss_base`; both contradict this plan. +- **Band floor.** Its validator keeps LOW at 0.0; the specification says 0.1. +- **AARS storage.** It stores AARS to four decimals and compares within half a unit of the fourth place; an exact AARS can have five (2.74995 in its own test), which is why it needs a tolerance. +- **`spec_version`** stays a constant `"0.8"`; the threat and mitigation levels are not stored, only their numbers. +- **The branch** is 31 commits behind `develop` (it lacks, for example, `tests/test_ave_conformance.py`), so its diff against `develop` shows deletions that are not its own; it needs a rebase before any reuse. + +## 12. Deviations from the specification, and open questions + +**Deviations: none intended.** Every constant, equation, rounding rule and band in section 3 is the specification's. AVE adds only what the specification leaves to the assessor: how to assess a class (section 5), what evidence supports a tier (7, 8), and which optional values to record (10). + +**Unresolved, to be settled with the decisions in section 13:** + +- **U1.** The specification gives no default for a factor (only for ThM and Mitigation_Factor). AVE's rule is that a factor with no stated basis is 0.0 (5.3, item 5). +- **U2.** "The calculation vector in Section 3" (2.2) is not defined. No vector string is proposed. +- **U3.** A score under 0.1 has no band (3.5.2); AVE rejects it. +- **U4.** Identity: Table 2 against the rationale in 3.6.8. AVE follows Table 2. +- **U5.** Whether CVSS v4.0 threat metrics may be in the base: the specification says "the CVSS v4.0 score of the vulnerability" and its examples are base vectors. AVE uses base metrics only. +- **U6.** The 0.67 floor is provisional (3.4.1) and may change in a later version of the specification. +- **U7.** Whether a class-level score has the meaning the specification gives a deployment-level score. AVE's position: a class score is the score of the class assessed in the RDP, and it is a reference point, not a finding in anyone's deployment. +- **U8.** The status of the AIVSS 1.0 candidate (D13). + +## 13. Decision list for the maintainer + +Each item has a recommendation. None is applied until approved in writing. + +**D1. Reference profile rule.** Adopt section 5.3: the RDP, mechanism factors from the class, deployment factors typical as shipped, an anchor per class, a stated basis for every non-zero factor. Alternatives: worst case for deployment factors (sets four factors to 1.0 almost everywhere), or a profile per component type (more precise, more to maintain). *Recommend: the RDP as written.* + +**D2. Subsequent-system impact, and reach counted once.** Score `SC/SI/SA` only for propagation the class itself states, and count tool reach once, in the Tools factor. The literal reading of 3.1.1 gives every steering class `SC:H/SI:H` and a base near 9.4. *Recommend: as written; it follows nine of OWASP's ten examples.* + +**D3. ThM mapping.** Options: (a) assess each record's tier from its cited sources (recommended); (b) map by value as #399 plans (agrees with the evidence for 4 of 10 pilot records, and calls two uncited records "Attacked"); (c) PoC for every record except cited in-the-wild exploitation. Option (a) needs primary sources, and 22 records still lack one (the quality queue). *Recommend (a), with PoC where the evidence tier cannot be told apart, and a rule that an in-the-wild claim must carry its citation.* + +**D4. Mitigation mapping.** Carry 1.0 to None and 0.83 to Partial by value, and apply section 8's definition to new assessments. *Recommend: yes.* `Strong` only with a cited validation. + +**D5. Field names.** Appendix A's ten inner key names; keep the container name `aarf`. The alternative is `amplification_factors` for full alignment, one more break for readers. *Recommend: inner keys renamed, container kept.* + +**D6. Levels and derived numbers.** Store `threat_maturity` and `mitigation` as well as the numbers, and validate they agree. *Recommend: yes.* + +**D7. AARS storage.** Store `aars` exactly, to five decimals, and compare exactly. *Recommend: yes.* + +**D8. `core_risk`.** Add the optional field, one of Appendix A's ten names, as the calibration anchor and for export. *Recommend: yes, optional.* + +**D9. A transition field.** Shape: `legacy_scoring` `{method: "ave-derived-v1", aarf_sum, aars, thm, mitigation_factor, aivss_score, aivss_severity}`. *Recommend: do not put it on active records.* The 1.x numbers stay in the frozen `dist/ave-records-v1.3.0.json`, in git history and in the `revisions` entry that records the change, and a field beside the new score invites the comparison 3.2 warns against. If the maintainer wants it, keep it to records whose `aivss` is optional (D10). + +**D10. `aivss` for `rejected` and `merged` records.** Make it optional for them, so no score is asserted for something declared not a class; keep it required for `active` and `deprecated`. Their last 1.x score stays in the frozen files and the status `revisions` entry. *Recommend: yes.* + +**D11. `vulnerability_rationale.agentic_distinction`.** Add as an optional documented string in 2.0.0 (not 2.1.0). The seven D7 JUSTIFY records already carry the distinction inside `vulnerability_rationale.vulnerability`; this gives it a place of its own for later records. *Recommend: yes.* + +**D12. CWE mapping field.** Conditional on TX4. TX4 has not been delivered, so there is no proposal to approve; the item stays on the list and nothing is added to 2.0.0 for it. + +**D13. The AIVSS 1.0 candidate.** Facts found on 2026-11-04: + +- The publications listed on `aivss.owasp.org` are v0.5 and v0.8; its homepage calls v0.8 "the latest version". The same homepage links "the AIVSS 1.0 calculator" at `aivss.owasp.org/calculator/`, titled "OWASP AIVSS 1.0 ยท Reference Calculator". +- OWASP's open letter of 2025-12-08 said v1.0 would be published at RSA 2026; v0.8 was published on 2026-03-19 instead. +- The candidate's repository is `kenhuangus/aivss-v1-calculator` (created 2026-08-28, last push 2026-10-22, Apache-2.0). Its owner login, `kenhuangus`, matches the Substack that signs the project's open letter as "Ken Huang, Co-Lead, OWASP AIVSS Project" (the letter is linked from `aivss.owasp.org`), and v0.8 names Ken Huang on the AIVSS leadership team; I did not verify that the GitHub account is that person's. It holds code only; its commit history shows the specification copies were removed, so the 1.0 specification text was not available to compare with. +- Its model differs from v0.8. There is no factor sum, ThM or Mitigation_Factor. Five categorical agentic metrics (LC, CP, AP, RH classify; ES informs an uplift) go in a separate `AIVSS:1.0/...` vector; the CVSS v4.0 score is kept unchanged (CVSS-BTE, so exploit maturity is in the CVSS vector); an Agentic Effect Class (A0, A1, A2, AX) is derived by a rule ladder; the AIVSS score is read from a lookup table keyed by the CVSS band and the class, and is never lower than CVSS-BTE. Its `legacy` command reproduces "withdrawn v0.x uplift scores" and says they must not be used for 1.0 compliance. +- It says of itself: "The Table 6 cell values are policy settings that have not yet been validated against independently rated findings"; the remediation overlay "not empirically calibrated"; `first_validation_status: not-submitted`; "OWASP does not endorse AIVSS v1". + +*Cost of a later move:* every class re-assessed on five new metrics; the ten factors, ThM and Mitigation_Factor leave the model; a new major schema (3.0.0). The CVSS v4.0 vector made authoritative here carries over; the factor judgments do not. *Recommend:* proceed with v0.8 as decided; keep method-specific values inside `aivss` and the CVSS vector outside it (as proposed), so a second method could be added beside the first; make `spec_version` a stated value and not a constant; and re-check the candidate's status before S03 starts, since S03 is where the cost is incurred. + +**D14. The severity distribution.** The pilot and the estimates say the same thing: under v0.8 most classes are HIGH or CRITICAL, MEDIUM is reachable mainly by classes with a narrow effect and a lower base, and LOW is unlikely. + +| Measure | CRITICAL | HIGH | MEDIUM | LOW | +|---|---|---|---|---| +| Today (89 records) | 1 | 20 | 66 | 2 | +| Estimate A: stored base, AVE's ten factors as they are, ThM 0.97 | 50 | 31 | 8 | 0 | +| Estimate B: stored base, the eight shared factors, ThM 0.97 | 41 | 39 | 9 | 0 | +| Estimate C: as B, ThM mapped by value | 37 | 41 | 11 | 0 | +| Floor: vector-computed base (S00), all ten factors 0, 88 valid vectors | 43 | 42 | 2 | 1 | +| Floor: stored base, all factors 0 | 15 | 48 | 26 | 0 | +| Ceiling: all factors 1 (vector-computed base / stored base) | 54 / 55 | 34 / 34 | 0 / 0 | 0 / 0 | +| Pilot, 10 records, before | 1 | 2 | 6 | 1 | +| Pilot, 10 records, after | 6 | 1 | 3 | 0 | + +The floors and ceilings use each record's stored Mitigation_Factor and ThM 0.97. The estimates run on non-conformant inputs (AVE's factors were not assigned against Table 2, Context and Opacity are unscored, and the stored bases are not the vector bases), so they are not a re-score. The pilot is ten records, six of them chosen by name, so it is not a sample and its frequencies must not be scaled up. What it supports: a class with a base of 9.0 or more and no mitigation credit is CRITICAL whatever the factors do (three of the four pilot records that never changed band under any alternative tried have such a base: AVE-2026-00001, 00044 and 00046; the fourth, 00066, has a base of 8.7 and a Factor_Sum of 5.0); bounded-effect classes can stay MEDIUM; and estimate C, applied to the pilot's ten, put 4 of the 10 in a different band from the pilot (6 agree). Re-derived pilot bases averaged 0.7 below both the stored bases (10 records) and the S00 vector bases (9 records), so the vector-based floor probably overstates. *Decision:* whether a distribution of this shape is acceptable to publish, and whether the README, the site and the implementer guide should say plainly that v0.8 raises most scores. *Recommend:* yes, and review the S03 vector re-derivation before the factor assignment, because it decides most of the outcome. + +**D15. A second assessor near the band edges.** In the pilot, 6 of 10 records change band under at least one reasonable alternative choice (vector, ThM rule, mitigation, or a half-point on every factor). *Recommend:* a second independent assessment for any record whose score is within 0.5 of a band boundary, using the annotator-agreement kit once it exists. + +**D16. Update #399.** Its statements that `cvss_base` is kept as stored and that there is no catalog v1.3.0 no longer match the plan. *Recommend:* edit #399 or close it in favour of a corrected tracking issue. From d71fae7d20434d53b0b302a88611dbe9e45ef7c3 Mon Sep 17 00:00:00 2001 From: chaksaray Date: Thu, 5 Nov 2026 06:09:54 +0700 Subject: [PATCH 2/5] docs: add the exact-decimal AIVSS arithmetic and tests, and D17 and D18 to the decision list (#446) Adds scripts/aivss_v08.py and tests/test_aivss_v08.py (OWASP's ten worked examples, the tie inputs a float product misrounds, the constants, the refusals); nothing imports the module yet. Rereads the conformance statement and the pilot and corrects them: the no-script-changed wording, D3's count of by-value Attacked tiers, an explicit denominator for the ThM finding, a duplicated sentence. Adds D17 (CVSS vector policy) and D18 (when to open the 30-day public comment period). Signed-off-by: chaksaray --- docs/audits/aivss-v0.8-pilot.md | 7 +- docs/specs/aivss-v0.8-conformance.md | 42 ++++++-- scripts/aivss_v08.py | 90 ++++++++++++++++ tests/test_aivss_v08.py | 156 +++++++++++++++++++++++++++ 4 files changed, 285 insertions(+), 10 deletions(-) create mode 100644 scripts/aivss_v08.py create mode 100644 tests/test_aivss_v08.py diff --git a/docs/audits/aivss-v0.8-pilot.md b/docs/audits/aivss-v0.8-pilot.md index c3780c4..be886c9 100644 --- a/docs/audits/aivss-v0.8-pilot.md +++ b/docs/audits/aivss-v0.8-pilot.md @@ -1,6 +1,6 @@ # AIVSS v0.8 pilot: ten records assessed under the conformance statement -Tests `docs/specs/aivss-v0.8-conformance.md` (S01, #399, issue #446) on ten real records. Report only: no record, schema file or script changed, and none of these scores is proposed for publication. The data is in `docs/audits/aivss-v0.8-pilot.json`, in the format of OWASP's Appendix A report schema. +Tests `docs/specs/aivss-v0.8-conformance.md` (S01, #399, issue #446) on ten real records. Report only: no record, schema file, validator or `dist/` file changed (the one code addition is the standalone arithmetic module `scripts/aivss_v08.py` and its tests), and none of these scores is proposed for publication. The data is in `docs/audits/aivss-v0.8-pilot.json`, in the format of OWASP's Appendix A report schema. **Date:** 2026-11-04. **Records:** `develop` at `0753b2d`. **Assessor:** one (the author of this report). No second assessment was made. @@ -11,6 +11,7 @@ Tests `docs/specs/aivss-v0.8-conformance.md` (S01, #399, issue #446) on ten real - **The result is not robust to reasonable alternative choices.** 6 of 10 records change band under at least one alternative (a different vector, ThM rule, mitigation level, or half a point on every factor). The four that never do (00001, 00044, 00046, 00066) have a CVSS base of 8.7 to 9.3 and Factor_Sum of 5.0 to 8.0. The CVSS vector is the most influential input: using the vector in the record today changes the band of 4 of the 9 records that have a valid one. - **The re-derived CVSS bases are lower on average than the ones in the records**: 0.7 below the stored `cvss_base` (10 records, from 2.6 lower to 0.9 higher) and 0.7 below the base of the stored vector (9 records, from 2.4 lower to 2.8 higher). So the corpus-wide estimate that uses the stored vectors probably overstates severity. - The earlier corpus estimate put 6 of the ten in the same band as the pilot. It was one band too high for three (00024, 00039, 00063) and one band too low for one (00019). +- Mapping today's `thm` by value agrees with the tier the cited evidence supports for **4 of the 10 pilot records** (00039, 00044, 00058, 00066). The ten are not a sample of the 89, so this is not a corpus rate; 49 of the 89 records are stored at 1.0, and only the five of them in the pilot were checked (one cites in-the-wild exploitation). - The statement changed in three places while piloting (end of this report). ## Selection rule (written before any record was assessed) @@ -185,7 +186,7 @@ The test: a class that sounds severe and a class that sounds narrow should not b - **MEDIUM (3).** 00039 leaks data through a channel with an explicit set of conditions and no effect on integrity or availability. 00063 removes a safety control but does nothing by itself: the harm is what the missing control then permits. 00058 only widens when a skill is invoked. None sounds as severe as the six, and none is CRITICAL. - **No LOW.** 00058 was LOW and is now MEDIUM, because a base of 5.1 is a floor under it: with its own Factor_Sum, ThM and mitigation, 00058 stays LOW only for a base of 3.6 or less. The record's own notes say its base and factors sit lower than the direct-injection classes, and it is the lowest-scoring class in the pilot. - **One rank inversion, and what the specification says about it.** 00044 (9.8) outscores 00046 (9.6), although 00046 intercepts every tool call and 00044 steers one action. The cause is the ThM tier (Attacked against Unreported). Section 3.2 of the specification says scores within the same band are equivalent for prioritisation and should not be ranked by decimal, so by the specification's own guidance there is no inversion; the conformance statement keeps that reading and AVE tooling should not rank by decimal within a band. -- **Where the check fails.** The six CRITICAL classes are not distinguished from one another by anything but a few tenths. The six sit between 9.0 and 9.8, separated by a few tenths that section 3.2 says not to rank on, and at a Factor_Sum of 6.5 or more every base of 7.0 or more scores 8.9 or higher. That follows from the equation (the conformance statement's section 5.4), not from the pilot's choices. +- **Where the check fails.** The six CRITICAL classes sit between 9.0 and 9.8, separated by a few tenths that section 3.2 says not to rank on, and at a Factor_Sum of 6.5 or more every base of 7.0 or more scores 8.9 or higher. That follows from the equation (the conformance statement's section 5.4), not from the pilot's choices. ## What the pilot changed in the statement @@ -205,4 +206,4 @@ Separately, the S01 task's `aivss_v08.py` was found to misround 36 of 19,089 gri ## Reproduction -The data file `docs/audits/aivss-v0.8-pilot.json` holds, for each record, the vector, the base score, the ten factors, ThM, Mitigation_Factor, Factor_Sum, AARS, the score and the band, in Appendix A's shape; it validates against that schema as transcribed from the specification. To recompute: score each `vector_string` with both CVSS v4.0 implementations named above; compute `AARS = (10 - base) x (factor_sum / 10) x threat_multiplier` and `score = RoundHalfUp((base + AARS) x mitigation_factor, 1)` in decimal arithmetic (the statement's section 3 has the reference form). The harness used here (arithmetic module, tests, mutation check, Appendix A validator) is not part of this change; S02 adds the arithmetic and its tests to the repository. +The data file `docs/audits/aivss-v0.8-pilot.json` holds, for each record, the vector, the base score, the ten factors, ThM, Mitigation_Factor, Factor_Sum, AARS, the score and the band, in Appendix A's shape; it validates against that schema as transcribed from the specification. To recompute: score each `vector_string` with both CVSS v4.0 implementations named above; compute `AARS = (10 - base) x (factor_sum / 10) x threat_multiplier` and `score = RoundHalfUp((base + AARS) x mitigation_factor, 1)` in decimal arithmetic (the statement's section 3 has the reference form). The exact arithmetic is `scripts/aivss_v08.py`, with its tests in `tests/test_aivss_v08.py` (part of this change). The CVSS scoring harness, the sensitivity script and the Appendix A validator used here are not part of this change. diff --git a/docs/specs/aivss-v0.8-conformance.md b/docs/specs/aivss-v0.8-conformance.md index 6ec1238..6d51b18 100644 --- a/docs/specs/aivss-v0.8-conformance.md +++ b/docs/specs/aivss-v0.8-conformance.md @@ -1,8 +1,8 @@ # AIVSS v0.8 conformance statement for AVE -**Status: draft for the maintainer's decision.** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, script or `dist/` file changes. Nothing here becomes AVE's rule until the maintainer approves the decision list in section 13. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. +**Status: draft for the maintainer's decision.** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, validator or `dist/` file changes. The one code addition is a standalone arithmetic module, `scripts/aivss_v08.py`, with its tests in `tests/test_aivss_v08.py`; nothing imports it. Nothing here becomes AVE's rule until the maintainer approves the decision list in section 13. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. -**Date:** 2026-11-04. **Repository state:** `develop` at `0753b2d`. +**Date:** 2026-11-04, reread and extended 2026-11-05 (the arithmetic module and its tests, decision D17). **Repository state:** `develop` at `0753b2d`. ## 1. What this statement is for @@ -37,7 +37,7 @@ Where a secondary source, a task file or an AVE document differs from the specif The score is computed from the unrounded AARS (3.4.0, step 3). AARS has at most five decimal places for every legal input (CVSS to one decimal, Factor_Sum in steps of 0.5, ThM to two decimals; checked by enumerating the whole input grid), so an exact stored AARS needs five places. -**Arithmetic must be exact decimal.** A float product misrounds raw values that are exact ties. Over the full grid (CVSS 0.0 to 10.0 in steps of 0.1, Factor_Sum 0.0 to 10.0 in steps of 0.5, three ThM levels, three mitigation levels: 19,089 inputs) a float implementation rounds 36 results, every one exactly one tenth low, and 2 of those cross a band: for example CVSS 3.9, Factor_Sum 5.0, ThM 1.00, Mitigation_Factor 1.0 has raw score 6.95, which the specification's rule makes 7.0 HIGH and a float product makes 6.9 MEDIUM. The reference arithmetic below is exact; it is the form S02 should adopt. +**Arithmetic must be exact decimal.** A float product misrounds raw values that are exact ties. Over the full grid (CVSS 0.0 to 10.0 in steps of 0.1, Factor_Sum 0.0 to 10.0 in steps of 0.5, three ThM levels, three mitigation levels: 19,089 inputs) a float implementation rounds 36 results, every one exactly one tenth low, and 2 of those cross a band: for example CVSS 3.9, Factor_Sum 5.0, ThM 1.00, Mitigation_Factor 1.0 has raw score 6.95, which the specification's rule makes 7.0 HIGH and a float product makes 6.9 MEDIUM. `scripts/aivss_v08.py` is the exact implementation. Its tests (`tests/test_aivss_v08.py`) cover OWASP's ten examples, the tie inputs above, the constants, the refusals and the five-decimal bound on AARS, and all 22 mutations of the module that were tried are caught. The excerpt below is its core. ```python from decimal import Decimal as D, ROUND_HALF_UP @@ -61,7 +61,7 @@ def band(score): # 3.5.2; below 0.1 the specificat ## 4. How `cvss_base` is determined -v0.8 takes a CVSS v4.0 base score as input (3.1.1). The audit in `docs/audits/cvss-input-reconciliation.md` (S00, #403) found that the stored `cvss_base` equals the score of the record's own vector for 3 of 88 valid vectors, and that one vector (AVE-2026-00066) is not valid CVSS v4.0. Because v0.8 adds the uplift to the base, the base is the floor of the score (section 5.4). This statement therefore makes the vector the input and the number a derived value. +v0.8 takes a CVSS v4.0 base score as input (3.1.1). The audit in `docs/audits/cvss-input-reconciliation.md` (S00, #403) found that the stored `cvss_base` equals the score of the record's own vector for 3 of 88 valid vectors, and that one vector (AVE-2026-00066) is not valid CVSS v4.0. Because v0.8 adds the uplift to the base, the base is the floor of the score (section 5.4). This statement therefore makes the vector the input and the number a derived value. Decision D17 sets the policy for choosing among sources for a vector and for the subsequent-system metrics. 1. **The vector is authoritative.** `cvss_base_vector` is the assessment; `aivss.cvss_base` is the score computed from it. A validator rule recomputes it and fails on a mismatch. 2. **Base metrics only.** The vector carries the eleven base metrics. Threat (`E`) and environmental metrics are not used: exploit maturity is already ThM, and counting it in both would count it twice. The specification's own examples are base vectors (3.6). @@ -131,7 +131,7 @@ Because v0.8 adds the uplift to the CVSS base, the base is a floor. With OWASP's | 8.0 | 8.2 | 8.7 | 9.1 | 9.6 | 0.0 | 5.4 | | 9.5 | 9.4 | 9.5 | 9.7 | 9.8 | 0.0 | 0.0 | -(ThM 0.97, Mitigation_Factor 1.0.) At OWASP's lowest sum, a class is HIGH from a base of 1.8. The only things that keep a class with a high base out of HIGH or CRITICAL are a low Factor_Sum and a Mitigation_Factor below 1. For the corpus this means the CVSS vectors, not the factors, decide most of the severity distribution (decision D14). +(ThM 0.97, Mitigation_Factor 1.0.) At OWASP's lowest sum, a class is HIGH from a base of 1.8. The only things that keep a class with a high base out of HIGH or CRITICAL are a low Factor_Sum and a Mitigation_Factor below 1. For the corpus this means the CVSS vectors, not the factors, decide most of the severity distribution (decisions D14 and D17). ## 6. The ten factors for a catalogue entry @@ -164,7 +164,7 @@ AVE's current factors map as follows (they were assigned against AVE's own defin The specification's default is 0.97 and argues that for agentic exploits the distance from proof of concept to attack is negligible (3.3.2). AVE therefore uses PoC when the evidence tier cannot be told apart, and records the tier and its source in the notes. -**What happens to today's `thm` (1, 0.9, 0.75).** The plan in #399 maps them by definition (0.75 to Unreported, 0.9 to PoC, 1.0 to Attacked). That is wrong for 1.0, because AVE's own documents define it two ways. `CONTRIBUTING.md` says 1.0 is "exploited in the wild or weaponised". `references/aivss-scoring.md` says 1 is "real and demonstrated (a disclosed CVE, published research, a working exploit description)" and that "every record in this corpus so far has scored 1". In the pilot, mapping by value agrees with the tier the cited evidence supports for 4 of 10 records. Of the five pilot records stored at 1.0, one cites an in-the-wild source (AVE-2026-00044); two are PoC; two cite nothing that demonstrates the class (and AVE-2026-00046's writeup says its 1.0 "reflects ... an in-the-wild threat maturity" while the record cites no incident). Two of the four stored at 0.75 are demonstrated in cited research and are PoC. This is decision D3. +**What happens to today's `thm` (1, 0.9, 0.75).** The plan in #399 maps them by definition (0.75 to Unreported, 0.9 to PoC, 1.0 to Attacked). That is wrong for 1.0, because AVE's own documents define it two ways. `CONTRIBUTING.md` says 1.0 is "exploited in the wild or weaponised". `references/aivss-scoring.md` says 1 is "real and demonstrated (a disclosed CVE, published research, a working exploit description)" and that "every record in this corpus so far has scored 1". In the pilot, mapping by value agrees with the tier the cited evidence supports for **4 of the 10 pilot records** (00039, 00044, 00058, 00066). The ten are not a sample of the 89, so no corpus rate follows: 49 of the 89 records are stored at 1.0, and only the five of those in the pilot were checked against their sources. Of those five, one cites an in-the-wild source (AVE-2026-00044); two are PoC; two cite nothing that demonstrates the class (and AVE-2026-00046's writeup says its 1.0 "reflects ... an in-the-wild threat maturity" while the record cites no incident). Two of the four stored at 0.75 are demonstrated in cited research and are PoC. This is decision D3. ## 8. The mitigation factor @@ -277,7 +277,7 @@ Each item has a recommendation. None is applied until approved in writing. **D2. Subsequent-system impact, and reach counted once.** Score `SC/SI/SA` only for propagation the class itself states, and count tool reach once, in the Tools factor. The literal reading of 3.1.1 gives every steering class `SC:H/SI:H` and a base near 9.4. *Recommend: as written; it follows nine of OWASP's ten examples.* -**D3. ThM mapping.** Options: (a) assess each record's tier from its cited sources (recommended); (b) map by value as #399 plans (agrees with the evidence for 4 of 10 pilot records, and calls two uncited records "Attacked"); (c) PoC for every record except cited in-the-wild exploitation. Option (a) needs primary sources, and 22 records still lack one (the quality queue). *Recommend (a), with PoC where the evidence tier cannot be told apart, and a rule that an in-the-wild claim must carry its citation.* +**D3. ThM mapping.** Options: (a) assess each record's tier from its cited sources (recommended); (b) map by value as #399 plans (agrees with the evidence for 4 of the 10 pilot records, which are not a sample of the 89; of the five pilot records stored at 1.0 it calls all five Attacked, where the evidence supports that for one); (c) PoC for every record except cited in-the-wild exploitation. Option (a) needs primary sources, and 22 records still lack one (the quality queue). *Recommend (a), with PoC where the evidence tier cannot be told apart, and a rule that an in-the-wild claim must carry its citation.* **D4. Mitigation mapping.** Carry 1.0 to None and 0.83 to Partial by value, and apply section 8's definition to new assessments. *Recommend: yes.* `Strong` only with a cited validation. @@ -326,3 +326,31 @@ The floors and ceilings use each record's stored Mitigation_Factor and ThM 0.97. **D15. A second assessor near the band edges.** In the pilot, 6 of 10 records change band under at least one reasonable alternative choice (vector, ThM rule, mitigation, or a half-point on every factor). *Recommend:* a second independent assessment for any record whose score is within 0.5 of a band boundary, using the annotator-agreement kit once it exists. **D16. Update #399.** Its statements that `cvss_base` is kept as stored and that there is no catalog v1.3.0 no longer match the plan. *Recommend:* edit #399 or close it in favour of a corrected tracking issue. + +**D17. CVSS vector policy.** The base is the floor of the v0.8 score (section 5.4), and the vectors in the records today put it high. Of the 88 valid vectors, 67 compute to a base of 9.0 or more and 87 to 7.0 or more (only AVE-2026-00058, at 2.3, is below 7.0; nine are exactly 10.0), and 63 set at least one subsequent-system metric to High (19 set all three). A class with a base of 9.0 and no mitigation credit is CRITICAL whatever its factors say, so the vectors, more than the factors, will decide the distribution. Proposed policy for the S03 re-derivation: + +1. **Prefer the primary-source advisory vector.** Where a record cites an advisory, CVE or GHSA whose publisher gave a CVSS v4.0 vector for this mechanism, start from that vector and cite it. If the publisher gave only CVSS 3.1, do not convert it (3.1.1): derive the vector by section 4 and note the advisory's score as context. If the advisory is for the nearest instance and not the class, say so and change only what the class differs in. +2. **Score the vulnerable system's own impact.** `VC`, `VI` and `VA` are the effect on the agent runtime and its host that the class causes by itself. Downstream effects are not folded in. +3. **Subsequent-system High only when demonstrated.** `SC`, `SI` or `SA` is `H` only when a cited source demonstrates the propagation (an incident, an advisory, a paper that shows it). Propagation the description merely states is `L` at most, and absent propagation is `N`. This tightens D2, which scores stated propagation. Applied to the pilot it would change AVE-2026-00046, whose `SC/SI:H` rest on the description (with `L` the base is 8.6 and the score 9.2, still CRITICAL), and leave AVE-2026-00020 as it is (Cohen et al. 2024 demonstrates propagation between agents). +4. **A second assessor on ten records.** Before S03 starts, a second assessor, or a separate pass that has not seen the first vectors, derives vectors independently for the pilot's ten records, and the two sets are compared metric by metric. The comparison reports exact-vector agreement per metric, the difference in base score, and whether the band agrees. The pass thresholds are the maintainer's to set. Without a pass, the section 4 rules are not yet reproducible enough to apply to 89 records. + +*Recommend: adopt 1 to 4.* The pilot's own sensitivity is the evidence for 4: 6 of 10 records change band under one alternative choice, and the vector is the choice that moves the most (4 of the 9 records with a valid stored vector). + +**D18. When to open the 30-day public comment period.** `CONTRIBUTING.md` ("Schema changes") says a major schema version "needs a migration path for existing records and a 30-day comment period before merging". It names no start event, no venue and no content. Schema 2.0.0 is a major version: it changes the meaning of `aars` and `thm`, removes two `aarf` keys and renames five. The release step S05 gates on the period having closed. + +*Recommend:* open it as soon as the S01 pull request merges, so that what the public reads is the approved statement and not a draft. Open it in a public issue or discussion on `aveproject/ave`, not in a comment on the pull request, and put in the opening post: + +1. links to the conformance statement, the pilot report with its data file, and the migration path; +2. the migration path as it stands then: what each existing field becomes (the `aarf` keys, `aars`, `thm`, `mitigation_factor`, the score and severity, `schema_version`), what happens to the 1.x numbers (D9, D10), and what consumers must change. Section 10 of the statement is the field mapping; the per-record migration itself comes later, in S03; +3. the day it opens and the day it closes; +4. what is open to change (the choices in D1 to D17) and what is not (the equations, constants and bands, which are OWASP's); +5. how to comment, and that each comment gets a written answer on the thread before S05. + +Points the maintainer should settle: + +- **The clock starts when the post is made**, not when this list is approved, and nothing is posted before the S01 pull request has merged. The post is a public act, so it is drafted for approval first. +- **Early or late.** Opening before S03 lets comments change the method before 89 records are re-assessed, which is cheap, but the public cannot yet see re-scored values. Opening after S03 shows the real numbers, but a change to the method then costs a re-score. Recommend early. +- **What restarts the clock.** Proposed: a change to the equations, the field mapping or the migration path restarts the 30 days; an editorial change does not. +- **Where it is announced.** The thread should be somewhere downstream tools and consumers of the dist files can subscribe to. Which channels is the maintainer's call, and nothing is announced outside the repository without approval. +- **What "merging" means.** The wording is "before merging". Read here as the merge that publishes schema 2.0.0 (S05), not the merges into a `release/2.0` branch. If the maintainer reads it as the first merge of 2.0.0 files into `develop`, the period has to be complete before S02. + diff --git a/scripts/aivss_v08.py b/scripts/aivss_v08.py new file mode 100644 index 0000000..e9ab2c0 --- /dev/null +++ b/scripts/aivss_v08.py @@ -0,0 +1,90 @@ +"""The OWASP AIVSS v0.8 arithmetic, in exact decimal. Pure functions, no I/O. + +Nothing imports this yet. It is the reference arithmetic that docs/specs/aivss-v0.8-conformance.md describes, kept +standalone until the maintainer approves that statement; schema 2.0.0 work would wire it into scripts/validate_records.py. + +Source: "AIVSS Scoring System For OWASP Agentic AI Core Security Risks v0.8", Part 2 (SHA-256 +a2abbd215f0d7790d273c30a893a09c0dc37a6c109765eb0363c01af897fd9af): + factors 2.1, 2.2 and Table 1, with the key names of Appendix A; AARS 3.3.1; ThM 3.3.2 (Table 4a); + primary equation 3.4 and 3.4.0; Mitigation_Factor 3.4.1 (Table 4b); rounding 3.5.1; bands 3.5.2. + +All arithmetic is exact decimal. A float product misrounds raw values that are exact ties (8.65 must become 8.7, +3.5.1): over the whole input grid a float implementation is one tenth low for 36 of 19,089 inputs. +""" + +from decimal import ROUND_HALF_UP, Decimal + +D = Decimal +FACTORS = ("autonomy", "tools", "language", "context", "non_determinism", "opacity", "persistence", "identity", "multi_agent", "self_mod") +FACTOR_LEVELS = (D("0.0"), D("0.5"), D("1.0")) +THM = {"attacked": D("1.00"), "poc": D("0.97"), "unreported": D("0.50")} # Table 4a; the specification's default is poc +MITIGATION = {"none": D("1.00"), "partial": D("0.83"), "strong": D("0.67")} # Table 4b; default none; 0.67 is provisional +BANDS = (("CRITICAL", D("9.0")), ("HIGH", D("7.0")), ("MEDIUM", D("4.0")), ("LOW", D("0.1"))) # 3.5.2; 0.0 has no band + + +# What: turns a number or a string into an exact Decimal +# Why: Decimal(float) carries the binary error that Decimal(str(float)) does not +# How: pass a Decimal through unchanged, convert anything else through its shortest string +def _d(x): + return x if isinstance(x, Decimal) else D(str(x)) + + +# What: rounds half up to one decimal (3.5.1: 8.64 becomes 8.6, 8.65 becomes 8.7) +# Why: Python's round() is ties-to-even on a float, which is what AVE's 1.x scores used +# How: exact Decimal quantize with ROUND_HALF_UP +def r1(x): + return float(_d(x).quantize(D("0.1"), rounding=ROUND_HALF_UP)) + + +# What: sums the ten factors exactly after checking the key set and every level +# Why: an eleventh key, a missing factor or a value like 0.3 would change every score without any error +# How: compare the keys with FACTORS, check each value is 0.0, 0.5 or 1.0, add as Decimals +def _factor_sum(aarf): + if set(aarf) != set(FACTORS): + raise ValueError(f"aarf must have exactly the ten v0.8 factors, got {sorted(set(aarf) ^ set(FACTORS))} different") + for k, v in aarf.items(): + if _d(v) not in FACTOR_LEVELS: + raise ValueError(f"{k}={v} is not one of {tuple(float(x) for x in FACTOR_LEVELS)}") + return sum((_d(v) for v in aarf.values()), D(0)) + + +# What: Factor_Sum as a float (3.3.1) +# Why: callers store and compare it as a plain number; every legal sum is a multiple of 0.5, so the float is exact +# How: the exact sum, converted +def factor_sum(aarf): + return float(_factor_sum(aarf)) + + +# What: the agentic uplift AARS = (10 - CVSS_Base) x (Factor_Sum / 10) x ThM, exact (3.3.1) +# Why: the score uses the unrounded uplift (3.4.0 step 3), and a stored AARS needs all of its places (at most five) +# How: Decimal arithmetic; cvss_base must lie in 0.0 to 10.0 and thm_level must be a key of THM +def aars_exact(cvss_base, aarf, thm_level): + c = _d(cvss_base) + if not D(0) <= c <= D(10): + raise ValueError("cvss_base out of range") + return (D(10) - c) * (_factor_sum(aarf) / D(10)) * THM[thm_level] + + +# What: the uplift as a float +# Why: convenient for display and approximate comparison; never use it to compute a score +# How: the exact uplift, converted +def aars(cvss_base, aarf, thm_level): + return float(aars_exact(cvss_base, aarf, thm_level)) + + +# What: AIVSS = RoundHalfUp((CVSS_Base + AARS) x Mitigation_Factor, 1) (3.4, 3.4.0, 3.5.1) +# Why: this is the number a record states and a validator recomputes +# How: one exact Decimal expression, rounded once at the end +def score(cvss_base, aarf, thm_level, mitigation_level): + return r1((_d(cvss_base) + aars_exact(cvss_base, aarf, thm_level)) * MITIGATION[mitigation_level]) + + +# What: the severity band of a reported score (3.5.2) +# Why: CLAUDE.md hard rule 6 ties a record's severity to its score +# How: the first band whose floor the score reaches; below 0.1 the specification defines no band, so raise +def band(s): + v = _d(s) + for name, floor in BANDS: + if v >= floor: + return name + raise ValueError(f"{s} is below 0.1; AIVSS v0.8 defines no band for it (3.5.2)") diff --git a/tests/test_aivss_v08.py b/tests/test_aivss_v08.py new file mode 100644 index 0000000..aeb4ffc --- /dev/null +++ b/tests/test_aivss_v08.py @@ -0,0 +1,156 @@ +"""scripts/aivss_v08.py: the OWASP AIVSS v0.8 arithmetic, in exact decimal. + +Sources are sections of "AIVSS Scoring System For OWASP Agentic AI Core Security Risks v0.8" (Part 2): 3.3.1 (AARS), +3.3.2 Table 4a (ThM), 3.4 and 3.4.0 (primary equation), 3.4.1 Table 4b (Mitigation_Factor), 3.5.1 (rounding), +3.5.2 (bands), and the ten worked examples of 3.6, which all use ThM 0.97 and Mitigation_Factor 1.0. +""" + +from decimal import Decimal + +import pytest + +from scripts import aivss_v08 as av + +FACTORS = av.FACTORS + +# OWASP section 3.6: (section, CVSS base, the ten factors in the specification's order, Factor_Sum, AARS, final score, band). +OWASP_EXAMPLES = [ + ("3.6.1", 9.4, (1, 1, 1, 1, 1, 1, .5, 1, 1, .5), 9.0, "0.5238", 9.9, "CRITICAL"), + ("3.6.2", 8.7, (1, 1, 1, 1, .5, 1, 1, 1, .5, 0), 8.0, "1.0088", 9.7, "CRITICAL"), + ("3.6.3", 7.1, (1, .5, 1, 1, 1, 1, .5, .5, 1, .5), 8.0, "2.2504", 9.4, "CRITICAL"), + ("3.6.4", 9.4, (1, 1, 1, 1, 1, 1, 1, 1, 1, .5), 9.5, "0.5529", 10.0, "CRITICAL"), + ("3.6.5", 7.4, (1, 1, 1, 1, 1, 1, 0, 1, .5, 0), 7.5, "1.8915", 9.3, "CRITICAL"), + ("3.6.6", 5.8, (1, .5, 1, 1, .5, 1, 1, 0, .5, 1), 7.5, "3.0555", 8.9, "HIGH"), + ("3.6.7", 6.9, (1, 1, .5, 1, .5, 1, .5, 0, 1, 1), 7.5, "2.25525", 9.2, "CRITICAL"), + ("3.6.8", 9.3, (1, 1, 0, 0, 1, 1, .5, 1, 1, 0), 6.5, "0.44135", 9.7, "CRITICAL"), + ("3.6.9", 5.3, (1, 1, 0, 0, 1, 1, .5, .5, 1, .5), 6.5, "2.96335", 8.3, "HIGH"), + ("3.6.10", 2.1, (.5, 0, 1, 1, 1, 1, 1, 0, 0, 1), 6.5, "4.98095", 7.1, "HIGH"), +] + + +def f(**kw): + d = {k: 0.0 for k in FACTORS} + d.update(kw) + return d + + +def spread(factor_sum): + """Ten factors, each 0, 0.5 or 1, whose sum is `factor_sum`.""" + vals = [1.0] * int(factor_sum // 1) + ([0.5] if factor_sum % 1 else []) + return dict(zip(FACTORS, vals + [0.0] * (10 - len(vals)))) + + +@pytest.mark.parametrize("row", OWASP_EXAMPLES, ids=[r[0] for r in OWASP_EXAMPLES]) +def test_the_equation_reproduces_each_of_owasps_ten_worked_examples(row): + _, base, vals, fsum, aars, final, band = row + a = dict(zip(FACTORS, vals)) + assert av.factor_sum(a) == fsum + assert av.aars_exact(base, a, "poc") == Decimal(aars) + assert av.score(base, a, "poc", "none") == final + assert av.band(final) == band + + +def test_the_factor_names_are_appendix_a_s(): + assert FACTORS == ("autonomy", "tools", "language", "context", "non_determinism", "opacity", "persistence", "identity", "multi_agent", "self_mod") + + +def test_an_example_that_is_not_from_the_specification(): + # AVE's own hand check, not one of OWASP's: CVSS 6.0, factor sum 7.0, PoC, partial mitigation: AARS 2.716, AIVSS 7.2 (High). + a = f(autonomy=1, tools=1, language=1, context=1, non_determinism=1, opacity=1, persistence=1) + assert av.factor_sum(a) == 7.0 + assert av.aars_exact(6.0, a, "poc") == Decimal("2.716") + assert av.score(6.0, a, "poc", "partial") == 7.2 and av.band(7.2) == "HIGH" + + +def test_uplift_is_bounded_by_the_gap_to_ten(): + all1 = {k: 1.0 for k in FACTORS} + assert av.aars(10.0, all1, "attacked") == 0.0 + assert av.score(9.0, all1, "attacked", "none") == 10.0 + assert av.score(8.5, f(), "attacked", "none") == 8.5 # no agentic factors: the score is the CVSS base + + +def test_without_mitigation_credit_the_score_is_never_below_the_cvss_base(): + for c in (0.0, 3.3, 5.5, 7.7, 9.9): + assert av.score(c, f(autonomy=0.5), "poc", "none") >= c + + +def test_each_threat_multiplier_level_scales_the_uplift(): + all1 = {k: 1.0 for k in FACTORS} # gap 5.0, factor sum 10: AARS is gap x ThM + assert av.aars(5.0, all1, "attacked") == 5.0 + assert av.aars(5.0, all1, "poc") == pytest.approx(4.85) + assert av.aars(5.0, all1, "unreported") == 2.5 + + +def test_each_mitigation_level_scales_the_score(): + all1 = {k: 1.0 for k in FACTORS} # CVSS 6.0, PoC: raw 9.88 before mitigation + assert [av.score(6.0, all1, "poc", m) for m in ("none", "partial", "strong")] == [9.9, 8.2, 6.6] + + +def test_the_constants_are_the_specifications(): + assert av.THM == {"attacked": Decimal("1.00"), "poc": Decimal("0.97"), "unreported": Decimal("0.50")} + assert av.MITIGATION == {"none": Decimal("1.00"), "partial": Decimal("0.83"), "strong": Decimal("0.67")} + assert av.FACTOR_LEVELS == (Decimal("0.0"), Decimal("0.5"), Decimal("1.0")) + + +def test_inputs_outside_the_specification_are_refused(): + with pytest.raises(ValueError): + av.factor_sum(f(autonomy=0.3)) + with pytest.raises(ValueError): + av.factor_sum({"autonomy": 1.0}) + with pytest.raises(ValueError): + av.factor_sum({**f(), "data_access": 1.0}) # an eleventh key + with pytest.raises(KeyError): + av.aars(5.0, f(), "theoretical") + with pytest.raises(KeyError): + av.score(5.0, f(), "poc", "weak") + for bad in (-0.1, 10.1): + with pytest.raises(ValueError): + av.aars(bad, f(), "poc") + + +@pytest.mark.parametrize("raw,expected", [(8.64, 8.6), (8.65, 8.7)]) +def test_the_specifications_own_rounding_examples(raw, expected): + assert av.r1(raw) == expected # 3.5.1 + + +def test_rounding_is_half_up_and_not_ties_to_even(): + assert av.r1(7.25) == 7.3 and av.r1(7.35) == 7.4 and av.r1(0.05) == 0.1 and av.r1(8.25) == 8.3 + + +@pytest.mark.parametrize("cvss,fsum,thm,mit,expected", [ + (1.0, 8.5, "attacked", "none", 8.7), # raw 8.65 exactly; a float product gives 8.6 + (0.0, 5.0, "attacked", "partial", 4.2), # raw 4.15 + (1.0, 1.5, "attacked", "none", 2.4), # raw 2.35 + (3.9, 5.0, "attacked", "none", 7.0), # raw 6.95: a float product gives 6.9 MEDIUM, the exact result is 7.0 HIGH +]) +def test_exact_ties_round_up_the_way_the_specification_says(cvss, fsum, thm, mit, expected): + assert av.factor_sum(spread(fsum)) == fsum + assert av.score(cvss, spread(fsum), thm, mit) == expected + if expected == 7.0: + assert av.band(expected) == "HIGH" + + +def test_the_score_comes_from_the_unrounded_uplift_not_the_stored_four_decimals(): + # AARS is exactly 2.74995 (five places). Rounded to four places it is 2.7500, which would give 4.65 and round up to 4.7. + a = f(autonomy=1, tools=1, multi_agent=1, context=0.5) + assert av.aars_exact(1.9, a, "poc") == Decimal("2.74995") and av.factor_sum(a) == 3.5 + assert av.score(1.9, a, "poc", "none") == 4.6 + + +def test_an_exact_uplift_never_needs_more_than_five_decimal_places(): + most = 0 + for c10 in range(0, 101): + for k in range(0, 21): + for thm in av.THM: + exp = -av.aars_exact(c10 / 10, spread(k / 2), thm).normalize().as_tuple().exponent + most = max(most, exp) + assert most == 5 + + +def test_bands(): + assert [av.band(x) for x in (10.0, 9.0, 8.9, 7.0, 6.9, 4.0, 3.9, 0.1)] == ["CRITICAL", "CRITICAL", "HIGH", "HIGH", "MEDIUM", "MEDIUM", "LOW", "LOW"] + + +def test_a_score_below_0_1_has_no_band_in_the_specification(): + with pytest.raises(ValueError): + av.band(0.0) From 0b2bc051ae8db0d166d6ca30e4ed3994991e3c06 Mon Sep 17 00:00:00 2001 From: chaksaray Date: Thu, 5 Nov 2026 06:31:10 +0700 Subject: [PATCH 3/5] docs: record the approvals, replace D17 with the CVSS vector policy, add D19 and D20 (#446) Approved by the maintainer on 2026-11-05: D1 to D12 (D12 conditional on TX4), D15, D16 and D18; D13, D14 and D17 as changed in the same message. D17 is now the CVSS-B-only policy (reasonable worst case per FIRST, subsequent systems by security domain, tool reach counted once, advisory vector as a start, two implementations, a second assessor on ten records). Corrects the subsequent-system count: 82 of 88 valid vectors have at least one of SC, SI, SA High, not 63 (63 had one or two). Adds D19 (S03a and S03b) and D20 (5 to 8 reference deployment profiles), neither yet approved in writing. Signed-off-by: chaksaray --- docs/audits/aivss-v0.8-pilot.md | 1 + docs/specs/aivss-v0.8-conformance.md | 68 ++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/docs/audits/aivss-v0.8-pilot.md b/docs/audits/aivss-v0.8-pilot.md index be886c9..8fe62c5 100644 --- a/docs/audits/aivss-v0.8-pilot.md +++ b/docs/audits/aivss-v0.8-pilot.md @@ -203,6 +203,7 @@ Separately, the S01 task's `aivss_v08.py` was found to misround 36 of 19,089 gri - Coverage is partial (see the selection rule): one `mcp_server`, no `agent` component, 8 of 13 entry classes. - The ThM tiers rest on the references each record cites today. Four of the ten (00024, 00039, 00046, 00058) cite nothing that demonstrates the class; the tier would change if a primary source is found (the quality queue has the 22 records that have none). - Nothing was checked against NVD or against a vendor's own CVSS vector for the nearest instances (for example CVE-2026-33068). +- The vectors were derived before decision D17 was approved (2026-11-05) and are not re-derived here. Its parts 2 and 4 (the reasonable worst case, and subsequent systems by security domain) may change some of them; S03a re-derives them. The pilot's value now is as evidence of how much the outcome moves, not as scores to apply. ## Reproduction diff --git a/docs/specs/aivss-v0.8-conformance.md b/docs/specs/aivss-v0.8-conformance.md index 6d51b18..bb3ed77 100644 --- a/docs/specs/aivss-v0.8-conformance.md +++ b/docs/specs/aivss-v0.8-conformance.md @@ -1,8 +1,8 @@ # AIVSS v0.8 conformance statement for AVE -**Status: draft for the maintainer's decision.** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, validator or `dist/` file changes. The one code addition is a standalone arithmetic module, `scripts/aivss_v08.py`, with its tests in `tests/test_aivss_v08.py`; nothing imports it. Nothing here becomes AVE's rule until the maintainer approves the decision list in section 13. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. +**Status (2026-11-05): decisions D1 to D12, D15, D16 and D18 are approved by the maintainer (D12 stays conditional on TX4); D13, D14 and D17 are approved as changed in the same message; D19 and D20 were added at the maintainer's direction and are not yet approved in writing (section 13).** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, validator or `dist/` file changes. The one code addition is a standalone arithmetic module, `scripts/aivss_v08.py`, with its tests in `tests/test_aivss_v08.py`; nothing imports it. Nothing here becomes AVE's rule except what section 13 marks approved, and nothing is applied to a record before S02, which waits for this pull request to merge and the public comment period (D18) to open. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. -**Date:** 2026-11-04, reread and extended 2026-11-05 (the arithmetic module and its tests, decision D17). **Repository state:** `develop` at `0753b2d`. +**Date:** 2026-11-04, reread and extended 2026-11-05 (the arithmetic module and its tests, the approvals, D17 to D20). **Repository state:** `develop` at `0753b2d`. ## 1. What this statement is for @@ -76,9 +76,11 @@ v0.8 takes a CVSS v4.0 base score as input (3.1.1). The audit in `docs/audits/cv | PR | `N` unless the text says the attacker needs an account on the vulnerable system | | UI | `A` when the victim must knowingly install, enable or approve something the attacker supplied for the class to apply. `P` when the victim only uses the product normally (opens a repository, asks an ordinary question). `N` when no victim action is needed | | VC, VI, VA | The agent runtime and its host. `H` when the class lets the attacker cause the outcome in full without a further vulnerability, `L` when only partially or for a subset, `N` when the described mechanism does not | -| SC, SI, SA | Systems beyond the agent that the class itself propagates to (another agent, a downstream service, another tenant), as its description states. Reach through the agent's tools is scored once, in the Tools factor, and not again here (decision D2) | +| SC, SI, SA | `H` when the class's mechanism, as described, causes impact outside the vulnerable system's security domain at the reasonable worst case for the reference deployment profile (decision D17, part 4). Propagation that needs further steps beyond the class is not counted. Tool reach is counted once, in Tools (D2) | -The specification's wording on subsequent systems (3.1.1: assess them "based on the full scope of systems the compromised agent can reach through its tool access, delegation chains, and inter-agent communication paths") can be read literally, and then every class that steers an agent with default tools gets `SC:H/SI:H`, as in OWASP's 3.6.1. OWASP's other nine examples do not do that: they set subsequent impacts only where the scenario states propagation (cascade, orchestration, connected internal tools). The rule above follows the nine and is decision D2. +The AV, AC, AT, PR and UI rows are the pilot's working rules. Decision D17 part 2 (the reasonable worst case) may change them, and S03a settles them. + +The specification's wording on subsequent systems (3.1.1: assess them "based on the full scope of systems the compromised agent can reach through its tool access, delegation chains, and inter-agent communication paths") can be read literally, and then every class that steers an agent with default tools gets `SC:H/SI:H`, as in OWASP's 3.6.1. OWASP's other nine examples do not do that: they set subsequent impacts only where the scenario states propagation (cascade, orchestration, connected internal tools). FIRST's own guidance puts the line at the security domain: a vulnerability in a component serving "components in a different security domain" has Subsequent System impact, and one confined to a shared security scope does not (CVSS v4.0 User Guide, guidance on the Vulnerable System and Subsequent System). Decisions D2 and D17 set AVE's rule on that basis. The pilot's vectors were derived earlier, under "the class states propagation", and are not re-derived here; S03a re-derives them under D17. ## 5. The class-level assessment rule @@ -111,6 +113,8 @@ All ten use ThM 0.97 and Mitigation_Factor 1.0 (3.6, introduction). What they sh ### 5.3 The rule +*Decision D20 (not yet approved) would replace items 2 and 3 for the factors: the ten values would come from one of 5 to 8 reference deployment profiles and not be assigned per record. D1, as approved, keeps this section as written until D20 is decided.* + 1. **Reference deployment profile (RDP).** A class is assessed as deployed this way: one agent of the kind the record's `component_type` names (skill, mcp_server, agent), operated by one user, with the tools and permissions its ecosystem grants by default, with its ecosystem's default confirmation behaviour, and with no hardening beyond those defaults. A multi-agent deployment applies only to a class whose mechanism is multi-agent. Hardening is credited once, in Mitigation_Factor, and never inside the factors. 2. **Two kinds of factor.** *Mechanism factors* (Language, Context, Persistence, Identity, Multi-Agent, Self-Mod) are taken from what the class does, as its description and fingerprint state it, whatever the deployment. *Deployment factors* (Autonomy, Tools, Non-Determinism, Opacity) are taken from the RDP. Table 6 in section 6 says what each level means for each factor. 3. **Typical, not worst case.** Deployment factors take the value that is typical for the component type as shipped. Worst case is not used for three reasons. OWASP's own examples are not worst case. A worst-case rule would set the four deployment factors to 1.0 for nearly every class and remove the factors' power to tell a broad class from a narrow one. And "typical as shipped" can be checked by a second assessor, whereas "worst imaginable" cannot. @@ -271,11 +275,18 @@ I found no difference between the specification and #395's reading of it. The di ## 13. Decision list for the maintainer -Each item has a recommendation. None is applied until approved in writing. +Each item has a recommendation. None is applied until approved in writing. Status as of 2026-11-05: + +| Decision | Status | +|---|---| +| D1 to D11, D15, D16, D18 | Approved as recommended | +| D12 | Approved as recommended; stays conditional on TX4 | +| D13, D14, D17 | Approved as changed in the maintainer's message of 2026-11-05 (D2 is amended by D17 part 4) | +| D19, D20 | Added at the maintainer's direction; not yet approved in writing. D20 amends D1 | **D1. Reference profile rule.** Adopt section 5.3: the RDP, mechanism factors from the class, deployment factors typical as shipped, an anchor per class, a stated basis for every non-zero factor. Alternatives: worst case for deployment factors (sets four factors to 1.0 almost everywhere), or a profile per component type (more precise, more to maintain). *Recommend: the RDP as written.* -**D2. Subsequent-system impact, and reach counted once.** Score `SC/SI/SA` only for propagation the class itself states, and count tool reach once, in the Tools factor. The literal reading of 3.1.1 gives every steering class `SC:H/SI:H` and a base near 9.4. *Recommend: as written; it follows nine of OWASP's ten examples.* +**D2. Subsequent-system impact, and reach counted once.** Score `SC/SI/SA` only for propagation the class itself states, and count tool reach once, in the Tools factor. The literal reading of 3.1.1 gives every steering class `SC:H/SI:H` and a base near 9.4. *Recommend: as written; it follows nine of OWASP's ten examples.* *Amended by D17 part 4 (2026-11-05) for `SC`, `SI` and `SA`: the test is impact outside the vulnerable system's security domain at the reasonable worst case, not only propagation the description states. The half that counts tool reach once, in Tools, is unchanged.* **D3. ThM mapping.** Options: (a) assess each record's tier from its cited sources (recommended); (b) map by value as #399 plans (agrees with the evidence for 4 of the 10 pilot records, which are not a sample of the 89; of the five pilot records stored at 1.0 it calls all five Attacked, where the evidence supports that for one); (c) PoC for every record except cited in-the-wild exploitation. Option (a) needs primary sources, and 22 records still lack one (the quality queue). *Recommend (a), with PoC where the evidence tier cannot be told apart, and a rule that an in-the-wild claim must carry its citation.* @@ -300,12 +311,12 @@ Each item has a recommendation. None is applied until approved in writing. **D13. The AIVSS 1.0 candidate.** Facts found on 2026-11-04: - The publications listed on `aivss.owasp.org` are v0.5 and v0.8; its homepage calls v0.8 "the latest version". The same homepage links "the AIVSS 1.0 calculator" at `aivss.owasp.org/calculator/`, titled "OWASP AIVSS 1.0 ยท Reference Calculator". -- OWASP's open letter of 2025-12-08 said v1.0 would be published at RSA 2026; v0.8 was published on 2026-03-19 instead. +- OWASP's open letter of 2025-12-08 said v1.0 would be published at RSA 2026; v0.8 was published on 2026-03-19 instead. That announcement says v0.8 "sets the stage for the highly anticipated v1.0 release, slated for publication before the end of 2026", and opened a public review period on 2026-04-16. - The candidate's repository is `kenhuangus/aivss-v1-calculator` (created 2026-08-28, last push 2026-10-22, Apache-2.0). Its owner login, `kenhuangus`, matches the Substack that signs the project's open letter as "Ken Huang, Co-Lead, OWASP AIVSS Project" (the letter is linked from `aivss.owasp.org`), and v0.8 names Ken Huang on the AIVSS leadership team; I did not verify that the GitHub account is that person's. It holds code only; its commit history shows the specification copies were removed, so the 1.0 specification text was not available to compare with. - Its model differs from v0.8. There is no factor sum, ThM or Mitigation_Factor. Five categorical agentic metrics (LC, CP, AP, RH classify; ES informs an uplift) go in a separate `AIVSS:1.0/...` vector; the CVSS v4.0 score is kept unchanged (CVSS-BTE, so exploit maturity is in the CVSS vector); an Agentic Effect Class (A0, A1, A2, AX) is derived by a rule ladder; the AIVSS score is read from a lookup table keyed by the CVSS band and the class, and is never lower than CVSS-BTE. Its `legacy` command reproduces "withdrawn v0.x uplift scores" and says they must not be used for 1.0 compliance. - It says of itself: "The Table 6 cell values are policy settings that have not yet been validated against independently rated findings"; the remediation overlay "not empirically calibrated"; `first_validation_status: not-submitted`; "OWASP does not endorse AIVSS v1". -*Cost of a later move:* every class re-assessed on five new metrics; the ten factors, ThM and Mitigation_Factor leave the model; a new major schema (3.0.0). The CVSS v4.0 vector made authoritative here carries over; the factor judgments do not. *Recommend:* proceed with v0.8 as decided; keep method-specific values inside `aivss` and the CVSS vector outside it (as proposed), so a second method could be added beside the first; make `spec_version` a stated value and not a constant; and re-check the candidate's status before S03 starts, since S03 is where the cost is incurred. +*Cost of a later move:* every class re-assessed on five new metrics; the ten factors, ThM and Mitigation_Factor leave the model; a new major schema (3.0.0). The CVSS v4.0 vector made authoritative here carries over; the factor judgments do not. *Decided 2026-11-05:* proceed with v0.8; do the CVSS vectors first (S03a, D19), since they carry over to any later method; re-check OWASP's status at S03 start. Also kept from the proposal: method-specific values stay inside `aivss` and the CVSS vector outside it, so a second method could be added beside the first, and `spec_version` is a stated value and not a constant. **D14. The severity distribution.** The pilot and the estimates say the same thing: under v0.8 most classes are HIGH or CRITICAL, MEDIUM is reachable mainly by classes with a narrow effect and a lower base, and LOW is unlikely. @@ -321,20 +332,26 @@ Each item has a recommendation. None is applied until approved in writing. | Pilot, 10 records, before | 1 | 2 | 6 | 1 | | Pilot, 10 records, after | 6 | 1 | 3 | 0 | -The floors and ceilings use each record's stored Mitigation_Factor and ThM 0.97. The estimates run on non-conformant inputs (AVE's factors were not assigned against Table 2, Context and Opacity are unscored, and the stored bases are not the vector bases), so they are not a re-score. The pilot is ten records, six of them chosen by name, so it is not a sample and its frequencies must not be scaled up. What it supports: a class with a base of 9.0 or more and no mitigation credit is CRITICAL whatever the factors do (three of the four pilot records that never changed band under any alternative tried have such a base: AVE-2026-00001, 00044 and 00046; the fourth, 00066, has a base of 8.7 and a Factor_Sum of 5.0); bounded-effect classes can stay MEDIUM; and estimate C, applied to the pilot's ten, put 4 of the 10 in a different band from the pilot (6 agree). Re-derived pilot bases averaged 0.7 below both the stored bases (10 records) and the S00 vector bases (9 records), so the vector-based floor probably overstates. *Decision:* whether a distribution of this shape is acceptable to publish, and whether the README, the site and the implementer guide should say plainly that v0.8 raises most scores. *Recommend:* yes, and review the S03 vector re-derivation before the factor assignment, because it decides most of the outcome. +The floors and ceilings use each record's stored Mitigation_Factor and ThM 0.97. The estimates run on non-conformant inputs (AVE's factors were not assigned against Table 2, Context and Opacity are unscored, and the stored bases are not the vector bases), so they are not a re-score. The pilot is ten records, six of them chosen by name, so it is not a sample and its frequencies must not be scaled up. What it supports: a class with a base of 9.0 or more and no mitigation credit is CRITICAL whatever the factors do (three of the four pilot records that never changed band under any alternative tried have such a base: AVE-2026-00001, 00044 and 00046; the fourth, 00066, has a base of 8.7 and a Factor_Sum of 5.0); bounded-effect classes can stay MEDIUM; and estimate C, applied to the pilot's ten, put 4 of the 10 in a different band from the pilot (6 agree). Re-derived pilot bases averaged 0.7 below both the stored bases (10 records) and the S00 vector bases (9 records), so the vector-based floor probably overstates. *Decision:* whether a distribution of this shape is acceptable to publish, and whether the README, the site and the implementer guide should say plainly that v0.8 raises most scores. *Decided 2026-11-05:* yes, review the S03 vector re-derivation before the factor assignment (it decides most of the outcome), and show the CVSS-B band beside the AIVSS band in the registry and on the site. FIRST's rating scale (CVSS v4.0 specification, Table 22: None 0.0, Low 0.1 to 3.9, Medium 4.0 to 6.9, High 7.0 to 8.9, Critical 9.0 to 10.0) matches AIVSS's except for None, so the two bands can sit side by side. The CVSS-B band can be derived from `aivss.cvss_base` when it is displayed, so it needs no schema field; it is a display change in the registry and site repositories. With the vectors in the records today the CVSS-B band alone is 67 CRITICAL, 20 HIGH and 1 LOW (88 valid vectors). **D15. A second assessor near the band edges.** In the pilot, 6 of 10 records change band under at least one reasonable alternative choice (vector, ThM rule, mitigation, or a half-point on every factor). *Recommend:* a second independent assessment for any record whose score is within 0.5 of a band boundary, using the annotator-agreement kit once it exists. **D16. Update #399.** Its statements that `cvss_base` is kept as stored and that there is no catalog v1.3.0 no longer match the plan. *Recommend:* edit #399 or close it in favour of a corrected tracking issue. -**D17. CVSS vector policy.** The base is the floor of the v0.8 score (section 5.4), and the vectors in the records today put it high. Of the 88 valid vectors, 67 compute to a base of 9.0 or more and 87 to 7.0 or more (only AVE-2026-00058, at 2.3, is below 7.0; nine are exactly 10.0), and 63 set at least one subsequent-system metric to High (19 set all three). A class with a base of 9.0 and no mitigation credit is CRITICAL whatever its factors say, so the vectors, more than the factors, will decide the distribution. Proposed policy for the S03 re-derivation: +**D17. CVSS vector policy (S03a).** The base is the floor of the v0.8 score (section 5.4), and the vectors in the records today put it high. Of the 88 valid vectors, 67 compute to a base of 9.0 or more and 87 to 7.0 or more (only AVE-2026-00058, at 2.3, is below 7.0; nine are exactly 10.0). Counting a vector as having subsequent-system impact when at least one of `SC`, `SI` or `SA` is `H`, 82 of the 88 qualify (`SC` 72, `SI` 71, `SA` 20; at least two 62; all three 19; none 6). An earlier draft said 63; that was the vectors with one or two High, not at least one. A class with a base of 9.0 and no mitigation credit is CRITICAL whatever its factors say, so the vectors, more than the factors, decide the distribution. + +Policy, approved 2026-11-05 with part 4 as changed by the maintainer: -1. **Prefer the primary-source advisory vector.** Where a record cites an advisory, CVE or GHSA whose publisher gave a CVSS v4.0 vector for this mechanism, start from that vector and cite it. If the publisher gave only CVSS 3.1, do not convert it (3.1.1): derive the vector by section 4 and note the advisory's score as context. If the advisory is for the nearest instance and not the class, say so and change only what the class differs in. -2. **Score the vulnerable system's own impact.** `VC`, `VI` and `VA` are the effect on the agent runtime and its host that the class causes by itself. Downstream effects are not folded in. -3. **Subsequent-system High only when demonstrated.** `SC`, `SI` or `SA` is `H` only when a cited source demonstrates the propagation (an incident, an advisory, a paper that shows it). Propagation the description merely states is `L` at most, and absent propagation is `N`. This tightens D2, which scores stated propagation. Applied to the pilot it would change AVE-2026-00046, whose `SC/SI:H` rest on the description (with `L` the base is 8.6 and the score 9.2, still CRITICAL), and leave AVE-2026-00020 as it is (Cohen et al. 2024 demonstrates propagation between agents). -4. **A second assessor on ten records.** Before S03 starts, a second assessor, or a separate pass that has not seen the first vectors, derives vectors independently for the pilot's ten records, and the two sets are compared metric by metric. The comparison reports exact-vector agreement per metric, the difference in base score, and whether the band agrees. The pass thresholds are the maintainer's to set. Without a pass, the section 4 rules are not yet reproducible enough to apply to 89 records. +1. **CVSS-B only.** Base metrics only. Threat, Environmental and Supplemental metrics are not used; exploit maturity is ThM. +2. **Reasonable worst case, per FIRST.** The CVSS v4.0 specification says the Base Score "assumes the reasonable worst-case impact across different deployed environments". For a class, the environment is its reference deployment profile (section 5.3, D20). +3. **Name the systems.** Each vector's notes name the vulnerable system and any subsequent system, in words (for example, "the agent runtime and its host" and "the sub-agent that obeys the output"). +4. **Subsequent systems.** `SC`, `SI` or `SA` is `H` when the class's mechanism, as described, causes impact outside the vulnerable system's security domain at the reasonable worst case for the reference deployment profile (FIRST). A cited demonstration is preferred evidence but not required. Propagation that needs further steps beyond the class is not counted. Tool reach is counted once, in Tools (D2). The profile is the same one that sets the factors. +5. **No double counting.** An effect is counted once: tool reach in Tools, exploit maturity in ThM, hardening in Mitigation_Factor, and an impact in the vector or in a factor but not in both. +6. **An advisory vector as a start where one exists.** The maintainer's estimate is about 6 records. This audit found 12 records that cite a CVE, GHSA or advisory (AVE-2026-00029, 00044, 00052, 00053, 00054, 00055, 00056, 00063, 00064, 00073, 00088 and 00089). Of these, 00044's is an incident write-up, 00052 and 00053 are proposed for rejection and 00054 is deferred. This audit did not check which publishers give a CVSS v4.0 vector, and only the references of 00088 and 00089 quote one. If an advisory has only CVSS 3.1, do not convert it (3.1.1). If it is for the nearest instance and not the class, say so and change only what the class differs in. +7. **Two implementations.** The Red Hat `cvss` library and FIRST's calculator source, pinned, with a test that fails if they disagree on any record. +8. **A second assessor on ten records.** Before S03a's vectors are applied, a second assessor, or a separate pass that has not seen the first vectors, derives vectors independently for the pilot's ten records, and the two sets are compared metric by metric: exact-vector agreement per metric, the difference in base score, and whether the CVSS-B band agrees. The pass thresholds are the maintainer's to set. The pilot's own sensitivity is the evidence: 6 of 10 records change band under one alternative choice, and the vector is the choice that moves the most (4 of the 9 records with a valid stored vector). -*Recommend: adopt 1 to 4.* The pilot's own sensitivity is the evidence for 4: 6 of 10 records change band under one alternative choice, and the vector is the choice that moves the most (4 of the 9 records with a valid stored vector). +The pilot's vectors predate this policy (parts 2 and 4 in particular) and are not re-derived here; S03a re-derives them. **D18. When to open the 30-day public comment period.** `CONTRIBUTING.md` ("Schema changes") says a major schema version "needs a migration path for existing records and a 30-day comment period before merging". It names no start event, no venue and no content. Schema 2.0.0 is a major version: it changes the meaning of `aars` and `thm`, removes two `aarf` keys and renames five. The release step S05 gates on the period having closed. @@ -354,3 +371,24 @@ Points the maintainer should settle: - **Where it is announced.** The thread should be somewhere downstream tools and consumers of the dist files can subscribe to. Which channels is the maintainer's call, and nothing is announced outside the repository without approval. - **What "merging" means.** The wording is "before merging". Read here as the merge that publishes schema 2.0.0 (S05), not the merges into a `release/2.0` branch. If the maintainer reads it as the first merge of 2.0.0 files into `develop`, the period has to be complete before S02. +**D19. Split S03 into S03a and S03b.** *Added at the maintainer's direction; not yet approved in writing.* + +- **S03a: the CVSS vectors**, for all 89 records, under D17. They are reusable: the OWASP 1.0 candidate keeps the official CVSS v4.0 vector and score intact (its README), so the vectors carry over to a later AIVSS method as well as serving v0.8 now. +- **S03b: the AIVSS inputs** under v0.8 (the profile, the ThM tier, the mitigation level and, under D20, the factor values), only after a checkpoint on OWASP's status. The checkpoint re-reads `aivss.owasp.org`, its publications list and the candidate repository. It is made at S03 start (D13) and again before S03b begins, because S03a does not depend on the answer and the answer may change while it runs. OWASP's announcement of 2026-03-19 says v1.0 is "slated for publication before the end of 2026". If v1.0 has been published by then, S03b waits for a maintainer decision (D13 gives the cost); if not, S03b proceeds on v0.8. +- **Where S03a's output lives (proposed).** S00 warned that changing `cvss_base` before 2.0.0 would silently rescore the 1.x scores. So S03a delivers a reviewed table of vectors, with the systems named (D17), and applies it to the records only on the 2.0.0 branch with the rest of the migration, not on `develop`. +- **Gate.** S02 does not start until this pull request has merged and the public comment period (D18) has opened. + +**D20. 5 to 8 reference deployment profiles instead of per-record factors.** *Added at the maintainer's direction; not yet approved in writing. It amends D1, which is approved.* + +- **What.** Define 5 to 8 reference deployment profiles. Each fixes the ten factor values and is the environment for the reasonable worst case in D17. Each record names its profile. The per-record judgements shrink to the CVSS vector (S03a), the ThM tier, the mitigation level and the profile, each with a stated basis: 89 x 10 factor judgements become about 8 x 10. A record that fits no profile is a signal to revise the profiles, not to override one. +- **Tension with D1.** D1, as approved, takes the four deployment factors from the profile and the six mechanism factors from the class. The pilot needed that, because mechanism factors differ by class (Language is 0 for AVE-2026-00024 and 00063 and 1.0 for 00001; Persistence is 1.0 only for 00019). If D20 replaces D1's per-class mechanism factors, those differences have to live in the profiles (profiles defined by deployment and mechanism family together) or they are lost. The pilot's ten records had 6 distinct nearest Core Risks; OWASP has 10. +- **Measured.** With the vectors in the records today, a profile's Factor_Sum moves the distribution little: + +| Profile Factor_Sum | CRITICAL | HIGH | MEDIUM | LOW | +|---|---|---|---|---| +| 3.0 | 50 | 35 | 2 | 1 | +| 5.0 | 50 | 37 | 1 | 0 | +| 8.0 | 54 | 33 | 1 | 0 | + + (88 valid vectors, ThM 0.97, each record's stored mitigation.) That is because 67 of the 88 bases already put the CVSS-B band at CRITICAL. After S03a the bases will move (the pilot's re-derived bases averaged 0.7 lower), and the profiles' sums will then matter more, so the profile set should be designed after S03a and not before. That is a further reason for D19. +- **Recommend:** adopt, with the profiles designed after S03a from the re-derived vectors; each profile states its ten values with a one-line basis for every non-zero factor, as the pilot does, and a named anchor; no per-record override. Open questions: how profiles are named and versioned, and who may add one. A change to a profile can change the severity of every record that names it, and each such change needs its own `revisions` entry under hard rule 11. From 757c863d79f719315c1d425cb9602442e36be411 Mon Sep 17 00:00:00 2001 From: chaksaray Date: Thu, 5 Nov 2026 06:42:46 +0700 Subject: [PATCH 4/5] docs: approve D19, withdraw D20 for a D1 table, add D21 and the confirmed advisory seeds (#446) D19 (S03a vectors, S03b AIVSS inputs) approved by the maintainer. D20 withdrawn as written and replaced by an amendment to D1: section 6.1 publishes the four deployment-factor values per component type (skill, mcp_server, agent); drafted values, applied to the pilot they change no band. Adds D21 (tier S03b by band sensitivity: 47 light and 41 full on today's vectors). D17 part 6 now lists six advisories for five records as S03a seeds, each confirmed against the GitHub Advisory Database entry and recomputed with both implementations. Signed-off-by: chaksaray --- docs/specs/aivss-v0.8-conformance.md | 74 ++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/docs/specs/aivss-v0.8-conformance.md b/docs/specs/aivss-v0.8-conformance.md index bb3ed77..f6da091 100644 --- a/docs/specs/aivss-v0.8-conformance.md +++ b/docs/specs/aivss-v0.8-conformance.md @@ -1,8 +1,8 @@ # AIVSS v0.8 conformance statement for AVE -**Status (2026-11-05): decisions D1 to D12, D15, D16 and D18 are approved by the maintainer (D12 stays conditional on TX4); D13, D14 and D17 are approved as changed in the same message; D19 and D20 were added at the maintainer's direction and are not yet approved in writing (section 13).** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, validator or `dist/` file changes. The one code addition is a standalone arithmetic module, `scripts/aivss_v08.py`, with its tests in `tests/test_aivss_v08.py`; nothing imports it. Nothing here becomes AVE's rule except what section 13 marks approved, and nothing is applied to a record before S02, which waits for this pull request to merge and the public comment period (D18) to open. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. +**Status (2026-11-05): decisions D1 to D12, D15, D16, D18 and D19 are approved by the maintainer (D12 stays conditional on TX4); D13, D14 and D17 are approved as changed; D20 is withdrawn and replaced by an amendment to D1, the table in section 6.1; D21 was added at the maintainer's direction and is not yet approved in writing (section 13).** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, validator or `dist/` file changes. The one code addition is a standalone arithmetic module, `scripts/aivss_v08.py`, with its tests in `tests/test_aivss_v08.py`; nothing imports it. Nothing here becomes AVE's rule except what section 13 marks approved, and nothing is applied to a record before S02, which waits for this pull request to merge and the public comment period (D18) to open. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. -**Date:** 2026-11-04, reread and extended 2026-11-05 (the arithmetic module and its tests, the approvals, D17 to D20). **Repository state:** `develop` at `0753b2d`. +**Date:** 2026-11-04, reread and extended 2026-11-05 (the arithmetic module and its tests, the approvals, D17 to D21). **Repository state:** `develop` at `0753b2d`. ## 1. What this statement is for @@ -113,7 +113,7 @@ All ten use ThM 0.97 and Mitigation_Factor 1.0 (3.6, introduction). What they sh ### 5.3 The rule -*Decision D20 (not yet approved) would replace items 2 and 3 for the factors: the ten values would come from one of 5 to 8 reference deployment profiles and not be assigned per record. D1, as approved, keeps this section as written until D20 is decided.* +*Amended 2026-11-05 (D1): the four deployment factors take the values in the table in section 6.1, one column per component type. Items 2 and 3 describe what that table is for.* 1. **Reference deployment profile (RDP).** A class is assessed as deployed this way: one agent of the kind the record's `component_type` names (skill, mcp_server, agent), operated by one user, with the tools and permissions its ecosystem grants by default, with its ecosystem's default confirmation behaviour, and with no hardening beyond those defaults. A multi-agent deployment applies only to a class whose mechanism is multi-agent. Hardening is credited once, in Mitigation_Factor, and never inside the factors. 2. **Two kinds of factor.** *Mechanism factors* (Language, Context, Persistence, Identity, Multi-Agent, Self-Mod) are taken from what the class does, as its description and fingerprint state it, whatever the deployment. *Deployment factors* (Autonomy, Tools, Non-Determinism, Opacity) are taken from the RDP. Table 6 in section 6 says what each level means for each factor. @@ -156,6 +156,28 @@ Adapted from Table 2. "Mechanism" factors come from the class; "deployment" fact Three clarifications were made while piloting, and the pilot lists where they applied: Persistence (1.0 only for the agent's own state, consistent with OWASP's 3.6.2 against 3.6.8), Context (the rule PR #401 also used), and Self-Mod for a single injected instruction (0.5, as in 3.6.1; 1.0 only for repeated goal conditioning, as in 3.6.10). +### 6.1 Deployment-factor values per component type (amendment to D1) + +D1 takes the four deployment factors (Autonomy, Tools, Non-Determinism, Opacity) from the reference deployment and not from the class. They are published here, one column per `component_type`, so that every record of a type starts from the same four numbers and a second assessor checks them against one table. They are "typical as shipped" (section 5.3). **The values are drafted here from the Table 2 rubric and the pilot, and take effect when the maintainer confirms them.** + +| Factor | skill | mcp_server | agent | +|---|---|---|---| +| Autonomy | 1.0 | 0.5 | 1.0 | +| Tools | 1.0 | 0.5 | 1.0 | +| Non-Determinism | 1.0 | 0.0 | 1.0 | +| Opacity | 0.5 | 0.5 | 1.0 | + +Basis, from Table 2: + +- **Autonomy.** skill 1.0: the host agent executes the skill's instructions and tools without a per-step human co-sign once the skill is enabled. mcp_server 0.5: the client normally asks before a tool call or a server's first use, a confirmation users routinely accept. agent 1.0: it acts on its own plan (nine of OWASP's ten examples score 1.0). +- **Tools.** skill 1.0: a skill reaches the host agent's tools (shell, filesystem, network). mcp_server 0.5: it exposes its own tool set, mixed read and write and scoped to the server. agent 1.0: broad, high-authority tools. +- **Non-Determinism.** skill 1.0 and agent 1.0: an LLM interprets the instructions or plans with no hard guardrail. mcp_server 0.0: server code is deterministic, and the variance sits in the client that calls it. +- **Opacity.** skill 0.5 and mcp_server 0.5: the artifact (instruction text, schema, code) is readable and reviewable, but why the agent acted is a black box. agent 1.0: the agent's decision logic is not externally auditable (all ten OWASP examples score Opacity 1.0). + +Not covered: 8 records have no column, because 6 have no `component_type`, one is `tool` and one is `other`. S03b assigns each a type (the field exists and is optional) or the maintainer adds a column; that is not decided here. + +Effect on the pilot: replacing the four factors by the table's values, with the pilot's six mechanism factors kept, changes no band of the ten records. Scores move by -0.1 to +0.3 and Factor_Sum by -1.5 to +1.5. Limits: the pilot has 9 skills, 1 `mcp_server` and no `agent`, so the `agent` column is tested by nothing and the `mcp_server` column by one record, and no value was checked against any product's default behaviour. A table loses some class difference: the pilot scored Non-Determinism 0 for AVE-2026-00063, a deterministic configuration flag, and the table gives a skill 1.0. That is the price of fixing the deployment factors per type. + AVE's current factors map as follows (they were assigned against AVE's own definitions, not Table 2): `autonomy`, `non_determinism` and `multi_agent` keep their names; `tool_use` is Tools; `natural_language_input` is Language; `persistent_memory` is Persistence; `dynamic_identity` is Identity; `self_modification` is Self-Mod; `data_access` and `external_dependencies` have no counterpart; Context and Opacity are new. Carrying the eight over by value would carry definitions that differ from Table 2 (this is why the S01 plan says not to). ## 7. The threat multiplier @@ -280,11 +302,14 @@ Each item has a recommendation. None is applied until approved in writing. Statu | Decision | Status | |---|---| | D1 to D11, D15, D16, D18 | Approved as recommended | +| D1 (amendment) | The deployment-factor values per component type are published as a table (section 6.1), in place of D20. The table's values are drafted and take effect when the maintainer confirms them | | D12 | Approved as recommended; stays conditional on TX4 | | D13, D14, D17 | Approved as changed in the maintainer's message of 2026-11-05 (D2 is amended by D17 part 4) | -| D19, D20 | Added at the maintainer's direction; not yet approved in writing. D20 amends D1 | +| D19 | Approved (maintainer, 2026-11-05) | +| D20 | Withdrawn as written; replaced by the D1 amendment | +| D21 | Added at the maintainer's direction; not yet approved in writing | -**D1. Reference profile rule.** Adopt section 5.3: the RDP, mechanism factors from the class, deployment factors typical as shipped, an anchor per class, a stated basis for every non-zero factor. Alternatives: worst case for deployment factors (sets four factors to 1.0 almost everywhere), or a profile per component type (more precise, more to maintain). *Recommend: the RDP as written.* +**D1. Reference profile rule.** Adopt section 5.3: the RDP, mechanism factors from the class, deployment factors typical as shipped, an anchor per class, a stated basis for every non-zero factor. Alternatives: worst case for deployment factors (sets four factors to 1.0 almost everywhere), or a profile per component type (more precise, more to maintain). *Recommend: the RDP as written.* *Amended 2026-11-05 by the maintainer: the deployment-factor values per component type are published as a table (section 6.1) in place of a new decision. The table's values are drafted and take effect when the maintainer confirms them.* **D2. Subsequent-system impact, and reach counted once.** Score `SC/SI/SA` only for propagation the class itself states, and count tool reach once, in the Tools factor. The literal reading of 3.1.1 gives every steering class `SC:H/SI:H` and a base near 9.4. *Recommend: as written; it follows nine of OWASP's ten examples.* *Amended by D17 part 4 (2026-11-05) for `SC`, `SI` and `SA`: the test is impact outside the vulnerable system's security domain at the reasonable worst case, not only propagation the description states. The half that counts tool reach once, in Tools, is unchanged.* @@ -343,11 +368,22 @@ The floors and ceilings use each record's stored Mitigation_Factor and ThM 0.97. Policy, approved 2026-11-05 with part 4 as changed by the maintainer: 1. **CVSS-B only.** Base metrics only. Threat, Environmental and Supplemental metrics are not used; exploit maturity is ThM. -2. **Reasonable worst case, per FIRST.** The CVSS v4.0 specification says the Base Score "assumes the reasonable worst-case impact across different deployed environments". For a class, the environment is its reference deployment profile (section 5.3, D20). +2. **Reasonable worst case, per FIRST.** The CVSS v4.0 specification says the Base Score "assumes the reasonable worst-case impact across different deployed environments". For a class, the environment is its reference deployment profile (section 5.3). 3. **Name the systems.** Each vector's notes name the vulnerable system and any subsequent system, in words (for example, "the agent runtime and its host" and "the sub-agent that obeys the output"). -4. **Subsequent systems.** `SC`, `SI` or `SA` is `H` when the class's mechanism, as described, causes impact outside the vulnerable system's security domain at the reasonable worst case for the reference deployment profile (FIRST). A cited demonstration is preferred evidence but not required. Propagation that needs further steps beyond the class is not counted. Tool reach is counted once, in Tools (D2). The profile is the same one that sets the factors. +4. **Subsequent systems.** `SC`, `SI` or `SA` is `H` when the class's mechanism, as described, causes impact outside the vulnerable system's security domain at the reasonable worst case for the reference deployment profile (FIRST). A cited demonstration is preferred evidence but not required. Propagation that needs further steps beyond the class is not counted. Tool reach is counted once, in Tools (D2). The profile is the same one that sets the deployment factors (section 6.1). 5. **No double counting.** An effect is counted once: tool reach in Tools, exploit maturity in ThM, hardening in Mitigation_Factor, and an impact in the vector or in a factor but not in both. -6. **An advisory vector as a start where one exists.** The maintainer's estimate is about 6 records. This audit found 12 records that cite a CVE, GHSA or advisory (AVE-2026-00029, 00044, 00052, 00053, 00054, 00055, 00056, 00063, 00064, 00073, 00088 and 00089). Of these, 00044's is an incident write-up, 00052 and 00053 are proposed for rejection and 00054 is deferred. This audit did not check which publishers give a CVSS v4.0 vector, and only the references of 00088 and 00089 quote one. If an advisory has only CVSS 3.1, do not convert it (3.1.1). If it is for the nearest instance and not the class, say so and change only what the class differs in. +6. **An advisory vector as a start where one exists.** Seeds for S03a, each confirmed on 2026-11-05 against its entry in the GitHub Advisory Database (all `reviewed`), which carries the publisher's CVSS v4.0 vector, and each recomputed with both implementations (all agree with the stated score): + +| Record | Advisory | CVE | Product | Vector | Score | +|---|---|---|---|---|---| +| AVE-2026-00064 | GHSA-4fgq-fpq9-mr3g | CVE-2025-59536 | Claude Code | `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N` | 8.7 | +| AVE-2026-00063 | GHSA-mmgp-wc2j-qcv7 | CVE-2026-33068 | Claude Code | `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N` | 7.7 | +| AVE-2026-00088 | GHSA-ff64-7w26-62rf | CVE-2026-25725 | Claude Code | `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N` | 7.7 | +| AVE-2026-00089 | GHSA-w5fx-fh39-j5rw | CVE-2025-59532 | Codex | `CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N` | 8.6 | +| AVE-2026-00089 | GHSA-w828-4qhx-vxx3 | CVE-2026-34452 | Anthropic SDK for Python | `CVSS:4.0/AV:L/AC:H/AT:N/PR:L/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N` | 5.8 | +| AVE-2026-00073 | GHSA-jh7p-qr78-84p7 | CVE-2026-21852 | Claude Code | `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N` | 5.3 | + + That is five records and six advisories; the maintainer's estimate was about 6 records. Each vector is for the nearest instance in a named product and not for the class, so S03a starts from it, changes only what the class differs in, and says so. The only seeded record in the pilot is AVE-2026-00063: its pilot vector (7.2) differs from the advisory's (7.7) in `AT` (`N` against `P`) and in `VC` and `VA` (`L` against `H`). The advisory GHSA-w828-4qhx-vxx3 also carries a CVSS 3.1 score (5.3), which is not used (3.1.1). None of the six publishers scores any subsequent-system impact, while 82 of the 88 vectors in the records have at least one High (part 4 decides which is right for a class). Records 00064, 00088 and 00089 cite further advisories that are not seeded here. The other records that cite a CVE, GHSA or advisory are 00029, 00044 (an incident write-up), 00052 and 00053 (proposed for rejection), 00054 (deferred), 00055 and 00056; no CVSS v4.0 vector was checked for them. If an advisory has only CVSS 3.1, do not convert it (3.1.1). 7. **Two implementations.** The Red Hat `cvss` library and FIRST's calculator source, pinned, with a test that fails if they disagree on any record. 8. **A second assessor on ten records.** Before S03a's vectors are applied, a second assessor, or a separate pass that has not seen the first vectors, derives vectors independently for the pilot's ten records, and the two sets are compared metric by metric: exact-vector agreement per metric, the difference in base score, and whether the CVSS-B band agrees. The pass thresholds are the maintainer's to set. The pilot's own sensitivity is the evidence: 6 of 10 records change band under one alternative choice, and the vector is the choice that moves the most (4 of the 9 records with a valid stored vector). @@ -371,24 +407,20 @@ Points the maintainer should settle: - **Where it is announced.** The thread should be somewhere downstream tools and consumers of the dist files can subscribe to. Which channels is the maintainer's call, and nothing is announced outside the repository without approval. - **What "merging" means.** The wording is "before merging". Read here as the merge that publishes schema 2.0.0 (S05), not the merges into a `release/2.0` branch. If the maintainer reads it as the first merge of 2.0.0 files into `develop`, the period has to be complete before S02. -**D19. Split S03 into S03a and S03b.** *Added at the maintainer's direction; not yet approved in writing.* +**D19. Split S03 into S03a and S03b.** *Approved 2026-11-05.* - **S03a: the CVSS vectors**, for all 89 records, under D17. They are reusable: the OWASP 1.0 candidate keeps the official CVSS v4.0 vector and score intact (its README), so the vectors carry over to a later AIVSS method as well as serving v0.8 now. -- **S03b: the AIVSS inputs** under v0.8 (the profile, the ThM tier, the mitigation level and, under D20, the factor values), only after a checkpoint on OWASP's status. The checkpoint re-reads `aivss.owasp.org`, its publications list and the candidate repository. It is made at S03 start (D13) and again before S03b begins, because S03a does not depend on the answer and the answer may change while it runs. OWASP's announcement of 2026-03-19 says v1.0 is "slated for publication before the end of 2026". If v1.0 has been published by then, S03b waits for a maintainer decision (D13 gives the cost); if not, S03b proceeds on v0.8. +- **S03b: the AIVSS inputs** under v0.8 (the four deployment factors for the record's component type from the table in section 6.1, the six mechanism factors, the ThM tier and the mitigation level, tiered by D21), only after a checkpoint on OWASP's status. The checkpoint re-reads `aivss.owasp.org`, its publications list and the candidate repository. It is made at S03 start (D13) and again before S03b begins, because S03a does not depend on the answer and the answer may change while it runs. OWASP's announcement of 2026-03-19 says v1.0 is "slated for publication before the end of 2026". If v1.0 has been published by then, S03b waits for a maintainer decision (D13 gives the cost); if not, S03b proceeds on v0.8. - **Where S03a's output lives (proposed).** S00 warned that changing `cvss_base` before 2.0.0 would silently rescore the 1.x scores. So S03a delivers a reviewed table of vectors, with the systems named (D17), and applies it to the records only on the 2.0.0 branch with the rest of the migration, not on `develop`. - **Gate.** S02 does not start until this pull request has merged and the public comment period (D18) has opened. -**D20. 5 to 8 reference deployment profiles instead of per-record factors.** *Added at the maintainer's direction; not yet approved in writing. It amends D1, which is approved.* +**D20. Withdrawn 2026-11-05.** The maintainer withdrew it as written (5 to 8 reference deployment profiles instead of per-record factors) and amended D1 instead, with the table of deployment-factor values per component type in section 6.1. No new decision. One finding is kept because it supports D19 and D21: with the vectors in the records today, the factor sum moves the distribution little (50 CRITICAL, 35 HIGH, 2 MEDIUM, 1 LOW at a Factor_Sum of 3.0, and 54, 33, 1, 0 at 8.0; 88 valid vectors, ThM 0.97, stored mitigation), because 67 of the 88 bases already put the CVSS-B band at CRITICAL. -- **What.** Define 5 to 8 reference deployment profiles. Each fixes the ten factor values and is the environment for the reasonable worst case in D17. Each record names its profile. The per-record judgements shrink to the CVSS vector (S03a), the ThM tier, the mitigation level and the profile, each with a stated basis: 89 x 10 factor judgements become about 8 x 10. A record that fits no profile is a signal to revise the profiles, not to override one. -- **Tension with D1.** D1, as approved, takes the four deployment factors from the profile and the six mechanism factors from the class. The pilot needed that, because mechanism factors differ by class (Language is 0 for AVE-2026-00024 and 00063 and 1.0 for 00001; Persistence is 1.0 only for 00019). If D20 replaces D1's per-class mechanism factors, those differences have to live in the profiles (profiles defined by deployment and mechanism family together) or they are lost. The pilot's ten records had 6 distinct nearest Core Risks; OWASP has 10. -- **Measured.** With the vectors in the records today, a profile's Factor_Sum moves the distribution little: +**D21. Tier S03b by band sensitivity.** *Added at the maintainer's direction; not yet approved in writing.* After S03a, compute each record's band at zero and at maximum uplift: -| Profile Factor_Sum | CRITICAL | HIGH | MEDIUM | LOW | -|---|---|---|---|---| -| 3.0 | 50 | 35 | 2 | 1 | -| 5.0 | 50 | 37 | 1 | 0 | -| 8.0 | 54 | 33 | 1 | 0 | +- **Floor:** its S03a vector base times its Mitigation_Factor (stored, or assessed once S03b assesses it), at Factor_Sum 0. +- **Ceiling:** Factor_Sum 10 with the top of its ThM range (Attacked 1.00, unless its sources rule that tier out), times the same Mitigation_Factor. At ThM 1.00 the ceiling is 10 times the Mitigation_Factor: 10.0 with no mitigation credit, 8.3 with Partial, 6.7 with Strong. +- **Light tier:** the band cannot change (floor and ceiling are in the same band) and neither end is within 0.5 of a band boundary. The record gets the six mechanism factors with a one-line basis each, on top of the four values from the table in section 6.1. +- **Full tier:** the band can change, or the floor is less than 0.5 above the lower boundary of its band, or the ceiling is less than 0.5 below the next boundary up. The record gets the full assessment as in the pilot (every factor with a basis, the uncertain calls scored) and second-assessor review. - (88 valid vectors, ThM 0.97, each record's stored mitigation.) That is because 67 of the 88 bases already put the CVSS-B band at CRITICAL. After S03a the bases will move (the pilot's re-derived bases averaged 0.7 lower), and the profiles' sums will then matter more, so the profile set should be designed after S03a and not before. That is a further reason for D19. -- **Recommend:** adopt, with the profiles designed after S03a from the re-derived vectors; each profile states its ten values with a one-line basis for every non-zero factor, as the pilot does, and a named anchor; no per-record override. Open questions: how profiles are named and versioned, and who may add one. A change to a profile can change the severity of every record that names it, and each such change needs its own `revisions` entry under hard rule 11. +Indicative sizes on today's vectors, which S03a will change: of the 88 valid vectors, 47 are light and 41 are full (14 band-sensitive and 27 band-insensitive but within 0.5 of a boundary), and AVE-2026-00066 has no valid vector yet. The numbers will move, because re-derived bases were 0.7 lower on average in the pilot and lower bases make more records band-sensitive. With no mitigation credit a record is band-insensitive only if its floor is CRITICAL (a base of 9.0 or more); with Partial credit (ceiling 8.3), only if its floor is HIGH (a base of about 8.4 or more). The six mechanism factors are still assessed for the light tier because AARS and the score are stored and exported. *Recommend: adopt.* From 2cc0ce8a33f69cfc5ba12721a7d838a5a2f5da40 Mon Sep 17 00:00:00 2001 From: chaksaray Date: Thu, 5 Nov 2026 06:53:50 +0700 Subject: [PATCH 5/5] docs: approve D21 with a band-sensitive-only full tier, revise table 6.1 (#446) D21 approved by the maintainer with one change: the full tier is band-sensitive records only; band-insensitive records near a band edge get an independent check of their vector and mitigation (D15, D17 part 8), not a full factor assessment. Table 6.1 revised by the maintainer: Non-Determinism and Opacity 1.0 in all three columns (OWASP scores Opacity 1.0 in all ten examples and Non-Determinism 0 in none), marked initial and adjustable during S03b. Applied to the pilot the revised table moves AVE-2026-00063 from 6.7 MEDIUM to 7.0 HIGH. The eight records without a column are assigned to the nearest type in S03b with a stated reason, no new columns. Signed-off-by: chaksaray --- docs/specs/aivss-v0.8-conformance.md | 37 +++++++++++++++------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/docs/specs/aivss-v0.8-conformance.md b/docs/specs/aivss-v0.8-conformance.md index f6da091..8d088f2 100644 --- a/docs/specs/aivss-v0.8-conformance.md +++ b/docs/specs/aivss-v0.8-conformance.md @@ -1,6 +1,6 @@ # AIVSS v0.8 conformance statement for AVE -**Status (2026-11-05): decisions D1 to D12, D15, D16, D18 and D19 are approved by the maintainer (D12 stays conditional on TX4); D13, D14 and D17 are approved as changed; D20 is withdrawn and replaced by an amendment to D1, the table in section 6.1; D21 was added at the maintainer's direction and is not yet approved in writing (section 13).** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, validator or `dist/` file changes. The one code addition is a standalone arithmetic module, `scripts/aivss_v08.py`, with its tests in `tests/test_aivss_v08.py`; nothing imports it. Nothing here becomes AVE's rule except what section 13 marks approved, and nothing is applied to a record before S02, which waits for this pull request to merge and the public comment period (D18) to open. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. +**Status (2026-11-05): decisions D1 to D12, D15, D16, D18 and D19 are approved by the maintainer (D12 stays conditional on TX4); D13, D14, D17 and D21 are approved as changed; D20 is withdrawn and replaced by an amendment to D1, the table in section 6.1, whose values are initial and adjustable during S03b (section 13).** Step S01 of the plan to conform AVE scoring to OWASP AIVSS v0.8 (#399, issue #446). It is report only: no record, schema file, validator or `dist/` file changes. The one code addition is a standalone arithmetic module, `scripts/aivss_v08.py`, with its tests in `tests/test_aivss_v08.py`; nothing imports it. Nothing here becomes AVE's rule except what section 13 marks approved, and nothing is applied to a record before S02, which waits for this pull request to merge and the public comment period (D18) to open. The pilot that tests this statement is `docs/audits/aivss-v0.8-pilot.md`, with its data in `docs/audits/aivss-v0.8-pilot.json`. **Date:** 2026-11-04, reread and extended 2026-11-05 (the arithmetic module and its tests, the approvals, D17 to D21). **Repository state:** `develop` at `0753b2d`. @@ -117,7 +117,7 @@ All ten use ThM 0.97 and Mitigation_Factor 1.0 (3.6, introduction). What they sh 1. **Reference deployment profile (RDP).** A class is assessed as deployed this way: one agent of the kind the record's `component_type` names (skill, mcp_server, agent), operated by one user, with the tools and permissions its ecosystem grants by default, with its ecosystem's default confirmation behaviour, and with no hardening beyond those defaults. A multi-agent deployment applies only to a class whose mechanism is multi-agent. Hardening is credited once, in Mitigation_Factor, and never inside the factors. 2. **Two kinds of factor.** *Mechanism factors* (Language, Context, Persistence, Identity, Multi-Agent, Self-Mod) are taken from what the class does, as its description and fingerprint state it, whatever the deployment. *Deployment factors* (Autonomy, Tools, Non-Determinism, Opacity) are taken from the RDP. Table 6 in section 6 says what each level means for each factor. -3. **Typical, not worst case.** Deployment factors take the value that is typical for the component type as shipped. Worst case is not used for three reasons. OWASP's own examples are not worst case. A worst-case rule would set the four deployment factors to 1.0 for nearly every class and remove the factors' power to tell a broad class from a narrow one. And "typical as shipped" can be checked by a second assessor, whereas "worst imaginable" cannot. +3. **Typical, not worst case.** Deployment factors take the value that is typical for the component type as shipped. Worst case is not used for three reasons. OWASP's own examples are not worst case. A worst-case rule would set the four deployment factors to 1.0 for nearly every class and remove the factors' power to tell a broad class from a narrow one. And "typical as shipped" can be checked by a second assessor, whereas "worst imaginable" cannot. The section 6.1 table follows this for Autonomy and Tools, which differ by component type, but sets Non-Determinism and Opacity at 1.0 in every column, because each column describes the LLM-driven agent that uses the component and OWASP scores Opacity 1.0 in all ten of its examples (amended 2026-11-05). 4. **Calibration anchors.** Each class is compared with the nearest Core Risk in 3.6 (Table 3 lists each Core Risk's high-impact factors). Copy that example's factor vector, then change a factor only for a reason written from the class's description or sources. The anchor is recorded (section 10, `core_risk`; Appendix A requires an `owasp_category`). Where no Core Risk fits well, say so. In the pilot the anchor was weak for AVE-2026-00039 and 00058. 5. **Evidence is stated for every non-zero factor**: one line, citing the record's description, fingerprint or a reference. A factor with no stated basis is 0.0 (no inflation without a reason, the same discipline as the existing "do not inflate" rule in `references/aivss-scoring.md`). 6. **Do not force a band.** The honest computed result is reported. Where it feels wrong, the notes say so, and the inputs are not adjusted. @@ -158,25 +158,27 @@ Three clarifications were made while piloting, and the pilot lists where they ap ### 6.1 Deployment-factor values per component type (amendment to D1) -D1 takes the four deployment factors (Autonomy, Tools, Non-Determinism, Opacity) from the reference deployment and not from the class. They are published here, one column per `component_type`, so that every record of a type starts from the same four numbers and a second assessor checks them against one table. They are "typical as shipped" (section 5.3). **The values are drafted here from the Table 2 rubric and the pilot, and take effect when the maintainer confirms them.** +D1 takes the four deployment factors (Autonomy, Tools, Non-Determinism, Opacity) from the reference deployment and not from the class. They are published here, one column per `component_type`, so that every record of a type starts from the same four numbers and a second assessor checks them against one table. Each column describes the agent that uses the component, as D1's reference profile does. **These are initial values. The maintainer reviewed and revised them on 2026-11-05, and they are adjustable during S03b.** An adjustment is recorded with its reason and its effect on the bands, because it moves every record of that component type. | Factor | skill | mcp_server | agent | |---|---|---|---| | Autonomy | 1.0 | 0.5 | 1.0 | | Tools | 1.0 | 0.5 | 1.0 | -| Non-Determinism | 1.0 | 0.0 | 1.0 | -| Opacity | 0.5 | 0.5 | 1.0 | +| Non-Determinism | 1.0 | 1.0 | 1.0 | +| Opacity | 1.0 | 1.0 | 1.0 | -Basis, from Table 2: +Basis, from Table 2 and OWASP's examples: - **Autonomy.** skill 1.0: the host agent executes the skill's instructions and tools without a per-step human co-sign once the skill is enabled. mcp_server 0.5: the client normally asks before a tool call or a server's first use, a confirmation users routinely accept. agent 1.0: it acts on its own plan (nine of OWASP's ten examples score 1.0). - **Tools.** skill 1.0: a skill reaches the host agent's tools (shell, filesystem, network). mcp_server 0.5: it exposes its own tool set, mixed read and write and scoped to the server. agent 1.0: broad, high-authority tools. -- **Non-Determinism.** skill 1.0 and agent 1.0: an LLM interprets the instructions or plans with no hard guardrail. mcp_server 0.0: server code is deterministic, and the variance sits in the client that calls it. -- **Opacity.** skill 0.5 and mcp_server 0.5: the artifact (instruction text, schema, code) is readable and reviewable, but why the agent acted is a black box. agent 1.0: the agent's decision logic is not externally auditable (all ten OWASP examples score Opacity 1.0). +- **Non-Determinism, 1.0 in all three columns.** Each column describes the agent that uses the component, and that agent's LLM interprets its inputs with no hard guardrail. A deterministic server does not make the agent that calls it deterministic. OWASP scores Non-Determinism 1.0 in seven of its ten examples and 0.5 in three, and 0 in none. (An earlier draft gave mcp_server 0.0 because server code is deterministic; that is withdrawn.) +- **Opacity, 1.0 in all three columns.** Why the agent acted is not traceable, and OWASP scores Opacity 1.0 in all ten examples. (An earlier draft gave skill and mcp_server 0.5 because the artifact is readable and reviewable. That reading concerns the artifact and not the agent, and no departure from OWASP's practice is justified here, so none is made.) -Not covered: 8 records have no column, because 6 have no `component_type`, one is `tool` and one is `other`. S03b assigns each a type (the field exists and is optional) or the maintainer adds a column; that is not decided here. +Two of the four values are now the same in every column, so the columns differ only in Autonomy and Tools, and only for `mcp_server`. -Effect on the pilot: replacing the four factors by the table's values, with the pilot's six mechanism factors kept, changes no band of the ten records. Scores move by -0.1 to +0.3 and Factor_Sum by -1.5 to +1.5. Limits: the pilot has 9 skills, 1 `mcp_server` and no `agent`, so the `agent` column is tested by nothing and the `mcp_server` column by one record, and no value was checked against any product's default behaviour. A table loses some class difference: the pilot scored Non-Determinism 0 for AVE-2026-00063, a deterministic configuration flag, and the table gives a skill 1.0. That is the price of fixing the deployment factors per type. +Eight records have no column: AVE-2026-00016 (`other`), 00054 (`tool`), and 00081, 00083, 00084, 00085, 00086 and 00087 (no `component_type`). In S03b each is assigned to the nearest of the three types, with the reason stated in the record's notes. No new columns are added. + +Effect on the pilot: replacing the four factors by the table's values, with the pilot's six mechanism factors kept, changes the band of one of the ten records. AVE-2026-00063 goes from 6.7 MEDIUM to 7.0 HIGH, exactly on the boundary. Scores rise by 0.0 to 0.5 and Factor_Sum by 0.0 to 2.0, never down, because the table sets Non-Determinism and Opacity at the top for every record. The change for 00063 is the cost of fixing the deployment factors per type: the pilot scored it Non-Determinism 0 (a deterministic configuration flag) and Opacity 0.5. Limits: the pilot has 9 skills, 1 `mcp_server` and no `agent`, so the `agent` column is tested by nothing and the `mcp_server` column by one record, and no value was checked against any product's default behaviour. AVE's current factors map as follows (they were assigned against AVE's own definitions, not Table 2): `autonomy`, `non_determinism` and `multi_agent` keep their names; `tool_use` is Tools; `natural_language_input` is Language; `persistent_memory` is Persistence; `dynamic_identity` is Identity; `self_modification` is Self-Mod; `data_access` and `external_dependencies` have no counterpart; Context and Opacity are new. Carrying the eight over by value would carry definitions that differ from Table 2 (this is why the S01 plan says not to). @@ -302,14 +304,14 @@ Each item has a recommendation. None is applied until approved in writing. Statu | Decision | Status | |---|---| | D1 to D11, D15, D16, D18 | Approved as recommended | -| D1 (amendment) | The deployment-factor values per component type are published as a table (section 6.1), in place of D20. The table's values are drafted and take effect when the maintainer confirms them | +| D1 (amendment) | The deployment-factor values per component type are published as a table (section 6.1), in place of D20. The maintainer revised the values on 2026-11-05 (Non-Determinism and Opacity 1.0 in all columns); they are initial and adjustable during S03b | | D12 | Approved as recommended; stays conditional on TX4 | | D13, D14, D17 | Approved as changed in the maintainer's message of 2026-11-05 (D2 is amended by D17 part 4) | | D19 | Approved (maintainer, 2026-11-05) | | D20 | Withdrawn as written; replaced by the D1 amendment | -| D21 | Added at the maintainer's direction; not yet approved in writing | +| D21 | Approved with the change that the full tier is band-sensitive records only (maintainer, 2026-11-05) | -**D1. Reference profile rule.** Adopt section 5.3: the RDP, mechanism factors from the class, deployment factors typical as shipped, an anchor per class, a stated basis for every non-zero factor. Alternatives: worst case for deployment factors (sets four factors to 1.0 almost everywhere), or a profile per component type (more precise, more to maintain). *Recommend: the RDP as written.* *Amended 2026-11-05 by the maintainer: the deployment-factor values per component type are published as a table (section 6.1) in place of a new decision. The table's values are drafted and take effect when the maintainer confirms them.* +**D1. Reference profile rule.** Adopt section 5.3: the RDP, mechanism factors from the class, deployment factors typical as shipped, an anchor per class, a stated basis for every non-zero factor. Alternatives: worst case for deployment factors (sets four factors to 1.0 almost everywhere), or a profile per component type (more precise, more to maintain). *Recommend: the RDP as written.* *Amended 2026-11-05 by the maintainer: the deployment-factor values per component type are published as a table (section 6.1) in place of a new decision. The table's values are initial and adjustable during S03b.* **D2. Subsequent-system impact, and reach counted once.** Score `SC/SI/SA` only for propagation the class itself states, and count tool reach once, in the Tools factor. The literal reading of 3.1.1 gives every steering class `SC:H/SI:H` and a base near 9.4. *Recommend: as written; it follows nine of OWASP's ten examples.* *Amended by D17 part 4 (2026-11-05) for `SC`, `SI` and `SA`: the test is impact outside the vulnerable system's security domain at the reasonable worst case, not only propagation the description states. The half that counts tool reach once, in Tools, is unchanged.* @@ -416,11 +418,12 @@ Points the maintainer should settle: **D20. Withdrawn 2026-11-05.** The maintainer withdrew it as written (5 to 8 reference deployment profiles instead of per-record factors) and amended D1 instead, with the table of deployment-factor values per component type in section 6.1. No new decision. One finding is kept because it supports D19 and D21: with the vectors in the records today, the factor sum moves the distribution little (50 CRITICAL, 35 HIGH, 2 MEDIUM, 1 LOW at a Factor_Sum of 3.0, and 54, 33, 1, 0 at 8.0; 88 valid vectors, ThM 0.97, stored mitigation), because 67 of the 88 bases already put the CVSS-B band at CRITICAL. -**D21. Tier S03b by band sensitivity.** *Added at the maintainer's direction; not yet approved in writing.* After S03a, compute each record's band at zero and at maximum uplift: +**D21. Tier S03b by band sensitivity.** *Approved 2026-11-05, with the change that the full tier is band-sensitive records only.* After S03a, compute each record's band at zero and at maximum uplift, and recompute it whenever a vector or a mitigation level changes: - **Floor:** its S03a vector base times its Mitigation_Factor (stored, or assessed once S03b assesses it), at Factor_Sum 0. - **Ceiling:** Factor_Sum 10 with the top of its ThM range (Attacked 1.00, unless its sources rule that tier out), times the same Mitigation_Factor. At ThM 1.00 the ceiling is 10 times the Mitigation_Factor: 10.0 with no mitigation credit, 8.3 with Partial, 6.7 with Strong. -- **Light tier:** the band cannot change (floor and ceiling are in the same band) and neither end is within 0.5 of a band boundary. The record gets the six mechanism factors with a one-line basis each, on top of the four values from the table in section 6.1. -- **Full tier:** the band can change, or the floor is less than 0.5 above the lower boundary of its band, or the ceiling is less than 0.5 below the next boundary up. The record gets the full assessment as in the pilot (every factor with a basis, the uncertain calls scored) and second-assessor review. +- **Full tier: band-sensitive records only.** The band can change between floor and ceiling. The record gets the full assessment as in the pilot (every factor with a basis, the uncertain calls scored) and second-assessor review. +- **Light tier: every band-insensitive record.** Floor and ceiling are in the same band. The record gets the six mechanism factors with a one-line basis each, on top of the four values from the table in section 6.1. +- **Edge check, within the light tier.** A band-insensitive record whose floor is less than 0.5 above the lower boundary of its band, or whose ceiling is less than 0.5 below the next boundary up, gets an independent check of its vector and its mitigation level (D15, D17 part 8). It does not get a full factor assessment. -Indicative sizes on today's vectors, which S03a will change: of the 88 valid vectors, 47 are light and 41 are full (14 band-sensitive and 27 band-insensitive but within 0.5 of a boundary), and AVE-2026-00066 has no valid vector yet. The numbers will move, because re-derived bases were 0.7 lower on average in the pilot and lower bases make more records band-sensitive. With no mitigation credit a record is band-insensitive only if its floor is CRITICAL (a base of 9.0 or more); with Partial credit (ceiling 8.3), only if its floor is HIGH (a base of about 8.4 or more). The six mechanism factors are still assessed for the light tier because AARS and the score are stored and exported. *Recommend: adopt.* +Indicative sizes on today's vectors, which S03a will change: of the 88 valid vectors, 14 are band-sensitive (full tier), and 74 are band-insensitive (light tier), of which 27 are within 0.5 of a boundary and get the edge check. AVE-2026-00066 has no valid vector yet. The numbers will move, because re-derived bases were 0.7 lower on average in the pilot and lower bases make more records band-sensitive. With no mitigation credit a record is band-insensitive only if its floor is CRITICAL (a base of 9.0 or more); with Partial credit (ceiling 8.3), only if its floor is HIGH (a base of about 8.4 or more). The six mechanism factors are still assessed for the light tier because AARS and the score are stored and exported.