Skip to content

Commit da02027

Browse files
authored
Set the ACS-Core floor: MODIFY and system/ping to SHOULD, Wrapped MCP and subagentStart as conditional MUSTs (#21)
Closes #132 Signed-off-by: rocklambros <rock@rockcyber.com> Signed-off-by: Bar Kaduri <bar@capsule.security>
1 parent 60acee3 commit da02027

12 files changed

Lines changed: 99 additions & 24 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Changelog
2+
3+
All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) once it reaches 1.0.0. Pre-1.0 releases MAY change the ACS-Core baseline in patch versions; the wire format version (`acs_version` in the handshake) evolves separately in the `specification/` directory.
4+
5+
## [0.1.3] — 2026-09-09
6+
7+
### Changed — ACS-Core baseline
8+
9+
- `MODIFY` is now SHOULD-support rather than MUST-support. Deployments whose framework cannot mutate a request (shell-hook integrations, IDE plugins without an argument-mutation surface) or that disable `MODIFY` for auditability reasons are conformant without it. See new [§6.5 MODIFY-incapable clients](docs/spec/instrument/specification.md#65-modify-incapable-clients-normative).
10+
- `subagentStart` is promoted from SHOULD-emit to MUST-emit for subagent-capable frameworks; `subagentStop` remains SHOULD-emit, unchanged since 0.1.0. A client whose framework has no sub-agent abstraction has nothing to emit; the Guardian determines client subagent-emission capability by deployment-defined means (mirroring the [§9.2 ASK precedent](docs/spec/instrument/specification.md#92-approver-incapable-clients-normative)).
11+
- `system/ping` is now SHOULD-implement rather than MUST-implement, provided the deployment declares an alternative liveness mechanism (transport-level keepalive on HTTP; process supervision or heartbeat on stdio; continuous observed hook traffic). Omitting `system/ping` without a declared alternative is non-conformant.
12+
- Wrapped MCP (`protocols/MCP/*`) MUST be implemented by deployments whose sessions involve MCP at any point, and MAY be omitted by deployments whose sessions never involve MCP. MCP `tools/call` MAY flow through the generic tool hooks when tool-level policy suffices; the requirement exists for the surfaces the generic hooks cannot see (`initialize`, `prompts/get`, `resources/read`, `notifications/*`). Mid-session MCP addition under a no-MCP handshake is a documented v0.1 limitation (no renegotiation; wrapped coverage begins at the next session), not a prohibition — see [Conformance › ACS-Core](docs/spec/conformance.md#acs-core-mandatory-baseline).
13+
14+
### Added
15+
16+
- **§6.5 MODIFY-incapable clients (normative)** in `docs/spec/instrument/specification.md`. Defines Guardian-side substitution (`DENY` with `reason_codes: ["modify_unsupported"]` + audit event) and client-side fallback (a client receiving an unapplicable `MODIFY` MUST treat it as `DENY` + audit event), with an explicit exemption for `postCompact`, where `DENY` is not a legal disposition (the Guardian returns `ALLOW` + audit event there).
17+
- Audit-event mandate in **§9.2** (approver-incapable clients): the Guardian MUST record the ASK-substitution as an audit event, so the substitution rate is machine-detectable rather than only reachable by grepping log prose.
18+
- Guardian handling of an omitted `subagentStop.final_chain_hash` specified in **§8.6**: omission means "chain not maintained by this framework," never an integrity failure.
19+
20+
### Changed — normative force harmonization
21+
22+
- **§6.3** (malformed MODIFY): `SHOULD record an audit event` → `MUST record an audit event`. All fallback / substitution rules now use consistent MUST-audit language across §6.3, §6.4, §6.5, and §9.2.
23+
- **§6.4** now names the §6.5 substitution as the one conformant deviation from verdict application, instead of contradicting it.
24+
- **§13** opens with the SHOULD it links from, instead of calling a liveness method required.
25+
26+
### Changed — schema
27+
28+
- `specification/v0.1.0/hooks/subagent-stop.json`: `final_chain_hash` moved from `required` to optional. Frameworks that maintain no session-chain (shell-hook integrations without an internal audit chain) MAY omit the field rather than fabricate a value; fabrication would corrupt the exact artifact the field exists to produce. Guardian handling of the omission lives in §8.6.
29+
30+
### Repository
31+
32+
- Commits land under human authorship ([#61](https://github.com/GenAI-Security-Project/agent-control-standard/pull/61)).
33+
34+
### Related issues
35+
36+
- Guardian-side hook-coverage unfalsifiability tracked at [#31](https://github.com/GenAI-Security-Project/agent-control-standard/issues/31); out of scope for this release, needed for the enforcement side of `subagentStart`'s security rationale to be checkable.
37+
38+
## [0.1.2] — 2026-09-09
39+
40+
- The landing page, MkDocs documentation, and all 44 schema URIs are published from this repository via GitHub Pages on every merge to `main`; the deploy fails on any unresolved `$id` or `$ref`, and a monitor rechecks every published URI every six hours.
41+
- The schema namespace moved onto a project-controlled base URI, and every schema is required to live at the path its `$id` declares.
42+
- The response envelope can carry a ServerHello ([#59](https://github.com/GenAI-Security-Project/agent-control-standard/pull/59)).
43+
- The skill lifecycle hooks (`skillRegister`, `skillLoad`, `skillUnload`) joined the Specification §5 taxonomy table, with a guard test that reads the schema titles so the views cannot drift again ([#56](https://github.com/GenAI-Security-Project/agent-control-standard/pull/56)).
44+
- The Identity for Agents workstream overview and standards survey landed, with identity woven into the core concepts.
45+
- A third-party content guard protects the published site, with its residual gaps recorded.
46+
- Governance reconciliation: `GOVERNANCE.md` as the authoritative roster, OWASP Nest project metadata, and the single-contact policy.
47+
48+
## [0.1.1] — 2026-08-11
49+
50+
- Relicensed: Apache 2.0 for code and schemas, CC BY-SA 4.0 for prose documentation. Everything through v0.1.0 remains MIT.
51+
- Repository and documentation URLs moved to `GenAI-Security-Project/agent-control-standard` and the current domain.
52+
- Repository security posture and CI supply chain hardened.
53+
- Python floor raised to unblock Dependabot security updates.
54+
- Release version decoupled from the specification version: `version.txt` and `pyproject.toml` carry the release, while schema `$id` URIs keep the spec version (`v0.1.0`).
55+
56+
## [0.1.0] — 2026-06-05
57+
58+
- Initial canonical v0.1.0 spec integrated (see [#2](https://github.com/GenAI-Security-Project/agent-control-standard/pull/2)).

‎LICENSING.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Copyright 2025-2026 The OWASP GenAI Security Project and the ACS contributors.
1818
| `overrides/**` | CC BY-SA 4.0 | `CC-BY-SA-4.0` |
1919
| `design/**` | CC BY-SA 4.0 | `CC-BY-SA-4.0` |
2020
| `landing/assets/fonts/**` | SIL Open Font License 1.1 | `OFL-1.1` |
21+
| `CHANGELOG.md` | CC BY-SA 4.0 | `CC-BY-SA-4.0` |
2122
| `reference-implementations/agt/policy/lib/**` | MIT License, Copyright (c) Microsoft Corporation | `MIT` |
2223
| Everything else, including any new top-level directory | Apache License 2.0 | `Apache-2.0` |
2324

‎docs/acs.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ flowchart LR
2222

2323
## What v0.1.0 ships
2424

25-
- **ACS-Core** (mandatory baseline) — capability-negotiation handshake, JSON-RPC envelope, 16 native lifecycle hooks (`sessionStart`/`End`, `agentTrigger`, `userMessage`, `agentResponse`, `turnStart`/`End`, `toolCallRequest`/`Result`, `knowledgeRetrieval`, `memoryContextRetrieval`, `memoryStore`, `preCompact`/`postCompact`, `subagentStart`/`Stop`), wrapped MCP, five dispositions (`allow`, `deny`, `modify`, `ask`, `defer`), SessionContext with rolling SHA-256 chain hash, optional Intent with immutability rule, replay protection, and `system/ping` liveness.
25+
- **ACS-Core** (mandatory baseline) — capability-negotiation handshake, JSON-RPC envelope, minimum hook set (`sessionStart`, `userMessage` or `agentTrigger`, `toolCallRequest`/`Result`, `agentResponse`, `sessionEnd`, `subagentStart` for subagent-capable frameworks), four MUST-support dispositions (`allow`, `deny`, `ask`, `defer`) with `modify` SHOULD-support, SessionContext with rolling SHA-256 chain hash, optional Intent with immutability rule, replay protection, baseline HMAC-SHA256 signature, decision honoring, declared liveness mechanism (`system/ping` or a transport-level alternative), and Wrapped MCP when sessions involve MCP. Additional hooks (`turnStart`/`End`, `preCompact`/`postCompact`, `subagentStop`, `knowledgeRetrieval`, `memoryContextRetrieval`, `memoryStore`, `skillRegister`/`Load`/`Unload`) are normatively defined and SHOULD be implemented when the harness can observe the corresponding event.
2626
- **ACS-Trace** profile — OpenTelemetry semconv mapping + OCSF event-class mapping, with decisions emitted as span events on the parent step span.
2727
- **ACS-Inspect** / **ACS-Inspect-Dynamic** profiles — canonical AgBOM with `agbom/snapshot` and `agbom/changed`, deterministic CycloneDX / SPDX / SWID derivations.
2828
- **ACS-Provenance** profile — field-level `Provenance` objects with `origin`, `source_id`, `derived_from`, and an OPTIONAL wire-format `trust` enum that obeys the monotonicity rule.

‎docs/spec/conformance.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,18 @@ A v0.1.0-conformant deployment MUST implement ACS-Core. ACS-Core comprises:
2929

3030
- **Handshake** — `handshake/hello` with ClientHello/ServerHello ([Specification §4](./instrument/specification.md#4-capability-negotiation-handshake)).
3131
- **Request/response envelope** — JSON-RPC 2.0 with ACS extensions ([§3](./instrument/specification.md#3-wire-format)). `request_id`, `timestamp`, `acs_version`, `metadata` required on every request.
32-
- **Hook taxonomy** — At minimum: `sessionStart`, `userMessage` or `agentTrigger`, `toolCallRequest`, `toolCallResult`, `agentResponse`, `sessionEnd`. Additional hooks (`turnStart`/`turnEnd`, `preCompact`/`postCompact`, `subagentStart`/`subagentStop`, `knowledgeRetrieval`, `memoryContextRetrieval`, `memoryStore`, `skillRegister`/`skillLoad`/`skillUnload`) are normatively defined and SHOULD be implemented when the harness can observe the corresponding event; they are capability-negotiated via the handshake. A deployment whose AgBOM includes `skill` components SHOULD emit the skill lifecycle hooks, so a Guardian is not blind to a composition surface the inventory already exposes.
33-
- **Dispositions** — All five (ALLOW, DENY, MODIFY, ASK, DEFER) with required fields per [§6](./instrument/specification.md#6-disposition-vocabulary).
32+
- **Hook taxonomy** — At minimum: `sessionStart`, `userMessage` or `agentTrigger`, `toolCallRequest`, `toolCallResult`, `agentResponse`, `sessionEnd`, `subagentStart`. A subagent-capable client MUST emit `subagentStart` when it spawns a sub-agent; a client whose framework has no sub-agent abstraction has nothing to emit. The Guardian determines client subagent-emission capability by deployment-defined means (agent identity bound at handshake, policy keyed on `agent_id`, organizational configuration), mirroring the ASK precedent in [§9.2](./instrument/specification.md#92-approver-incapable-clients-normative). Without `subagentStart`, a Guardian is blind to cross-agent propagation (the confused-deputy attack class). `subagentStop` is SHOULD-emit (audit-only, not decision-eligible; its `final_chain_hash` field is optional for frameworks maintaining no session-chain — see [`subagent-stop.json`](https://genai-security-project.github.io/agent-control-standard/schema/v0.1.0/hooks/subagent-stop.json)). Additional hooks (`turnStart`/`turnEnd`, `preCompact`/`postCompact`, `knowledgeRetrieval`, `memoryContextRetrieval`, `memoryStore`, `skillRegister`/`skillLoad`/`skillUnload`) are normatively defined and SHOULD be implemented when the harness can observe the corresponding event; they are capability-negotiated via the handshake. A deployment whose AgBOM includes `skill` components SHOULD emit the skill lifecycle hooks, so a Guardian is not blind to a composition surface the inventory already exposes.
33+
- **Dispositions** — Four MUST-support: ALLOW, DENY, ASK, DEFER, with required fields per [§6](./instrument/specification.md#6-disposition-vocabulary). MODIFY is SHOULD-support: deployments that implement MODIFY MUST follow the MODIFY composition rules ([§6.3](./instrument/specification.md#63-modify-composition-normative)); deployments that do not implement MODIFY are handled per [§6.5](./instrument/specification.md#65-modify-incapable-clients-normative) (the Guardian substitutes `DENY` with `reason_codes: ["modify_unsupported"]` and an audit event recording the substitution, determined by deployment-defined means rather than a wire declaration, mirroring the §9.2 precedent for ASK).
3434
- **SessionContext and Intent**: `session_id`, `chain_hash` (rolling SHA-256), append-only ContextEntry chain, with the Guardian publishing the chain head (`chain_hash`) on responses for content-bearing steps ([§8](./instrument/specification.md#8-sessioncontext-and-intent)). Intent is optional but normative when IBAC is the enforcement paradigm.
3535
- **Replay protection** — `request_id` (UUID) and `timestamp` on every request; Guardians MUST reject replays per [§10.3](./instrument/specification.md#103-replay-protection).
3636
- **Baseline integrity**: every request and response carries a signature over the canonical envelope ([§10](./instrument/specification.md#10-cryptographic-signatures)). `HMAC-SHA256` with an HKDF-derived per-session key from deployment-provided key material is the baseline; asymmetric and post-quantum algorithms are the ACS-Crypto profile.
3737
- **Decision honoring**: the Observed Agent MUST wait for the Guardian's decision up to the negotiated timeout and apply it; on a decision failure (timeout, transport failure, or an error without a decision) it applies the `on_decision_failure` posture (default `proceed`, fail-open) and records every fail-open proceed as an audit event ([§6.4](./instrument/specification.md#64-honoring-decisions-normative)). Handshake failure follows the deployment's startup posture ([§4.1](./instrument/specification.md#41-handshake-failure-normative)).
38-
- **Liveness** — `system/ping` ([§13](./instrument/specification.md#13-liveness-system-methods)).
39-
- **Wrapped MCP** — `protocols/MCP/*` ([Hooks](./instrument/hooks.md#protocolsmcp)).
38+
- **Liveness** — `system/ping` SHOULD be implemented: the Observed Agent declares it in `methods_implemented` and sends it, and the Guardian answers it per [§13](./instrument/specification.md#13-liveness-system-methods). A deployment MAY omit it only if the Observed Agent relies on an alternative liveness mechanism that the deployment's configuration names (for example: TCP keepalive or HTTP/2 PING on HTTP transports; process supervision or an out-of-band heartbeat on stdio; or continuous observed hook traffic where the session's own cadence acts as the probe). ACS does not put that declaration on the wire in v0.1, as [§9.2](./instrument/specification.md#92-approver-incapable-clients-normative) does not for approver capability. Omitting `system/ping` without a declared alternative is non-conformant: the chain of defaults (`startup_posture: proceed`, `on_decision_failure: proceed`, no liveness) produces silent fail-open on Guardian outage, which the Core baseline cannot allow.
39+
- **Wrapped MCP** — `protocols/MCP/*` ([Hooks](./instrument/hooks.md#protocolsmcp)) MUST be implemented by deployments whose sessions involve MCP at any point (tools, resources, prompts, notifications), so that `protocols/MCP/resources/read` — the canonical prompt-injection ingress for attacker-controlled external content — is not bypassed. MCP `tools/call` MAY instead flow through the generic `steps/toolCallRequest` / `steps/toolCallResult` hooks when tool-level policy suffices; the requirement exists for the surfaces the generic hooks cannot see (capability negotiation, prompt fetches, resource reads, notifications). Support is declared in the handshake via `wrapped_protocols`. Deployments whose sessions never involve MCP MAY omit the namespace. **Known v0.1 limitation:** `wrapped_protocols` is declared once, at handshake, and v0.1 defines no renegotiation. A session that declared no MCP and then gains an MCP server mid-session (a mutation `agbom/changed` reports, and the `acs-inspect-dynamic` profile exists to surface) cannot begin wrapping mid-session: the generic tool hooks still govern that server's tool calls, the addition is visible through `agbom/changed`, and wrapped coverage begins at the next session's handshake. Renegotiation is v0.2 scope.
4040

4141
ACS-Core does NOT require: field-level Provenance objects, Trace event emission, AgBOM, asymmetric or post-quantum signatures, or `request_hash` on ContextEntry (`request_hash` remains SHOULD). It DOES require the baseline signature (§10) and decision honoring (§6.4). ACS-Core deployments validate hook payloads against the base schemas, where `provenance` is OPTIONAL; field-level Provenance is added by the ACS-Provenance profile.
4242

43-
What "ACS-Core conformant" guarantees: the channel is authenticated and the Observed Agent honors the Guardian's decisions. It does NOT assert that a deployment's policies are strict, nor that the audit chain is tamper-evident against a compromised Guardian (that is the ACS-Crypto and ACS-Audit profiles, since the HMAC baseline is symmetric). A permissive Guardian is a conformant but permissive deployment, not a violation.
43+
What "ACS-Core conformant" guarantees: the channel is authenticated and the Observed Agent honors the Guardian's decisions on the four MUST-support dispositions (ALLOW, DENY, ASK, DEFER). Deployments that also implement MODIFY (SHOULD-support, [§6.5](./instrument/specification.md#65-modify-incapable-clients-normative)) honor it too; deployments that do not implement MODIFY receive `DENY` substitutions carrying `reason_codes: ["modify_unsupported"]` instead, except at `postCompact`, where they receive `ALLOW` and the Guardian records an audit event carrying that reason code (§6.5). A minimum-conformant deployment can therefore permit or refuse an action but cannot alter it — redaction and other content rewrites require MODIFY support. This clause does NOT assert that a deployment's policies are strict, nor that the audit chain is tamper-evident against a compromised Guardian (that is the ACS-Crypto and ACS-Audit profiles, since the HMAC baseline is symmetric). A permissive Guardian is a conformant but permissive deployment, not a violation.
4444

4545
Who verifies a conformance claim: nobody, in v0.1.0. `profiles_supported` and `profiles_accepted` are self-declaration on the wire. This release ships no conformance test suite, no registry of conformant implementations, and no steward body to arbitrate a disputed claim. A deployment that advertises "ACS-Core conformant" is asserting that about itself, and a buyer who procures on that basis is trusting the implementer rather than a third party. Test the deployment against the requirements above the way you would check any other vendor claim. A conformance suite and the governance to operate it are tracked in [issue #19](https://github.com/GenAI-Security-Project/agent-control-standard/issues/19) and scoped to a later release.
4646

@@ -95,7 +95,7 @@ Profiles compose. A deployment that wants full observability and supply-chain in
9595

9696
| Profile | What it adds | When to claim |
9797
|---|---|---|
98-
| `acs-core` | Handshake, envelope, hook taxonomy, dispositions, SessionContext + published chain head, replay protection, baseline signature (HMAC-SHA256), decision honoring, ping | Always (mandatory) |
98+
| `acs-core` | Handshake, envelope, minimum hook set (incl. `subagentStart` for subagent-capable clients), four MUST-support dispositions (ALLOW/DENY/ASK/DEFER) with MODIFY SHOULD-support (§6.5), SessionContext + published chain head, replay protection, baseline signature (HMAC-SHA256), decision honoring, declared liveness mechanism, Wrapped MCP when sessions involve MCP | Always (mandatory) |
9999
| `acs-trace` | OTel + OCSF event emission per step | Cross-vendor observability or SIEM integration |
100100
| `acs-inspect` | `agbom/snapshot` + canonical AgBOM serialization | Policy depends on component inventory |
101101
| `acs-inspect-dynamic` | `agbom/changed` on mutation | Agent hot-swaps components mid-session |

0 commit comments

Comments
 (0)