Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,30 @@ jobs:
with:
python-version: "3.12"

- name: Install dependencies
run: python -m pip install --upgrade pip setuptools && pip install -e ".[dev]" "agent-governance-toolkit[full]>=4.1"
- name: Install dependencies
run: python -m pip install --upgrade pip setuptools && pip install -e ".[dev]"

# AGT 4.1 currently constrains cryptography below 49, while the runtime
# requires 50+ for published security fixes. Keep the scanner isolated
# so its tooling constraints cannot downgrade the package under test,
# then override that stale upper bound inside the ephemeral scanner too.
- name: Install governance tooling in an isolated environment
run: |
python -m venv .agt-venv
.agt-venv/bin/pip install "agent-governance-toolkit[full]>=4.1"
.agt-venv/bin/pip install --upgrade --no-deps "cryptography>=50.0"

- name: Generate evidence file
run: python scripts/gen_agt_evidence.py

# Blocking gate: the [full] toolkit provides the ASI coverage modules
# (10/10) and the evidence declares cA2A's governed capabilities, so strict
# verify is COMPLETE. A regression that drops coverage or governance fails CI.
- name: AGT governance verify (strict)
run: agt verify --evidence agt-evidence.json
- name: AGT governance verify (strict)
run: .agt-venv/bin/agt verify --evidence agt-evidence.json

- name: Save attestation JSON
run: agt --json verify --evidence agt-evidence.json > agt-attestation.json
- name: Save attestation JSON
run: .agt-venv/bin/agt --json verify --evidence agt-evidence.json > agt-attestation.json

- name: Upload governance artifacts
uses: actions/upload-artifact@v7
Expand Down
18 changes: 14 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,27 @@ jobs:
with:
python-version: "3.12"

- name: Install package and AGT
run: python -m pip install --upgrade pip && pip install -e "." "agent-governance-toolkit[full]>=4.1"
- name: Install package
run: python -m pip install --upgrade pip && pip install -e "."

# Isolate AGT's tooling dependencies from the release artifact. AGT 4.1
# constrains cryptography below 49; cA2A requires 50+ security fixes. The
# ephemeral scanner is upgraded too so the release gate runs no known-
# vulnerable cryptography build while that upstream bound is stale.
- name: Install governance tooling in an isolated environment
run: |
python -m venv .agt-venv
.agt-venv/bin/pip install "agent-governance-toolkit[full]>=4.1"
.agt-venv/bin/pip install --upgrade --no-deps "cryptography>=50.0"

- name: Generate evidence file
run: python scripts/gen_agt_evidence.py

- name: AGT governance verify (strict)
run: agt verify --evidence agt-evidence.json
run: .agt-venv/bin/agt verify --evidence agt-evidence.json

- name: Save attestation JSON
run: agt --json verify --evidence agt-evidence.json > agt-attestation.json
run: .agt-venv/bin/agt --json verify --evidence agt-evidence.json > agt-attestation.json

- name: Attach evidence to release
if: github.event_name == 'release'
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
version and `latest` tags, keyless signing, and provenance attestation. All
third-party container actions are pinned to immutable commits.

- Raised dependency floors past newly disclosed vulnerable releases:
`cryptography>=50.0` (PYSEC-2026-3552/3553/3554), `aiohttp>=3.14.3`
(PYSEC-2026-3545/3546/3547) for the A2A SDK extra, and
`pymdown-extensions>=11.0.1` (PYSEC-2026-3654) for documentation builds.
- Isolated the AGT governance CLI in its own virtual environment. AGT 4.1
constrains `cryptography<49`, so installing it alongside cA2A could either
downgrade the runtime below the security floor or make releases unresolvable.
The ephemeral AGT environment also overrides that stale upper bound with
`cryptography>=50.0`; the strict verification path is tested against it.

- **A delegation chain was a bearer credential: any party holding a copy was granted the leaf's authority.** The inbound path verified signatures, continuity, attenuation, depth and replay, then granted, without ever requiring the caller to demonstrate a relationship to the chain it presented. `PeerRequest` had no field that could carry such a proof, and `subject` — an Ed25519 public key — was only ever compared as a string for continuity, never used as a key.

Chains are published deliberately: handed to auditors for offline verification, embedded in provenance DAGs, and shipped in `examples/`. So the credential intended for publication was the credential that granted authority. A chain lifted from any of those and replayed verbatim was accepted, and the provenance record emitted afterwards named the legitimate subject, so the audit trail attributed the call to the wrong party. Nothing was forged, so nothing failed a check and nothing anomalous reached a log; verbatim replay leaves no tamper evidence to find. `CREDENTIAL_REPLAY` does not cover it, catching only a duplicate `credential_id` inside one chain rather than replay of a whole valid chain by a different party.
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ classifiers = [
]
requires-python = ">=3.11"
dependencies = [
"cryptography>=42.0",
"cryptography>=50.0",
"pyyaml>=6.0",
"cedarpy==4.8.7",
# TRACE record models + RFC 8785 signing, reused rather than reimplemented
Expand All @@ -48,6 +48,7 @@ tpm = [
# the base install stays dependency-light.
a2a-sdk = [
"a2a-sdk>=1.1,<2",
"aiohttp>=3.14.3",
]
dev = [
"pytest>=8.0",
Expand All @@ -63,6 +64,7 @@ dev = [
# So tests/unit/test_a2a_sdk_bridge.py runs in CI rather than skipping. A
# bridge whose tests only ever skip is a bridge nobody has exercised.
"a2a-sdk>=1.1,<2",
"aiohttp>=3.14.3",
]

[project.scripts]
Expand Down
2 changes: 1 addition & 1 deletion requirements-docs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ mkdocs>=1.6.1
mkdocs-material>=9.7.7
mkdocs-minify-plugin>=0.8
mkdocs-llmstxt>=0.5,<1.0
pymdown-extensions>=10.21.3
pymdown-extensions>=11.0.1
mkdocstrings[python]>=1.0.6
griffe>=2.1.0
36 changes: 36 additions & 0 deletions tests/unit/test_dependency_security_floors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Keep dependency floors above versions with known release-blocking advisories."""

from __future__ import annotations

import tomllib
from pathlib import Path


def _project() -> dict:
with Path("pyproject.toml").open("rb") as stream:
return tomllib.load(stream)["project"]


def test_runtime_cryptography_floor_includes_2026_security_fixes() -> None:
assert "cryptography>=50.0" in _project()["dependencies"]


def test_a2a_sdk_extra_cannot_resolve_vulnerable_aiohttp() -> None:
extras = _project()["optional-dependencies"]
assert "aiohttp>=3.14.3" in extras["a2a-sdk"]
assert "aiohttp>=3.14.3" in extras["dev"]


def test_docs_floor_excludes_vulnerable_pymdown_extensions() -> None:
requirements = Path("requirements-docs.txt").read_text(encoding="utf-8").splitlines()
assert "pymdown-extensions>=11.0.1" in requirements


def test_governance_tooling_cannot_downgrade_runtime_dependencies() -> None:
for workflow in ("ci.yml", "release.yml"):
contents = Path(".github/workflows", workflow).read_text(encoding="utf-8")
assert "python -m venv .agt-venv" in contents
assert '.agt-venv/bin/pip install "agent-governance-toolkit[full]>=4.1"' in contents
assert '.agt-venv/bin/pip install --upgrade --no-deps "cryptography>=50.0"' in contents
assert 'pip install -e ".[dev]" "agent-governance-toolkit' not in contents
assert 'pip install -e "." "agent-governance-toolkit' not in contents