diff --git a/crosswalks/ave-to-agent-evidence-vocabulary.json b/crosswalks/ave-to-agent-evidence-vocabulary.json index 96fcc1f..31fcf16 100644 --- a/crosswalks/ave-to-agent-evidence-vocabulary.json +++ b/crosswalks/ave-to-agent-evidence-vocabulary.json @@ -4,21 +4,35 @@ "standard": "AVE", "version": "1.1.0", "url": "https://aveproject.org", - "record_count": 80, - "commit": "1e29789e4941b6c1c2435508dbf3c245eedc8d04" + "record_count": 89, + "commit": "4032785b67d35fed2e542b23577e8c601c61e145", + "previous": { + "record_count": 80, + "commit": "1e29789e4941b6c1c2435508dbf3c245eedc8d04", + "generated": "2026-09-15" + } }, "target": { "registry": "agent-evidence-vocabulary", - "version": "0.2.0", + "version": "0.8.0", "license": "CC0-1.0", - "url": "https://github.com/probityai/agent-evidence-vocabulary", + "url": "https://github.com/probityai/agent-evidence/tree/agent-evidence-vocabulary-v0.8.0/packages/vocabulary", "registry_file": "vocabulary.yaml", - "term_count": 8, - "checked_against_live_file": "2026-09-15", - "commit": "66177d65690e9d7eb7e4ff59df8f91792a90735b" + "registry_file_sha256": "76233ba8924cebdf053f0449ce023186805156aedca4121b9b156bd747a411b4", + "term_uri_base": "https://w3id.org/agent-evidence/vocab/v1/", + "term_count": 37, + "checked_against_live_file": "2026-10-27", + "commit": "5fe04d8ffe98710d68ee958c8595d0de6179a3bf", + "previous": { + "version": "0.2.0", + "term_count": 8, + "checked_against_live_file": "2026-09-15", + "commit": "66177d65690e9d7eb7e4ff59df8f91792a90735b", + "repository": "https://github.com/probityai-archive/agent-evidence-vocabulary" + } }, - "generated": "2026-09-15", - "note": "A field-level crosswalk between AVE's evidence-provenance properties and the agent-evidence-vocabulary registry, which names the axes an execution-evidence claim is read on: who observed the execution, how directly, and what the claim leaves out. The unit is a schema property rather than a category, because the two sides describe different things: AVE enumerates behavioral vulnerability classes and the registry names the provenance axes any claim about an execution carries. They meet at exactly one place, which is how AVE says where its evidence came from. Read coverage before trusting a row: none of the 80 records carries evidence_vantage, evidence_method or verification_basis. All three are optional in schema v1.1.0 and all three read absent on every record at the commit above, verified by fetching each record file rather than by reading the schema. Every mapping below is therefore evidence: inferred, established by comparing two schema definitions, and none is evidence: emitted. A row moves to emitted when a record carries the field and a reviewer can fetch it.", + "generated": "2026-10-27", + "note": "A field-level crosswalk between AVE's evidence-provenance properties and the agent-evidence-vocabulary registry, which names the axes an execution-evidence claim is read on: who observed the execution, how directly, what the claim leaves out, and why a published record's derived value changed. The unit is a schema property rather than a category, because the two sides describe different things: AVE enumerates behavioral vulnerability classes and the registry names the provenance axes any claim about an execution carries. They meet at two places: how AVE says where its evidence came from, and how an AVE record says why one of its own derived values changed. Read coverage before trusting a row: at the AVE commit above, 16 of the 89 records carry at least one of evidence_vantage and verification_basis, and none carries evidence_method. Nine records carry evidence_vantage (eight artifact, one substrate, AVE-2026-00074) and seven carry verification_basis (all artifact_reconstructed); this was checked by reading every record file in the pinned tree rather than by reading the schema. One record, AVE-2026-00074, carries a revisions entry, with reason_code declaration_added. The rows for evidence_vantage, verification_basis and revisions[].reason_code are therefore evidence: emitted, and the rows for evidence_method and evidence_basis_engines stay evidence: inferred, established by comparing two schema definitions. AVE records are unsigned JSON files in a git repository, so emitted here means that a record carries the field and a reviewer can fetch it at the pinned commit, which is the rule this file set on 2026-09-15; the registry's own definition of emitted names a signed statement, and whether a row meets the registry's promotion rule is for the registry to decide. A row moves to emitted when a record carries the field and a reviewer can fetch it.", "mappings": [ { "ave_field": "evidence_vantage", @@ -33,8 +47,20 @@ "artifact" ], "match_type": "exact", - "evidence": "inferred", - "notes": "Value sets are identical and so is the composition rule: both take the weakest input, so a claim mixing substrate and artifact observations inherits artifact. The two definitions were written independently and reached the same two-value split, which is the case for mapping them exact rather than structural. The registry adds one consumer-side requirement AVE's schema does not state, that a consumer with no policy-pinned substrate root must treat a substrate row as unattested rather than infer the root from the claim." + "evidence": "emitted", + "notes": "Value sets are identical and so is the composition rule: both take the weakest input, so a claim mixing substrate and artifact observations inherits artifact. The two definitions were written independently and reached the same two-value split, which is the case for mapping them exact rather than structural. The registry adds one consumer-side requirement AVE's schema does not state, that a consumer with no policy-pinned substrate root must treat a substrate row as unattested rather than infer the root from the claim. At 0.8.0 the registry term is unchanged in values and composition.", + "registry_term_uri": "https://w3id.org/agent-evidence/vocab/v1/observation_vantage", + "records_carrying": [ + "AVE-2026-00004", + "AVE-2026-00005", + "AVE-2026-00024", + "AVE-2026-00032", + "AVE-2026-00033", + "AVE-2026-00047", + "AVE-2026-00051", + "AVE-2026-00074", + "AVE-2026-00082" + ] }, { "ave_field": "evidence_method", @@ -50,7 +76,9 @@ ], "match_type": "exact", "evidence": "inferred", - "notes": "Identical value sets, identical weakest-input composition, and both treat reconstructed as the floor a producer may always truthfully state. AVE's schema says an absent value reads as reconstructed; the registry does not state a default, so a producer emitting both sides should write the value rather than rely on either reading." + "notes": "Identical value sets, identical weakest-input composition, and both treat reconstructed as the floor a producer may always truthfully state. AVE's schema says an absent value reads as reconstructed; the registry does not state a default, so a producer emitting both sides should write the value rather than rely on either reading. No record carries the field at the pinned commit, so the row stays inferred.", + "registry_term_uri": "https://w3id.org/agent-evidence/vocab/v1/observation_directness", + "records_carrying": [] }, { "ave_field": "verification_basis", @@ -63,8 +91,21 @@ "registry_term": "observation_vantage + observation_directness", "registry_section": "evidence_dimensions", "match_type": "structural", - "evidence": "inferred", - "notes": "The four values are the product of the two axes above, which is what scripts/write_verification_basis.py composes. The registry keeps the axes separate and does not define the composed term, so this is a structural correspondence rather than a term pairing: a consumer holding an AVE verification_basis can split it into the two registry axes without loss, and a consumer holding both registry values can compose the AVE value without loss." + "evidence": "emitted", + "notes": "The four values are the product of the two axes above, which is what scripts/write_verification_basis.py composes. The registry keeps the axes separate and does not define the composed term, so this is a structural correspondence rather than a term pairing: a consumer holding an AVE verification_basis can split it into the two registry axes without loss, and a consumer holding both registry values can compose the AVE value without loss. Seven records carry a declared value, all artifact_reconstructed, and validate_records.py checks each against the derivation, so the declaration is falsifiable.", + "registry_term_uri": [ + "https://w3id.org/agent-evidence/vocab/v1/observation_vantage", + "https://w3id.org/agent-evidence/vocab/v1/observation_directness" + ], + "records_carrying": [ + "AVE-2026-00083", + "AVE-2026-00084", + "AVE-2026-00085", + "AVE-2026-00086", + "AVE-2026-00087", + "AVE-2026-00088", + "AVE-2026-00089" + ] }, { "ave_field": "evidence_basis_engines", @@ -81,39 +122,239 @@ "registry_section": "evidence_dimensions", "match_type": "partial", "evidence": "inferred", - "notes": "One value carries vantage information and the rest do not. external_authority means a party outside the observed artifact answered, which is the substrate side of the registry's axis; sandbox observes execution and is the other candidate. pattern, yara, semgrep, llm and magika all read the artifact's own bytes, so they sit on the artifact side. AVE's own schema already composes this field into verification_basis by weakest input, so the partial mapping is not a gap in AVE, it is the reason the composed field exists." + "notes": "One value carries vantage information and the rest do not. external_authority means a party outside the observed artifact answered, which is the substrate side of the registry's axis; sandbox observes execution and is the other candidate. pattern, yara, semgrep, llm and magika all read the artifact's own bytes, so they sit on the artifact side. AVE's own schema already composes this field into verification_basis by weakest input, so the partial mapping is not a gap in AVE, it is the reason the composed field exists.", + "registry_term_uri": "https://w3id.org/agent-evidence/vocab/v1/observation_vantage" + }, + { + "ave_field": "revisions[].reason_code", + "ave_values": [ + "declaration_added", + "declaration_corrected", + "vocabulary_member_added", + "derivation_rule_changed" + ], + "registry_term": "revision_reason", + "registry_term_uri": "https://w3id.org/agent-evidence/vocab/v1/revision_reason", + "registry_section": "record_lifecycle", + "registry_values": [ + "declaration_added", + "declaration_corrected", + "vocabulary_member_added", + "derivation_rule_changed" + ], + "match_type": "exact", + "evidence": "emitted", + "source_path": "records/AVE-2026-00074.json", + "records_carrying": [ + "AVE-2026-00074" + ], + "notes": "Same four codes, same meaning, same entry shape: date, field, from, to and reason_code required, reason optional, append-only, and a record with no revisions array makes no claim about its own history. AVE copied the codes from the registry when it added the array (#360) and states that its enum stands on its own and does not follow later changes there; the four codes were compared with revision_reason at 0.8.0 and are identical. One record carries an entry, AVE-2026-00074, with reason_code declaration_added for evidence_vantage (null to substrate); the other three codes are valid in the schema and no record uses them. AVE adds checks the registry does not state, such as date order and an unbroken from-to chain per field, which are validator behavior and do not change the correspondence." } ], "gaps": [ { "side": "registry", "registry_term": "field_evidence_partition", - "reason": "Declares which identity's signature backs which field inside one mixed claim. AVE records a vulnerability class rather than a signed claim, so there is no per-field signer to partition." + "reason": "Declares which identity's signature backs which field inside one mixed claim. AVE records a vulnerability class rather than a signed claim, so there is no per-field signer to partition.", + "registry_section": "evidence_dimensions" }, { "side": "registry", "registry_term": "issuance_time_basis", - "reason": "Distinguishes a timestamp anchored to a beacon from one the producer asserts. AVE records carry published and last_updated as editorial dates on the record, not as claims about when an execution was observed." + "reason": "Distinguishes a timestamp anchored to a beacon from one the producer asserts. AVE records carry published and last_updated as editorial dates on the record, not as claims about when an execution was observed.", + "registry_section": "evidence_dimensions" }, { "side": "registry", "registry_term": "containment_posture", - "reason": "Describes the network posture an execution ran under. AVE classifies component behavior independently of any one run's containment." + "reason": "Describes the network posture an execution ran under. AVE classifies component behavior independently of any one run's containment.", + "registry_section": "posture_and_coverage" }, { "side": "registry", "registry_term": "coverage_denominator", - "reason": "States the population a claim was measured over. An AVE record is a class definition rather than a measurement, so it has no denominator to declare." + "reason": "States the population a claim was measured over. An AVE record is a class definition rather than a measurement, so it has no denominator to declare.", + "registry_section": "posture_and_coverage" }, { "side": "registry", "registry_term": "does_not_assert", - "reason": "Carries, inside the signed bytes, what a claim deliberately leaves out. AVE has no signed-claim envelope for this to sit in; the nearest thing is prose in vulnerability_rationale." + "reason": "Carries, inside the signed bytes, what a claim deliberately leaves out. AVE has no signed-claim envelope for this to sit in; the nearest thing is prose in vulnerability_rationale.", + "registry_section": "posture_and_coverage" }, { "side": "registry", "registry_term": "result", - "reason": "A recomputable outcome lattice over one execution: fail, degraded, pass_indirect, pass. AVE scores a class with AIVSS rather than recording an outcome, and the registry's own out-of-scope block rules out reading its lattice as a threshold anyway." + "reason": "A recomputable outcome lattice over one execution: fail, degraded, pass_indirect, pass. AVE scores a class with AIVSS rather than recording an outcome, and the registry's own out-of-scope block rules out reading its lattice as a threshold anyway.", + "registry_section": "outcome_lattice" + }, + { + "side": "registry", + "registry_term": "witness_scope", + "registry_section": "evidence_dimensions", + "reason": "Names whether the witness is the observed party, a peer or an outside party. An AVE record is a class definition with no witness, so there is nothing for the field to describe; evidence_vantage says what was observed, which the registry keeps orthogonal to this." + }, + { + "side": "registry", + "registry_term": "commitment_anchor", + "registry_section": "evidence_dimensions", + "reason": "Says whether the latest time a record existed is proven by an external anchor. AVE records carry editorial published and last_updated dates and no anchor." + }, + { + "side": "registry", + "registry_term": "anchor_time_rule", + "registry_section": "evidence_dimensions", + "reason": "The companion of commitment_anchor, which AVE has no counterpart for." + }, + { + "side": "registry", + "registry_term": "attestation_tier", + "registry_section": "evidence_dimensions", + "reason": "Says whether a platform re-derived the signed subject or signed what the caller supplied. AVE records are not platform attestations." + }, + { + "side": "registry", + "registry_term": "intent_binding", + "registry_section": "evidence_dimensions", + "reason": "Says whether the intent an action ran under was committed before the action. An AVE record describes a behavior class, not an action taken under an intent." + }, + { + "side": "registry", + "registry_term": "origin_kind", + "registry_section": "evidence_dimensions", + "reason": "Says which party produced the evidence a record is assembled from. AVE records name a researcher and sources, but no field states whether the producer was the runtime itself, a control plane or a log import." + }, + { + "side": "registry", + "registry_term": "independence_basis", + "registry_section": "evidence_dimensions", + "reason": "Says whether a guarantee was shown by sources independent of the party it is about. AVE records make no guarantee about a named party." + }, + { + "side": "registry", + "registry_term": "party_role", + "registry_section": "evidence_dimensions", + "reason": "Names the role a party holds with respect to one evidence set. AVE records have no audited provider, auditing organisation or evaluating authority." + }, + { + "side": "registry", + "registry_term": "control_relation", + "registry_section": "evidence_dimensions", + "reason": "A structured statement of who can direct the party a claim is about. AVE classifies component behavior and says nothing about ownership or control." + }, + { + "side": "registry", + "registry_term": "evidence_origin_class", + "registry_section": "evidence_dimensions", + "reason": "Says which kind of act produced an evidence item: a document read, a system queried, a person asked, a test performed. AVE's evidence_kind_default names a scanner's detection technique, which is a different question." + }, + { + "side": "registry", + "registry_term": "claim_subject", + "registry_section": "posture_and_coverage", + "reason": "Says whether a claim is about a tool, an agent or an organization. An AVE record is about a behavioral class of a component, which is none of the three." + }, + { + "side": "registry", + "registry_term": "base_state_resolution", + "registry_section": "posture_and_coverage", + "reason": "Says how the before-state root of an observed interval was obtained. AVE records observe no interval." + }, + { + "side": "registry", + "registry_term": "set_sufficiency", + "registry_section": "posture_and_coverage", + "reason": "Says whether the evidence set a claim rests on was sufficient. AVE carries a confidence prior and a mutation count, neither of which assesses a set." + }, + { + "side": "registry", + "registry_term": "material_change_trigger", + "registry_section": "posture_and_coverage", + "reason": "Names the event that ends a standing claim and obliges a re-assessment. AVE records are revised through the revisions array, which records what changed and not what would invalidate the record." + }, + { + "side": "registry", + "registry_term": "admission_decision", + "registry_section": "change_admission", + "reason": "The outcome of one decision on a proposed change to an agent harness. AVE records make no admission decision." + }, + { + "side": "registry", + "registry_term": "admission_gate", + "registry_section": "change_admission", + "reason": "The closed names of the checks an admission rests on. AVE has no admission." + }, + { + "side": "registry", + "registry_term": "evaluation_mode", + "registry_section": "change_admission", + "reason": "How an evaluation result attached to an admission was obtained. AVE has no admission." + }, + { + "side": "registry", + "registry_term": "replay_coverage", + "registry_section": "change_admission", + "reason": "Says whether a guard's replay checked every trace in its snapshot. AVE records do not replay traces." + }, + { + "side": "registry", + "registry_term": "replay_snapshot", + "registry_section": "change_admission", + "reason": "The SHA-256 that freezes the recorded traces a guard was replayed over. AVE records do not replay traces." + }, + { + "side": "registry", + "registry_term": "authority_change", + "registry_section": "change_admission", + "reason": "Says whether a candidate harness grants authority its parent lacked. AVE records classify behavior and do not compare a candidate with a parent." + }, + { + "side": "registry", + "registry_term": "done_contract", + "registry_section": "done_verification", + "reason": "The definition of done for one task, sealed before the agent's first turn. AVE has no task." + }, + { + "side": "registry", + "registry_term": "done_receipt", + "registry_section": "done_verification", + "reason": "The record of one done decision. AVE records no decision about a run." + }, + { + "side": "registry", + "registry_term": "acceptance_observed", + "registry_section": "done_verification", + "reason": "Whether acceptance commands pass on the agent's final tree. AVE has no acceptance commands." + }, + { + "side": "registry", + "registry_term": "protected_path", + "registry_section": "done_verification", + "reason": "A path the contract places off limits to the agent. AVE has no contract." + }, + { + "side": "registry", + "registry_term": "claimed_tool_output", + "registry_section": "done_verification", + "reason": "A command the agent says it ran, parsed from its transcript. AVE records hold no transcript." + }, + { + "side": "registry", + "registry_term": "observed_tool_output", + "registry_section": "done_verification", + "reason": "The exec events an independent observer recorded for a command. AVE records hold no run." + }, + { + "side": "registry", + "registry_term": "stop_decision", + "registry_section": "done_verification", + "reason": "The action a published policy table returns for a run's verdict history. AVE has no run history." + }, + { + "side": "registry", + "registry_term": "inconclusive_verdict", + "registry_section": "done_verification", + "reason": "The verdict that the records neither show a claim true nor false. AVE records a class definition, which has no such verdict." }, { "side": "ave", @@ -134,17 +375,27 @@ "side": "ave", "ave_field": "evidence_kind_default", "reason": "A scanner hint naming the detection technique. The registry names where a claim came from rather than how it was computed." + }, + { + "side": "ave", + "ave_field": "detection_methodology", + "reason": "Free text describing the detection approach (static scan, semantic analysis, behavioral sandbox, network monitoring). The registry names where a claim came from and has no term for how a scanner worked." } ], "coverage": { - "registry_terms_total": 8, - "registry_terms_mapped": 2, + "registry_terms_total": 37, + "registry_terms_mapped": 3, "registry_terms_structurally_covered": 1, - "registry_terms_unmapped": 6, - "ave_evidence_fields_total": 7, - "ave_evidence_fields_mapped": 4, - "ave_records_total": 80, - "ave_records_carrying_any_mapped_field": 0, - "what_the_counts_leave_out": "registry_terms_mapped counts observation_vantage and observation_directness. verification_basis covers the same two axes composed, so it is counted once as structural rather than twice, and registry_terms_unmapped plus the two mapped terms is 8. ave_records_carrying_any_mapped_field is 0 because evidence_vantage, evidence_method and verification_basis are absent from all 80 record files at the pinned commit, checked by fetching each file. evidence_basis_engines is present on records and is the partial row, so the zero describes the three composed fields rather than the whole mapping." - } + "registry_terms_unmapped": 34, + "ave_evidence_fields_total": 10, + "ave_evidence_fields_mapped": 5, + "ave_records_total": 89, + "ave_records_carrying_any_mapped_field": 16, + "ave_records_carrying_evidence_vantage": 9, + "ave_records_carrying_evidence_method": 0, + "ave_records_carrying_verification_basis": 7, + "ave_records_carrying_revisions": 1, + "what_the_counts_leave_out": "registry_terms_mapped counts observation_vantage, observation_directness and revision_reason, and registry_terms_unmapped plus those three is 37. verification_basis covers the same two axes composed, so it is counted once as structural rather than twice. ave_evidence_fields_total counts the ten schema properties this file maps or lists as gaps: the five mapped (evidence_vantage, evidence_method, verification_basis, evidence_basis_engines, revisions) and the five in gaps. ave_records_carrying_any_mapped_field is 16, the union of the nine records carrying evidence_vantage and the seven carrying verification_basis, and it does not count the one record carrying revisions or the 89 carrying evidence_basis_engines, which is the partial row. Every figure was read from the record files at the pinned commit." + }, + "revision_note": "2026-10-27 refresh of the 2026-09-15 revision. Source: AVE record_count 80 to 89 and the pinned commit moved to 4032785b. Target: retargeted from agent-evidence-vocabulary 0.2.0 (8 terms, commit 66177d65, now in the archived probityai-archive/agent-evidence-vocabulary) to 0.8.0 (37 terms) in probityai/agent-evidence under packages/vocabulary, read at commit 5fe04d8f; the 0.2.0 values are kept under previous on both endpoints. The two value sets and the weakest-input composition rule of observation_vantage and observation_directness are unchanged at 0.8.0, so those rows keep match_type exact. Coverage: records carrying a mapped field 0 to 16, and the evidence_vantage and verification_basis rows moved from inferred to emitted. Added: the revisions[].reason_code row against revision_reason (AVE added the array in #360, copying the four codes from this registry), a registry_term_uri on every row, and gaps for the 28 registry terms added since 0.2.0. Corrected: ave_evidence_fields_total was stated as 7 on 2026-09-15 while the fields the file mapped or listed as gaps were 8, and detection_methodology, also a schema property, was in neither list; it is now listed as a gap, and the total is 10 with revisions added." } diff --git a/crosswalks/ave-to-agent-evidence-vocabulary.md b/crosswalks/ave-to-agent-evidence-vocabulary.md index 3821ac4..84fabbe 100644 --- a/crosswalks/ave-to-agent-evidence-vocabulary.md +++ b/crosswalks/ave-to-agent-evidence-vocabulary.md @@ -2,72 +2,93 @@ A field-level crosswalk between AVE's evidence-provenance properties and the agent-evidence-vocabulary registry, which names the axes an execution-evidence -claim is read on: who observed the execution, how directly, and what the claim -leaves out. Machine-readable form in +claim is read on: who observed the execution, how directly, what the claim +leaves out, and why a published record's derived value changed. Machine-readable +form in [`ave-to-agent-evidence-vocabulary.json`](ave-to-agent-evidence-vocabulary.json), against [`schema/crosswalk-1.0.0.schema.json`](../schema/crosswalk-1.0.0.schema.json). | | | |---|---| -| Source | AVE 1.1.0, 80 records, commit `1e29789e4941b6c1c2435508dbf3c245eedc8d04` | -| Target | [agent-evidence-vocabulary](https://github.com/probityai/agent-evidence-vocabulary) 0.2.0, 8 terms, CC0-1.0, commit `66177d65690e9d7eb7e4ff59df8f91792a90735b` | -| Generated | 2026-09-15 | +| Source | AVE 1.1.0, 89 records, commit `4032785b67d35fed2e542b23577e8c601c61e145` | +| Target | [agent-evidence-vocabulary](https://github.com/probityai/agent-evidence/tree/agent-evidence-vocabulary-v0.8.0/packages/vocabulary) 0.8.0, 37 terms, CC0-1.0, commit `5fe04d8ffe98710d68ee958c8595d0de6179a3bf` | +| Generated | 2026-10-27 | | Unit | one schema property, not one category | +Previous revision (2026-09-15): AVE 1.1.0 with 80 records at `1e29789e`, against +vocabulary 0.2.0 with 8 terms at `66177d65`. The registry has since moved into +the `agent-evidence` repository, and the old repository is archived. + ## Read this first -None of the 80 records carries `evidence_vantage`, `evidence_method` or -`verification_basis`. All three are optional in schema v1.1.0, and all three -read absent on every record file at the pinned commit. That was checked by -fetching each of the 80 files, not by reading the schema. +At the pinned commit, 16 of the 89 records carry at least one of +`evidence_vantage` and `verification_basis`, and none carries `evidence_method`. +Nine records carry `evidence_vantage` (eight `artifact`, and AVE-2026-00074 with +`substrate`), and seven carry `verification_basis` (all `artifact_reconstructed`). +That was checked by reading every record file in the pinned tree, not by reading +the schema. One record, AVE-2026-00074, carries a `revisions` entry, with +`reason_code` `declaration_added`. -So every row below carries an evidence state of inferred, established by -comparing two schema definitions. None carries emitted, and a reviewer should -not read one that way. A row moves to emitted when a record carries the field -and the reviewer can fetch it. The script that writes verification_basis has -nothing to derive over until that happens. +So the `evidence_vantage`, `verification_basis` and `revisions[].reason_code` +rows carry an evidence state of emitted, and the `evidence_method` and +`evidence_basis_engines` rows stay inferred, established by comparing two schema +definitions. AVE records are unsigned JSON files in a git repository, so emitted +here means a record carries the field and a reviewer can fetch it at the pinned +commit, which is the rule this file set in September. The registry's own +definition of emitted names a signed statement, and whether a row meets the +registry's promotion rule is for the registry to decide. ## The mapping -| AVE field | Registry term | Match | Why | -|---|---|---|---| -| `evidence_vantage` | `observation_vantage` | exact | `substrate` and `artifact` on both sides, same two values, same weakest-input composition | -| `evidence_method` | `observation_directness` | exact | `intercepted` and `reconstructed` on both sides, same composition, same floor | -| `verification_basis` | `observation_vantage` + `observation_directness` | structural | AVE's four values are the product of the two registry axes; either side converts without loss | -| `evidence_basis_engines` | `observation_vantage` | partial | `external_authority` and `sandbox` sit on the substrate side; the five artifact-reading engines sit on the other | +| AVE field | Registry term | Match | Evidence | Why | +|---|---|---|---|---| +| `evidence_vantage` | `observation_vantage` | exact | emitted, 9 records | `substrate` and `artifact` on both sides, same two values, same weakest-input composition | +| `evidence_method` | `observation_directness` | exact | inferred, 0 records | `intercepted` and `reconstructed` on both sides, same composition, same floor | +| `verification_basis` | `observation_vantage` + `observation_directness` | structural | emitted, 7 records | AVE's four values are the product of the two registry axes; either side converts without loss | +| `evidence_basis_engines` | `observation_vantage` | partial | inferred | `external_authority` and `sandbox` sit on the substrate side; the five artifact-reading engines sit on the other | +| `revisions[].reason_code` | `revision_reason` | exact | emitted, 1 record | the same four codes and the same entry shape; AVE copied the codes when it added the array in #360 | -The two exact rows are unusual and worth a sentence. The definitions were +The two axis rows are unusual and worth a sentence. The definitions were written independently, on different sides, and reached the same two-value split with the same composition rule. That is the case for calling them exact rather -than approximate: there is nothing to reconcile. +than approximate: there is nothing to reconcile. Both value sets and the +composition rule are unchanged at registry 0.8.0. + +The `revisions` row is the newest. The four codes in AVE's schema enum were +compared with `revision_reason` at 0.8.0 and are identical. AVE states that its +enum stands on its own and does not follow later changes in the registry. One +code, `declaration_added`, is used by one record, and the other three are valid +in the schema and unused. ## What does not map -Six registry terms have no AVE counterpart, because an AVE record classifies a -component's behavior while the registry describes one observed execution. +Thirty-four registry terms have no AVE counterpart, because an AVE record +classifies a component's behavior while the registry describes one observed +execution, the admission of a change to a harness, or the decision that a task +is done. The JSON lists each term with its own reason. By section: -| Registry term with no AVE counterpart | AVE field with no registry counterpart | +| Registry section | Terms with no AVE counterpart | |---|---| -| `field_evidence_partition` | `confidence_baseline` | -| `issuance_time_basis` | `detection_stage` | -| `containment_posture` | `detection_layer` | -| `coverage_denominator` | `evidence_kind_default` | -| `does_not_assert` | | -| `result` | | - -The first field in the right-hand column will never get a counterpart. The -registry's own out-of-scope block excludes scored assessment of an actor, so a -confidence prior sits outside it by design and not by omission. +| `evidence_dimensions` | `witness_scope`, `field_evidence_partition`, `issuance_time_basis`, `commitment_anchor`, `anchor_time_rule`, `attestation_tier`, `intent_binding`, `origin_kind`, `independence_basis`, `party_role`, `control_relation`, `evidence_origin_class` | +| `posture_and_coverage` | `containment_posture`, `coverage_denominator`, `does_not_assert`, `claim_subject`, `base_state_resolution`, `set_sufficiency`, `material_change_trigger` | +| `outcome_lattice` | `result` | +| `change_admission` | `admission_decision`, `admission_gate`, `evaluation_mode`, `replay_coverage`, `replay_snapshot`, `authority_change` | +| `done_verification` | `done_contract`, `done_receipt`, `acceptance_observed`, `protected_path`, `claimed_tool_output`, `observed_tool_output`, `stop_decision`, `inconclusive_verdict` | -The per-field reasons are in the gaps array of the JSON. +Five AVE fields have no registry counterpart: `confidence_baseline`, +`detection_stage`, `detection_layer`, `evidence_kind_default` and +`detection_methodology`. The first will never get one. The registry's own +out-of-scope block excludes scored assessment of an actor, so a confidence prior +sits outside it by design and not by omission. ## Offered as a basis for collaboration -The registry is CC0-1.0 and its eight terms all carry the status proposed and none carries canonical. Its -promotion rule is that a term becomes canonical only when an independently -maintained system emits it in a running artifact and files a crosswalk with a -source path a reviewer can fetch. AVE already declares two of those fields in -its schema. If records start carrying them, the two exact rows above become the -evidence that rule asks for, and the coverage number in the JSON moves without -the mapping changing. +The registry is CC0-1.0 and all 37 of its terms carry the status proposed and +none carries canonical. Its promotion rule is that a term becomes canonical only +when an independently maintained system emits it in a running artifact and files +a crosswalk with a source path a reviewer can fetch. The `revisions` row above +carries that source path, `records/AVE-2026-00074.json`, and the registry's +promotion trigger for `revision_reason` asks for exactly that shape. If more +records carry `evidence_method` or more revisions, the coverage numbers in the +JSON move without the mapping changing. diff --git a/dist/ave-records-latest.json b/dist/ave-records-latest.json index 84fc17c..d24fc9e 100644 --- a/dist/ave-records-latest.json +++ b/dist/ave-records-latest.json @@ -1036,6 +1036,13 @@ "private_data" ] }, + "security_boundary": "static file content → LLM context window (a boundary that does not exist the same way for a deterministic program reading the same file)", + "missing_control": "no separation between content an LLM incidentally reads and content a co-located prompt-injection payload can induce the LLM to act on; a hardcoded credential is exposed to both", + "vulnerability_rationale": { + "capability": "Skill/component files can contain literal string values, including credential-shaped ones.", + "vulnerability": "Conventional secrets-in-source (CWE-798), amplified by a property specific to agent components: the credential sits in the same context window an LLM reads, so a prompt injection payload elsewhere in that context can instruct the agent to read and exfiltrate it. A compiled program reading the same file has no such boundary.", + "impact": "The credential is readable by any process that loads the component, including the agent itself, any injected instructions that reach the context window, and any observer with read access to the file." + }, "mitigation": { "strategy": [ "validate_input", @@ -1066,7 +1073,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-05-16T00:00:00Z", - "last_updated": "2026-05-16T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "CWE-798", @@ -3438,6 +3445,13 @@ "external_comms" ] }, + "security_boundary": "trusted instruction content → shell execution, with no boundary between the two once a component's text is treated as instruction", + "missing_control": "no distinction between natural-language content that merely describes a step and natural-language content that constitutes an executable directive", + "vulnerability_rationale": { + "capability": "Agent with shell/code-execution tool access follows embedded commands.", + "vulnerability": "Conventional command injection (CWE-78 territory) delivered through natural language rather than code. The mechanism is conventional; what makes it an AVE class is the channel: the input is natural-language content that an agent reads and treats as an instruction, and tools built to find command injection in code, such as SAST scanners, do not read that channel, so the flaw stays invisible to them until the agent has acted on it.", + "impact": "Arbitrary remote code executes on the host with the agent's privilege level." + }, "mitigation": { "strategy": [ "deny_by_default", @@ -3460,7 +3474,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-04-19T09:00:00Z", - "last_updated": "2026-08-26T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "CWE-78", @@ -3588,6 +3602,13 @@ "untrusted_content" ] }, + "security_boundary": "instruction content → shell execution, with no boundary between the two", + "missing_control": "no distinction between natural-language content that merely describes a step and natural-language content that constitutes an executable directive", + "vulnerability_rationale": { + "capability": "Agent with filesystem/shell access follows embedded destructive commands.", + "vulnerability": "Conventional destructive-command pattern (`rm -rf /` class), delivered through natural language by the same channel as AVE-2026-00004: instructions an agent follows, which code-oriented scanners do not read. It stays a separate class from 00004 because the impact differs: irrecoverable data loss with no code-execution requirement, a severity and detection distinction and not only a label.", + "impact": "Files on the host are permanently destroyed, and the loss is irrecoverable without backup." + }, "mitigation": { "strategy": [ "require_human_approval", @@ -3610,7 +3631,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-04-19T09:00:00Z", - "last_updated": "2026-08-26T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "CWE-78", @@ -7531,6 +7552,13 @@ "untrusted_content" ] }, + "security_boundary": "instruction content → unsafe deserialization/eval call, with no boundary between them", + "missing_control": "no detection of unsafe deserialization or eval when it is instructed in natural language and not written as code", + "vulnerability_rationale": { + "capability": "Agent follows instructions to deserialize or evaluate externally supplied data.", + "vulnerability": "Conventional remote code execution through unsafe deserialization or eval (CWE-502 and CWE-94), delivered through natural language. The mechanism is conventional; the distinction is the channel, as for AVE-2026-00004 and 00005: the unsafe operation is instructed in text that an agent follows, and code-oriented scanners do not read that text.", + "impact": "A reliable code execution path through the agent's execution environment." + }, "mitigation": { "strategy": [ "validate_input", @@ -7575,7 +7603,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-04-19T09:00:00Z", - "last_updated": "2026-10-31T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "CWE-502", @@ -8596,6 +8624,13 @@ "untrusted_content" ] }, + "security_boundary": "agent output (trusted-intermediary status) → downstream interpreter (SQL/HTML/shell)", + "missing_control": "no escaping or sanitization gate between agent-generated output and downstream interpretation", + "vulnerability_rationale": { + "capability": "Agent output is passed to downstream interpreters as a trusted intermediary.", + "vulnerability": "No escaping/sanitization gate exists between agent-generated output and downstream interpretation. The mechanism is classic injection (CWE-79 and CWE-89 territory); what is agentic is the trust elevation backend systems grant an agent compared with raw user input, so the agent's trusted role draws less scrutiny than raw user input would.", + "impact": "Classic injection (SQLi/XSS/command injection) via a trust-elevated conduit." + }, "mitigation": { "strategy": [ "sanitize_output", @@ -8640,7 +8675,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-04-19T09:00:00Z", - "last_updated": "2026-10-31T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "OWASP LLM Insecure Output", @@ -11179,6 +11214,13 @@ "external_comms" ] }, + "security_boundary": "declared or default provider endpoint → actual configured endpoint", + "missing_control": "no verification that a provider or telemetry endpoint value matches the component's declared or default provider before traffic is sent", + "vulnerability_rationale": { + "capability": "Components can declare telemetry, provider and API endpoint values in configuration.", + "vulnerability": "Conventional config-based traffic redirection, but tied to infrastructure that exists only because the component is agentic: LLM provider base URLs, MCP server URLs and A2A agent-card URLs. No verification checks the endpoint against the declared or default provider, and a committed value redirects the traffic with no content injected into the model's context. The record cites a real case, CVE-2026-21852, where a redirected ANTHROPIC_BASE_URL leaked a user's API key.", + "impact": "Telemetry, model or provider traffic is sent to a host the component's author did not intend, so credentials such as the user's API key can leak, before any trust confirmation is shown." + }, "mitigation": { "strategy": [ "deny_by_default", @@ -11206,7 +11248,7 @@ "researcher": "Nicolai (predictor2718)", "researcher_url": "https://github.com/predictor2718", "published": "2026-08-06T00:00:00Z", - "last_updated": "2026-08-08T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "cfgaudit crosswalk gap detail", @@ -11314,6 +11356,13 @@ "untrusted_content" ] }, + "security_boundary": "reviewed artifact (the .py source a human or scanner reads) → executed artifact (the .pyc the interpreter actually loads)", + "missing_control": "no bytecode-versus-source comparison step in the review or scanning pipeline", + "vulnerability_rationale": { + "capability": "CPython prefers a valid cached .pyc over recompiling source when one is present.", + "vulnerability": "The bytecode-cache preference is a general interpreter property and not agent-specific in mechanism. What makes it an AVE class is the target: research cited in the record (CSA AI Safety Initiative and Trail of Bits) frames it as a technique for evading agent-skill scanners specifically, which document their own inability to analyze binary or encrypted code, so a skill's .pyc can carry dangerous primitives that a source-only scan never sees.", + "impact": "The interpreter executes dangerous primitives (process execution, network calls, credential-path access) that appear nowhere in the .py source a reviewer or source-only scanner reads." + }, "mitigation": { "strategy": [ "validate_input", @@ -11340,7 +11389,7 @@ "researcher": "CSA / Trail of Bits", "researcher_url": "https://labs.cloudsecurityalliance.org/research/csa-research-note-ai-agent-skill-scanner-bypass-20260610-csa/", "published": "2026-08-07T00:00:00Z", - "last_updated": "2026-08-07T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "repo-forensics bytecode scanner", diff --git a/dist/ave-records-latest.manifest.json b/dist/ave-records-latest.manifest.json index 60d533d..f46e293 100644 --- a/dist/ave-records-latest.manifest.json +++ b/dist/ave-records-latest.manifest.json @@ -1,7 +1,7 @@ { "schema_version": "1.3.0", "record_count": 89, - "generated_at": "2026-11-04T13:46:15.467Z", + "generated_at": "2026-11-05T00:00:53.487Z", "source": "https://github.com/aveproject/ave", - "sha256": "ef927adae8c9deca9361808f60869d1bfa6e65622de60c5c6c9e4bbcb82cb4ab" + "sha256": "3631a6920bec6aad889b610bfabf8a9cac28aabfe29e687a3f6d79c3ae3ef944" } diff --git a/records/AVE-2026-00004.json b/records/AVE-2026-00004.json index 5f24d5c..f486538 100644 --- a/records/AVE-2026-00004.json +++ b/records/AVE-2026-00004.json @@ -46,6 +46,13 @@ "external_comms" ] }, + "security_boundary": "trusted instruction content → shell execution, with no boundary between the two once a component's text is treated as instruction", + "missing_control": "no distinction between natural-language content that merely describes a step and natural-language content that constitutes an executable directive", + "vulnerability_rationale": { + "capability": "Agent with shell/code-execution tool access follows embedded commands.", + "vulnerability": "Conventional command injection (CWE-78 territory) delivered through natural language rather than code. The mechanism is conventional; what makes it an AVE class is the channel: the input is natural-language content that an agent reads and treats as an instruction, and tools built to find command injection in code, such as SAST scanners, do not read that channel, so the flaw stays invisible to them until the agent has acted on it.", + "impact": "Arbitrary remote code executes on the host with the agent's privilege level." + }, "mitigation": { "strategy": [ "deny_by_default", @@ -68,7 +75,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-04-19T09:00:00Z", - "last_updated": "2026-08-26T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "CWE-78", diff --git a/records/AVE-2026-00005.json b/records/AVE-2026-00005.json index e94b078..b1a867f 100644 --- a/records/AVE-2026-00005.json +++ b/records/AVE-2026-00005.json @@ -45,6 +45,13 @@ "untrusted_content" ] }, + "security_boundary": "instruction content → shell execution, with no boundary between the two", + "missing_control": "no distinction between natural-language content that merely describes a step and natural-language content that constitutes an executable directive", + "vulnerability_rationale": { + "capability": "Agent with filesystem/shell access follows embedded destructive commands.", + "vulnerability": "Conventional destructive-command pattern (`rm -rf /` class), delivered through natural language by the same channel as AVE-2026-00004: instructions an agent follows, which code-oriented scanners do not read. It stays a separate class from 00004 because the impact differs: irrecoverable data loss with no code-execution requirement, a severity and detection distinction and not only a label.", + "impact": "Files on the host are permanently destroyed, and the loss is irrecoverable without backup." + }, "mitigation": { "strategy": [ "require_human_approval", @@ -67,7 +74,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-04-19T09:00:00Z", - "last_updated": "2026-08-26T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "CWE-78", diff --git a/records/AVE-2026-00033.json b/records/AVE-2026-00033.json index 27723c4..a8c934f 100644 --- a/records/AVE-2026-00033.json +++ b/records/AVE-2026-00033.json @@ -44,6 +44,13 @@ "untrusted_content" ] }, + "security_boundary": "instruction content → unsafe deserialization/eval call, with no boundary between them", + "missing_control": "no detection of unsafe deserialization or eval when it is instructed in natural language and not written as code", + "vulnerability_rationale": { + "capability": "Agent follows instructions to deserialize or evaluate externally supplied data.", + "vulnerability": "Conventional remote code execution through unsafe deserialization or eval (CWE-502 and CWE-94), delivered through natural language. The mechanism is conventional; the distinction is the channel, as for AVE-2026-00004 and 00005: the unsafe operation is instructed in text that an agent follows, and code-oriented scanners do not read that text.", + "impact": "A reliable code execution path through the agent's execution environment." + }, "mitigation": { "strategy": [ "validate_input", @@ -88,7 +95,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-04-19T09:00:00Z", - "last_updated": "2026-10-31T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "CWE-502", diff --git a/records/AVE-2026-00040.json b/records/AVE-2026-00040.json index 8e75d65..a05c95f 100644 --- a/records/AVE-2026-00040.json +++ b/records/AVE-2026-00040.json @@ -41,6 +41,13 @@ "untrusted_content" ] }, + "security_boundary": "agent output (trusted-intermediary status) → downstream interpreter (SQL/HTML/shell)", + "missing_control": "no escaping or sanitization gate between agent-generated output and downstream interpretation", + "vulnerability_rationale": { + "capability": "Agent output is passed to downstream interpreters as a trusted intermediary.", + "vulnerability": "No escaping/sanitization gate exists between agent-generated output and downstream interpretation. The mechanism is classic injection (CWE-79 and CWE-89 territory); what is agentic is the trust elevation backend systems grant an agent compared with raw user input, so the agent's trusted role draws less scrutiny than raw user input would.", + "impact": "Classic injection (SQLi/XSS/command injection) via a trust-elevated conduit." + }, "mitigation": { "strategy": [ "sanitize_output", @@ -85,7 +92,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-04-19T09:00:00Z", - "last_updated": "2026-10-31T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "OWASP LLM Insecure Output", diff --git a/records/AVE-2026-00047.json b/records/AVE-2026-00047.json index 66a20a2..47f1ef7 100644 --- a/records/AVE-2026-00047.json +++ b/records/AVE-2026-00047.json @@ -49,6 +49,13 @@ "private_data" ] }, + "security_boundary": "static file content → LLM context window (a boundary that does not exist the same way for a deterministic program reading the same file)", + "missing_control": "no separation between content an LLM incidentally reads and content a co-located prompt-injection payload can induce the LLM to act on; a hardcoded credential is exposed to both", + "vulnerability_rationale": { + "capability": "Skill/component files can contain literal string values, including credential-shaped ones.", + "vulnerability": "Conventional secrets-in-source (CWE-798), amplified by a property specific to agent components: the credential sits in the same context window an LLM reads, so a prompt injection payload elsewhere in that context can instruct the agent to read and exfiltrate it. A compiled program reading the same file has no such boundary.", + "impact": "The credential is readable by any process that loads the component, including the agent itself, any injected instructions that reach the context window, and any observer with read access to the file." + }, "mitigation": { "strategy": [ "validate_input", @@ -79,7 +86,7 @@ "researcher": "Saray Chak", "researcher_url": "https://bawbel.io", "published": "2026-05-16T00:00:00Z", - "last_updated": "2026-05-16T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "CWE-798", diff --git a/records/AVE-2026-00073.json b/records/AVE-2026-00073.json index f5af284..be4a2be 100644 --- a/records/AVE-2026-00073.json +++ b/records/AVE-2026-00073.json @@ -32,6 +32,13 @@ "trifecta_profile": { "requires": ["private_data", "external_comms"] }, + "security_boundary": "declared or default provider endpoint → actual configured endpoint", + "missing_control": "no verification that a provider or telemetry endpoint value matches the component's declared or default provider before traffic is sent", + "vulnerability_rationale": { + "capability": "Components can declare telemetry, provider and API endpoint values in configuration.", + "vulnerability": "Conventional config-based traffic redirection, but tied to infrastructure that exists only because the component is agentic: LLM provider base URLs, MCP server URLs and A2A agent-card URLs. No verification checks the endpoint against the declared or default provider, and a committed value redirects the traffic with no content injected into the model's context. The record cites a real case, CVE-2026-21852, where a redirected ANTHROPIC_BASE_URL leaked a user's API key.", + "impact": "Telemetry, model or provider traffic is sent to a host the component's author did not intend, so credentials such as the user's API key can leak, before any trust confirmation is shown." + }, "mitigation": { "strategy": ["deny_by_default", "verify_identity"], "enforcement_point": "static_scan", @@ -56,7 +63,7 @@ "researcher": "Nicolai (predictor2718)", "researcher_url": "https://github.com/predictor2718", "published": "2026-08-06T00:00:00Z", - "last_updated": "2026-08-08T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "cfgaudit crosswalk gap detail", diff --git a/records/AVE-2026-00075.json b/records/AVE-2026-00075.json index 1999fc9..0d60b60 100644 --- a/records/AVE-2026-00075.json +++ b/records/AVE-2026-00075.json @@ -36,6 +36,13 @@ "trifecta_profile": { "requires": ["untrusted_content"] }, + "security_boundary": "reviewed artifact (the .py source a human or scanner reads) → executed artifact (the .pyc the interpreter actually loads)", + "missing_control": "no bytecode-versus-source comparison step in the review or scanning pipeline", + "vulnerability_rationale": { + "capability": "CPython prefers a valid cached .pyc over recompiling source when one is present.", + "vulnerability": "The bytecode-cache preference is a general interpreter property and not agent-specific in mechanism. What makes it an AVE class is the target: research cited in the record (CSA AI Safety Initiative and Trail of Bits) frames it as a technique for evading agent-skill scanners specifically, which document their own inability to analyze binary or encrypted code, so a skill's .pyc can carry dangerous primitives that a source-only scan never sees.", + "impact": "The interpreter executes dangerous primitives (process execution, network calls, credential-path access) that appear nowhere in the .py source a reviewer or source-only scanner reads." + }, "mitigation": { "strategy": ["validate_input", "deny_by_default"], "enforcement_point": "static_scan", @@ -59,7 +66,7 @@ "researcher": "CSA / Trail of Bits", "researcher_url": "https://labs.cloudsecurityalliance.org/research/csa-research-note-ai-agent-skill-scanner-bypass-20260610-csa/", "published": "2026-08-07T00:00:00Z", - "last_updated": "2026-08-07T00:00:00Z", + "last_updated": "2026-11-04T00:00:00Z", "references": [ { "tag": "repo-forensics bytecode scanner",