AID-H-021.003: Agent Context Source & Configuration Governance
Pillars: app, infra, data
Lifecycle: building, validation, operation
Scope boundary
Owns upstream context-source ownership, trust tier, freshness definitions, precedence, contradiction handling, code-to-document synchronization, and signed release eligibility. It does not verify runtime chunks or decide which retrieval candidates enter a live prompt.
AID-H-020.004: AID-H-021.003 defines and signs the context-source governance release; AID-H-020.004 verifies and enforces that release for every retrieval candidate. Policy authorship and runtime enforcement remain separate.
AID-M-002: AID-H-021.003 governs operational context sources, ownership, freshness, precedence, and release state; AID-M-002 creates broader cross-lifecycle provenance, integrity, and risk-characterization records. Context governance consumes lineage but owns the operational policy for agent-readable sources.
AID-H-016: AID-H-021.003 decides which external context sources and configurations are eligible; AID-H-016 hardens instruction hierarchy and data separation once context is assembled. Approved context can still be untrusted data relative to system instructions.
AID-H-021.005: AID-H-021.003 governs source ownership, freshness, precedence, and release of operational context; AID-H-021.005 decides whether the workspace manifest may activate execution-capable surfaces. Approved context governance does not establish workspace trust, and workspace trust does not approve every context source.
Implementation guidance
- AID-H-021.003-G001: Govern the context corpus with a machine-readable manifest that defines owner, trust tier, freshness SLA, and criticality for every document.
- AID-H-021.003-G002: Evaluate every governed context source against its versioned freshness policy and publish a signed release-eligibility report for downstream retrieval enforcement.
- AID-H-021.003-G003: Detect contradictory policy statements across documents and enforce deterministic precedence before ingestion.
- AID-H-021.003-G004: Sign the approved context source/configuration governance state as an immutable release manifest for H-020.004 to verify and enforce.
- AID-H-021.003-G005: Gate releases on code-doc drift checks so behavior-changing code updates cannot ship with stale context guidance.
AID-H-021.003-G001
Delivery level: reusable corpus-manifest gate
The manifest is complete only when it is reconciled in both directions with the corpus directory. Validating listed rows alone allows an unlisted document to enter indexing. Keep signature enforcement for critical context in the sibling signed-manifest method; this method owns inventory, ownership, trust tier, criticality, and freshness metadata.
Step 1: Use a closed manifest schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["schema_version", "manifest_version", "sources"],
"properties": {
"schema_version": {"const": "aidefend.context-corpus-manifest.v1"},
"manifest_version": {"type": "string", "minLength": 1, "maxLength": 128},
"sources": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"source_id", "relative_path", "owner", "trust_tier",
"criticality", "reviewed_at", "expires_at"
],
"properties": {
"source_id": {"type": "string", "minLength": 1, "maxLength": 128},
"relative_path": {"type": "string", "minLength": 1, "maxLength": 512},
"owner": {"type": "string", "minLength": 1, "maxLength": 128},
"trust_tier": {"enum": ["verified", "reviewed", "untrusted"]},
"criticality": {"enum": ["low", "moderate", "high", "critical"]},
"reviewed_at": {"type": "string", "format": "date-time"},
"expires_at": {"type": "string", "format": "date-time"}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}Step 2: Reconcile manifest and real corpus population
# File: scripts/validate_context_manifest.py
from __future__ import annotations
import argparse
import hashlib
import json
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
import jsonschema
def unique_object(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
value: dict[str, Any] = {}
for key, item in pairs:
if key in value:
raise ValueError(f"duplicate JSON key: {key}")
value[key] = item
return value
def load_json(path: Path) -> tuple[Any, bytes]:
payload = path.read_bytes()
value = json.loads(
payload.decode("utf-8", errors="strict"),
object_pairs_hook=unique_object,
parse_constant=lambda token: (_ for _ in ()).throw(ValueError(f"non-finite JSON number: {token}")),
)
return value, payload
def parse_utc(value: str) -> datetime:
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
if parsed.tzinfo is None:
raise ValueError("freshness timestamps must include a timezone")
return parsed.astimezone(timezone.utc)
def validate(schema_path: Path, manifest_path: Path, corpus_root: Path) -> dict[str, Any]:
schema, _ = load_json(schema_path)
manifest, manifest_bytes = load_json(manifest_path)
jsonschema.Draft202012Validator(
schema, format_checker=jsonschema.FormatChecker()
).validate(manifest)
source_ids: set[str] = set()
expected_paths: set[str] = set()
expired: list[str] = []
now = datetime.now(timezone.utc)
for source in manifest["sources"]:
source_id = source["source_id"]
if source_id in source_ids:
raise ValueError(f"duplicate source_id: {source_id}")
source_ids.add(source_id)
relative = source["relative_path"]
path = Path(relative)
if (
path.is_absolute() or ".." in path.parts
or path.as_posix() != relative or relative in expected_paths
):
raise ValueError(f"unsafe or duplicate relative_path: {relative}")
expected_paths.add(relative)
reviewed = parse_utc(source["reviewed_at"])
expires = parse_utc(source["expires_at"])
if expires <= reviewed:
raise ValueError(f"expires_at is not after reviewed_at: {source_id}")
if expires <= now:
expired.append(source_id)
root = corpus_root.resolve(strict=True)
actual_paths: set[str] = set()
for candidate in root.rglob("*"):
if candidate.is_symlink():
raise ValueError(f"corpus contains a symlink: {candidate}")
if candidate.is_file():
relative = candidate.relative_to(root).as_posix()
if relative in actual_paths:
raise ValueError(f"duplicate corpus member: {relative}")
actual_paths.add(relative)
elif not candidate.is_dir():
raise ValueError(f"corpus contains a non-regular member: {candidate}")
missing = sorted(expected_paths - actual_paths)
unlisted = sorted(actual_paths - expected_paths)
outcome = "PASS"
if missing or unlisted or expired:
outcome = "FAIL"
return {
"schema_version": "aidefend.context-corpus-inventory-result.v1",
"manifest_version": manifest["manifest_version"],
"manifest_sha256": hashlib.sha256(manifest_bytes).hexdigest(),
"manifest_source_count": len(expected_paths),
"corpus_file_count": len(actual_paths),
"missing_paths": missing,
"unlisted_paths": unlisted,
"expired_source_ids": sorted(expired),
"outcome": outcome,
}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--schema", type=Path, required=True)
parser.add_argument("--manifest", type=Path, required=True)
parser.add_argument("--corpus-root", type=Path, required=True)
parser.add_argument("--report", type=Path, required=True)
args = parser.parse_args()
report = validate(args.schema, args.manifest, args.corpus_root)
args.report.parent.mkdir(parents=True, exist_ok=True)
args.report.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8")
return 0 if report["outcome"] == "PASS" else 1
if __name__ == "__main__":
raise SystemExit(main())Step 3: Gate merge and indexing
python scripts/validate_context_manifest.py --schema schemas/context-corpus.schema.json --manifest context/sources.json --corpus-root context/documents --report evidence/context-corpus-inventory.jsonRun the same command in pull-request CI and immediately before indexing. Missing, expired, unlisted, duplicate, linked, or non-regular content blocks the gate. The indexer must consume the same corpus-root snapshot and manifest digest recorded by the PASS report; otherwise the result is stale rather than transferable.
AID-H-021.003-G002
Concept
Freshness is defined and evaluated at source/configuration release time here. This control publishes a signed eligibility state; it does not block live retrieval. AID-H-020.004 consumes the state and owns runtime fail-closed enforcement.
Build a complete freshness eligibility report
# File: context_governance/check_source_freshness.py
from __future__ import annotations
import hashlib
import json
from datetime import datetime, timezone
from pathlib import Path
def parse_time(value: str) -> datetime:
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
if parsed.utcoffset() is None:
raise ValueError("timestamp lacks timezone")
return parsed.astimezone(timezone.utc)
def evaluate(manifest_path: Path, governed_root: Path, now: datetime) -> dict:
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
entries = manifest.get("sources")
if not isinstance(entries, list) or not entries:
return {"status": "INSUFFICIENT_DATA", "reason": "source manifest is empty"}
source_ids: set[str] = set()
results: list[dict] = []
for entry in entries:
required = {
"source_id", "relative_path", "owner", "trust_tier",
"criticality", "reviewed_at", "expires_at",
}
if not isinstance(entry, dict) or set(entry) != required:
raise ValueError("source entry schema mismatch")
if entry["source_id"] in source_ids:
raise ValueError("duplicate source_id")
source_ids.add(entry["source_id"])
path = (governed_root / entry["relative_path"]).resolve()
if governed_root.resolve() not in path.parents:
raise ValueError("source path escapes governed root")
present = path.is_file()
reviewed = parse_time(entry["reviewed_at"])
expires = parse_time(entry["expires_at"])
current = present and reviewed <= now < expires
results.append({
"source_id": entry["source_id"],
"present": present,
"current": current,
"content_sha256": (
hashlib.sha256(path.read_bytes()).hexdigest() if present else None
),
"expires_at": entry["expires_at"],
})
status = "PASS" if all(item["current"] for item in results) else "FAIL"
return {
"schema_version": "aidefend.context-source-eligibility.v1",
"status": status,
"manifest_sha256": hashlib.sha256(manifest_path.read_bytes()).hexdigest(),
"evaluated_at": now.isoformat(),
"source_count": len(results),
"results": results,
}
Evidence and handoff
Run the checker on every context-source/configuration change and before publishing a trusted context release. Sign the complete report and source manifest under the approved CI identity. Missing sources, malformed timestamps, duplicate IDs, or incomplete populations cannot produce PASS. H-020.004 independently verifies the signed bytes and current time before live context assembly.
Action: Publish the signed source manifest and freshness report as governance artifacts; do not implement a retrieval deny path in this sub-technique.
AID-H-021.003-G003
Concept
Conflicting runbooks create nondeterministic agent behavior. Conflict detection must happen before embeddings or retrieval ranking, with a deterministic precedence policy that picks one authoritative statement and quarantines the rest.
Step 1: Represent policy claims explicitly in document metadata
# File: docs/refund-policy.md.meta.yaml
doc_id: DOC-SUPPORT-REFUND
policy_claims:
- key: refund.max_without_human_approval
value: "100"
precedence: 80
- key: refund.allowed_channels
value: "support_portal_only"
precedence: 80
Step 2: Block equal-precedence conflicting claims
# File: scripts/detect_context_conflicts.py
from __future__ import annotations
from collections import defaultdict
import hashlib
import json
from pathlib import Path
import yaml
claims_by_key: dict[str, list[tuple[int, str, str]]] = defaultdict(list)
source_digests: dict[str, str] = {}
for meta_file in Path("docs").rglob("*.meta.yaml"):
raw = meta_file.read_bytes()
if len(raw) > 1_000_000:
raise SystemExit(f"metadata file exceeds policy limit: {meta_file}")
meta = yaml.safe_load(raw.decode("utf-8", errors="strict"))
if not isinstance(meta, dict) or set(meta) != {"doc_id", "policy_claims"}:
raise SystemExit(f"metadata schema mismatch: {meta_file}")
doc_id = meta["doc_id"]
if not isinstance(doc_id, str) or not doc_id:
raise SystemExit(f"invalid doc_id: {meta_file}")
source_digests[doc_id] = hashlib.sha256(raw).hexdigest()
for claim in meta.get("policy_claims", []):
if not isinstance(claim, dict) or set(claim) != {"key", "value", "precedence"}:
raise SystemExit(f"claim schema mismatch: {meta_file}")
if isinstance(claim["precedence"], bool) or not isinstance(claim["precedence"], int):
raise SystemExit(f"claim precedence must be an integer: {meta_file}")
claims_by_key[str(claim["key"])].append(
(claim["precedence"], str(claim["value"]), doc_id)
)
errors: list[str] = []
selected: dict[str, dict] = {}
for key, rows in claims_by_key.items():
highest = max(rows, key=lambda row: row[0])[0]
top_rows = [row for row in rows if row[0] == highest]
distinct_values = {row[1] for row in top_rows}
if len(distinct_values) > 1:
errors.append(f"{key}: conflicting values at precedence {highest}: {top_rows}")
else:
selected[key] = {
"value": top_rows[0][1],
"precedence": highest,
"source_doc_ids": sorted({row[2] for row in top_rows}),
}
report = {
"schema_version": "aidefend.context-precedence.v1",
"status": "FAIL" if errors else "PASS",
"claim_key_count": len(claims_by_key),
"selected_claims": selected,
"source_metadata_sha256": dict(sorted(source_digests.items())),
"conflicts": errors,
}
Path("context").mkdir(exist_ok=True)
Path("context/precedence.json").write_text(
json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
if errors:
raise SystemExit("context conflict gate failed:\n" + "\n".join(errors))
print("context conflict gate passed")
Step 3: Quarantine unresolved conflicts from retrieval indexes
If a conflict is detected, prevent all affected documents from being promoted into the trusted retrieval namespace until owner teams resolve and re-approve the precedence outcome.
Verification: Retain the complete claim population, source digests, precedence-policy digest, conflicts, and selected authoritative claim; independently replay the same inputs and require the same result before release.
Action: Make conflict detection a required pre-ingestion gate and enforce one authoritative claim per key at highest precedence.
AID-H-021.003-G004
Concept
Sign the source/configuration governance state, not a second copy of the RAG chunk-integrity manifest. The signed artifact declares which sources, owners, trust tiers, precedence rules, freshness states, and release versions are approved. H-020.004 verifies and enforces it at retrieval time; H-020.001 separately verifies chunk and embedding bytes.
Create and sign the governance release manifest
# File: context_governance/build_release_manifest.py
from __future__ import annotations
import hashlib
import json
import math
import os
import subprocess
from pathlib import Path
SOURCES = Path("context/sources.json")
FRESHNESS = Path("artifacts/context/freshness.json")
PRECEDENCE = Path("context/precedence.json")
OUTPUT = Path("artifacts/context/context_release_manifest.json")
SIGNATURE = OUTPUT.with_suffix(".sig")
SIGN_TIMEOUT_SECONDS = float(os.environ["VERIFIED_CONTEXT_GOVERNANCE_SIGN_TIMEOUT_SECONDS"])
VERIFY_TIMEOUT_SECONDS = float(os.environ["VERIFIED_CONTEXT_GOVERNANCE_VERIFY_TIMEOUT_SECONDS"])
if any(
not math.isfinite(value) or value <= 0
for value in (SIGN_TIMEOUT_SECONDS, VERIFY_TIMEOUT_SECONDS)
):
raise RuntimeError("verified context-governance signing timeouts are invalid")
def sha256_file(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def canonical(value: dict) -> bytes:
return (json.dumps(
value, sort_keys=True, separators=(",", ":"), allow_nan=False
) + "\n").encode("utf-8")
sources = json.loads(SOURCES.read_text(encoding="utf-8"))
freshness = json.loads(FRESHNESS.read_text(encoding="utf-8"))
precedence = json.loads(PRECEDENCE.read_text(encoding="utf-8"))
if (not isinstance(sources, dict)
or set(sources) != {"schema_version", "manifest_version", "sources"}
or sources["schema_version"] != "aidefend.context-corpus-manifest.v1"
or not isinstance(sources["manifest_version"], str)
or not 1 <= len(sources["manifest_version"]) <= 128
or not isinstance(sources["sources"], list) or not sources["sources"]):
raise SystemExit("ERROR: context source manifest schema mismatch")
if freshness.get("status") != "PASS":
raise SystemExit("FAIL: context source eligibility did not pass")
if precedence.get("status") != "PASS":
raise SystemExit("FAIL: context precedence gate did not pass")
if freshness.get("manifest_sha256") != sha256_file(SOURCES):
raise SystemExit("ERROR: freshness report is bound to different source bytes")
source_ids = [item.get("source_id") for item in sources["sources"]]
fresh_ids = [item.get("source_id") for item in freshness.get("results", [])]
if source_ids != fresh_ids or source_ids != sorted(set(source_ids)):
raise SystemExit("ERROR: source population differs across governance artifacts")
release_id = os.environ["CONTEXT_RELEASE_ID"]
if not release_id or len(release_id) > 128:
raise SystemExit("ERROR: invalid context release ID")
manifest = {
"schema_version": "aidefend.context-governance-release.v1",
"release_id": release_id,
"sources_sha256": sha256_file(SOURCES),
"freshness_report_sha256": sha256_file(FRESHNESS),
"precedence_policy_sha256": sha256_file(PRECEDENCE),
"source_count": freshness["source_count"],
"source_states": [
{
"source_id": item["source_id"],
"content_sha256": item["content_sha256"],
"expires_at": item["expires_at"],
}
for item in sorted(freshness["results"], key=lambda row: row["source_id"])
],
}
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
OUTPUT.write_bytes(canonical(manifest))
subprocess.run([
"cosign", "sign-blob", "--yes",
"--key", "env://CONTEXT_GOVERNANCE_SIGNING_KEY",
"--bundle", str(SIGNATURE), str(OUTPUT),
], check=True, timeout=SIGN_TIMEOUT_SECONDS)
subprocess.run([
"cosign", "verify-blob", "--key", os.environ["CONTEXT_GOVERNANCE_VERIFY_KEY"],
"--bundle", str(SIGNATURE), str(OUTPUT),
], check=True, capture_output=True, text=True, timeout=VERIFY_TIMEOUT_SECONDS)
Independent verification
A release-independent identity verifies the signature, recomputes all three source artifact digests and the complete source-state population, and confirms that no source is missing, duplicated, or expired at release time. Retain the manifest/signature, freshness report/signature, precedence policy, source bytes, CI identity, and replay result. Runtime retrieval denial and audit events remain in H-020.004.
Action: Publish one immutable governance release manifest per approved context release and expose its exact digest to the RAG enforcement plane.
AID-H-021.003-G005
Concept
When code changes but corresponding operational context stays stale, agents can make unsafe decisions from outdated instructions. Add a deterministic code-doc drift gate to CI so high-impact code paths require synchronized context updates.
Step 1: Maintain explicit path-to-doc ownership mapping
# File: context/code_doc_traceability.yaml
mappings:
- code_path_prefix: "agent/tools/refund/"
required_doc_ids: ["DOC-SUPPORT-REFUND", "DOC-ESCALATION-POLICY"]
- code_path_prefix: "agent/connectors/email/"
required_doc_ids: ["DOC-OUTBOUND-COMMS"]
Step 2: Block PRs when mapped code changes without required document updates
# File: scripts/check_code_doc_drift.py
from __future__ import annotations
import hashlib
import json
from pathlib import Path
MAPPING_FIELDS = {"code_path_prefix", "required_doc_ids"}
META_FIELDS = {"doc_id", "content_sha256", "reviewed_by", "review_ticket"}
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def evaluate(changed_files: set[str], trace: dict, docs_root: Path) -> dict:
if not isinstance(changed_files, set) or any(
not isinstance(path, str) or not path for path in changed_files
):
return {"status": "ERROR", "reason": "changed_file_population_invalid"}
if not isinstance(trace, dict) or set(trace) != {"mappings"}:
return {"status": "ERROR", "reason": "traceability_schema_mismatch"}
mappings = trace["mappings"]
if not isinstance(mappings, list) or not mappings:
return {"status": "INSUFFICIENT_DATA", "reason": "traceability_mapping_empty"}
required_doc_ids: set[str] = set()
for mapping in mappings:
if not isinstance(mapping, dict) or set(mapping) != MAPPING_FIELDS:
return {"status": "ERROR", "reason": "traceability_entry_schema_mismatch"}
prefix = mapping["code_path_prefix"]
doc_ids = mapping["required_doc_ids"]
if not isinstance(prefix, str) or not prefix or not isinstance(doc_ids, list) or not doc_ids:
return {"status": "ERROR", "reason": "traceability_entry_invalid"}
if any(not isinstance(doc_id, str) or not doc_id for doc_id in doc_ids):
return {"status": "ERROR", "reason": "traceability_doc_id_invalid"}
if any(path.startswith(prefix) for path in changed_files):
required_doc_ids.update(doc_ids)
if not required_doc_ids:
return {"status": "NOT_APPLICABLE", "reason": "no_mapped_code_path_changed"}
findings: list[dict] = []
verified_docs: list[dict] = []
for doc_id in sorted(required_doc_ids):
relative_doc = f"docs/{doc_id}.md"
relative_meta = f"docs/{doc_id}.meta.json"
if relative_doc not in changed_files or relative_meta not in changed_files:
findings.append({"doc_id": doc_id, "reason": "document_and_review_metadata_must_both_change"})
continue
doc_path = docs_root / f"{doc_id}.md"
meta_path = docs_root / f"{doc_id}.meta.json"
try:
meta = json.loads(meta_path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
findings.append({"doc_id": doc_id, "reason": type(exc).__name__})
continue
if not isinstance(meta, dict) or set(meta) != META_FIELDS or meta["doc_id"] != doc_id:
findings.append({"doc_id": doc_id, "reason": "review_metadata_schema_mismatch"})
continue
reviewers = meta["reviewed_by"]
if not isinstance(reviewers, list) or not reviewers or any(
not isinstance(reviewer, str) or not reviewer for reviewer in reviewers
):
findings.append({"doc_id": doc_id, "reason": "reviewer_evidence_missing"})
continue
if not isinstance(meta["review_ticket"], str) or not meta["review_ticket"]:
findings.append({"doc_id": doc_id, "reason": "review_ticket_missing"})
continue
actual_digest = sha256(doc_path)
if meta["content_sha256"] != actual_digest:
findings.append({"doc_id": doc_id, "reason": "document_digest_mismatch"})
continue
verified_docs.append({"doc_id": doc_id, "content_sha256": actual_digest})
return {
"schema_version": "aidefend.h021003-code-doc-drift.v1",
"status": "FAIL" if findings else "PASS",
"required_doc_ids": sorted(required_doc_ids),
"verified_docs": verified_docs,
"findings": findings,
}
Step 3: Enforce in protected branch checks
Supply changed_files from an authenticated base/head commit comparison, and supply trace from a strict-schema, signature-verified traceability release. Make this gate required on protected branches. The check requires both changed document bytes and review metadata bound to the new content digest; touching a file or metadata alone cannot pass. Any emergency exception must be a signed, expiring policy object evaluated and retained with the release receipt.
Action: Prevent behavior-changing code from being released unless every mapped high-impact document has materially changed bytes, digest-bound review evidence, and an independently replayed PASS receipt.
Open-source tools
- Git
- Open Policy Agent (OPA)
- Conftest
- Cosign
- in-toto
- Semgrep
Commercial / hosted tools
- GitHub Enterprise Cloud
- GitLab Premium
- GitLab Ultimate
- AWS Key Management Service (AWS KMS)
- Google Cloud Key Management Service
- Azure Key Vault
- HashiCorp Vault Enterprise
- HCP Vault Dedicated
- Splunk (governance evidence only; not release enforcement)
- Datadog (governance evidence only; not release enforcement)
Threat mappings
MITRE ATLAS
- AML.T0099 AI Agent Tool Data Poisoning
- AML.T0070 RAG Poisoning
- AML.T0071 False RAG Entry Injection
- AML.T0059 Erode Dataset Integrity
- AML.T0081 Modify AI Agent Configuration
MAESTRO
- Compromised RAG Pipelines (L2)
- Data Tampering (L2)
- Supply Chain Attacks (Cross-Layer)
OWASP LLM Top 10 2026
- LLM05:2026 Data and Model Poisoning (signed source governance supplies trusted context-release evidence to retrieval enforcement but does not itself admit each retrieved chunk)
- LLM07:2026 Misinformation (owned and freshness-governed context sources support grounded answers but do not independently verify every generated claim)
OWASP ML Top 10 2023
- ML06:2023 AI Supply Chain Attacks (context corpus updates from third-party connectors require governance gates)
OWASP Top 10 for Agentic Applications 2026
- ASI06:2026 Memory & Context Poisoning
- ASI04:2026 Agentic Supply Chain Vulnerabilities
NIST Adversarial Machine Learning 2025
- N/A
Cisco Integrated AI Security and Safety Framework
- AISubtech-6.1.1 Knowledge Base Poisoning
- AITech-7.3 Data Source Abuse and Manipulation
Google Secure AI Framework 2.0 - Risks
- IIC: Insecure Integrated Component (documentation and tool-spec corpus is an integrated component requiring integrity controls)
- MDT: Model Deployment Tampering (signed critical corpus manifests detect unauthorized deployment-stage context changes)
Databricks AI Security Framework 3.0
- Agents - Core 13.1: Memory Poisoning
- Raw Data 1.7: Lack of data trustworthiness
- Raw Data 1.11: Compromised 3rd-party datasets