Update from code changes: A2A UNVERIFIABLE semantics + doc corrections - #248
Update from code changes: A2A UNVERIFIABLE semantics + doc corrections#248mintlify[bot] wants to merge 2 commits into
Conversation
|
Skipping PR review because a bot author is detected. If you want to trigger CodeAnt AI, comment |
QWED Security Verification Report6 files scanned | 0 blocked | 0 warnings | 15 info | 0 suppressed | 1 verified Informational Findings
Engines
Verified Files
Verified by QWED — deterministic security verification. No LLM used. |
| | `compile` | `\bcompile\s*\(` | Code compilation | | ||
| | `importlib` | `\bimportlib\s*\.` | Runtime module loading | | ||
| If either layer finds a threat, the verdict is `BLOCKED` (the reason notes which layer triggered). If both layers are clean, the verdict is `HEURISTIC_PASS` — a signed attestation that no known dangerous constructs were found, **not** a deterministic guarantee that the code is safe to execute. | ||
|
|
| | `compile` | `\bcompile\s*\(` | Code compilation | | ||
| | `importlib` | `\bimportlib\s*\.` | Runtime module loading | | ||
| If either layer finds a threat, the verdict is `BLOCKED` (the reason notes which layer triggered). If both layers are clean, the verdict is `HEURISTIC_PASS` — a signed attestation that no known dangerous constructs were found, **not** a deterministic guarantee that the code is safe to execute. | ||
|
|
| | `compile` | `\bcompile\s*\(` | Code compilation | | ||
| | `importlib` | `\bimportlib\s*\.` | Runtime module loading | | ||
| If either layer finds a threat, the verdict is `BLOCKED` (the reason notes which layer triggered). If both layers are clean, the verdict is `HEURISTIC_PASS` — a signed attestation that no known dangerous constructs were found, **not** a deterministic guarantee that the code is safe to execute. | ||
|
|
| | `importlib` | `\bimportlib\s*\.` | Runtime module loading | | ||
| If either layer finds a threat, the verdict is `BLOCKED` (the reason notes which layer triggered). If both layers are clean, the verdict is `HEURISTIC_PASS` — a signed attestation that no known dangerous constructs were found, **not** a deterministic guarantee that the code is safe to execute. | ||
|
|
||
| ```python |
| | `importlib` | `\bimportlib\s*\.` | Runtime module loading | | ||
| If either layer finds a threat, the verdict is `BLOCKED` (the reason notes which layer triggered). If both layers are clean, the verdict is `HEURISTIC_PASS` — a signed attestation that no known dangerous constructs were found, **not** a deterministic guarantee that the code is safe to execute. | ||
|
|
||
| ```python |
| # verdict.reason = "Dangerous code patterns detected (AST): subprocess import" | ||
| ``` | ||
|
|
||
| ### Passthrough |
| ``` | ||
|
|
||
| ### Passthrough | ||
| ### Passthrough (unverifiable) |
|
|
||
| ### Passthrough | ||
| ### Passthrough (unverifiable) | ||
|
|
| - **Empty/malformed finance and logic payloads → `UNVERIFIABLE`, no JWT.** A `FINANCIAL_TRANSACTION` missing `data`, `line_items`, or `claimed_total`, or with non-numeric amounts, now returns `status=unverifiable` from `finance_guard`. A `LOGIC_ASSERTION` with a missing, non-list, or empty `assertions` array, or malformed entries, returns `status=unverifiable` from `logic_guard`. Earlier releases collapsed these cases to `verified=True` + a signed `FORWARDED` verdict. | ||
| - **`GENERAL` and `DATA_QUERY` are no longer silently forwarded.** The passthrough branch now returns an `unverifiable` verdict with `engine_used="passthrough"`, `attestation_jwt=None`, and reason `"No verification engine available for this payload type"`. Callers must decide their own downstream policy for unverified traffic. | ||
| - **No `Bypass` verification stage.** The pipeline has four stages, not five. `config.trusted_agents` is pre-added to the `TrustBoundary` allowlist at interceptor construction time — trusted agents still flow through engine routing and receive a normal verdict. The [Verification interceptor](/a2a/interceptor#verification-pipeline) and [Architecture](/a2a/architecture) pages have been corrected. | ||
| - **`CodeGuard` is AST-first, regex-second.** Code payloads are first parsed into an AST and inspected for direct dangerous constructs (`eval(`, `exec(`, `subprocess.run(`, `import subprocess`, etc.). Only if the AST layer is clean does a regex heuristic scan run to catch obfuscation patterns (`getattr(__builtins__, ...)`, base64-encoded exec, dynamic `__import__`). The verdict is `BLOCKED` if either layer triggers, or `HEURISTIC_PASS` if both are clean — not a proof of safety. |
| - **Empty/malformed finance and logic payloads → `UNVERIFIABLE`, no JWT.** A `FINANCIAL_TRANSACTION` missing `data`, `line_items`, or `claimed_total`, or with non-numeric amounts, now returns `status=unverifiable` from `finance_guard`. A `LOGIC_ASSERTION` with a missing, non-list, or empty `assertions` array, or malformed entries, returns `status=unverifiable` from `logic_guard`. Earlier releases collapsed these cases to `verified=True` + a signed `FORWARDED` verdict. | ||
| - **`GENERAL` and `DATA_QUERY` are no longer silently forwarded.** The passthrough branch now returns an `unverifiable` verdict with `engine_used="passthrough"`, `attestation_jwt=None`, and reason `"No verification engine available for this payload type"`. Callers must decide their own downstream policy for unverified traffic. | ||
| - **No `Bypass` verification stage.** The pipeline has four stages, not five. `config.trusted_agents` is pre-added to the `TrustBoundary` allowlist at interceptor construction time — trusted agents still flow through engine routing and receive a normal verdict. The [Verification interceptor](/a2a/interceptor#verification-pipeline) and [Architecture](/a2a/architecture) pages have been corrected. | ||
| - **`CodeGuard` is AST-first, regex-second.** Code payloads are first parsed into an AST and inspected for direct dangerous constructs (`eval(`, `exec(`, `subprocess.run(`, `import subprocess`, etc.). Only if the AST layer is clean does a regex heuristic scan run to catch obfuscation patterns (`getattr(__builtins__, ...)`, base64-encoded exec, dynamic `__import__`). The verdict is `BLOCKED` if either layer triggers, or `HEURISTIC_PASS` if both are clean — not a proof of safety. |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
Greptile SummaryThe PR realigns the A2A documentation with fail-closed
Confidence Score: 4/5The documentation update appears safe to merge after resolving three non-blocking contract and terminology inconsistencies. The principal behavior corrections are coherent, but the Overview still promises JWTs for every verdict, the new Files Needing Attention: a2a/overview.mdx, a2a/interceptor.mdx, changelog.mdx
|
| Filename | Overview |
|---|---|
| a2a/interceptor.mdx | Substantially updates pipeline and verdict semantics, but leaves ambiguity around the error status and the passthrough field name. |
| a2a/architecture.mdx | Updates routing, attestation, and Code Guard architecture to include UNVERIFIABLE and HEURISTIC_PASS. |
| a2a/quickstart.mdx | Correctly changes the unsupported-payload response example to an unsigned unverifiable verdict. |
| a2a/crypto-attestations.mdx | Corrects the documented default JWT lifetime and signing example to 300 seconds. |
| a2a/overview.mdx | Updates Code Guard terminology but retains a universal attestation claim that conflicts with the new verdict contract. |
| changelog.mdx | Adds a detailed release entry, including the same unresolved error-status contract presented by the interceptor page. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
M[Agent message] --> T[Trust boundary]
T --> R{Payload type}
R -->|Finance| F[Finance guard]
R -->|Logic| L[Logic guard]
R -->|Code| C[AST and regex guard]
R -->|General or data query| U[UNVERIFIABLE]
F --> V[Signed verdict]
L --> V
C --> V
U --> N[No JWT]
Reviews (1): Last reviewed commit: "docs: improve SEO titles for a2a overvie..." | Re-trigger Greptile
| </Card> | ||
| <Card title="Deterministic Engines" icon="microchip" href="/a2a/interceptor#verification-engines"> | ||
| Financial verification uses `Decimal` arithmetic. Logic uses set-based contradiction detection. Code uses regex-hardened pattern scanning. | ||
| Financial verification uses `Decimal` arithmetic. Logic uses set-based contradiction detection. Code uses AST structural analysis backed by regex heuristics. |
There was a problem hiding this comment.
| | `blocked` | Engine detected a violation (bad math, contradiction, dangerous code). Do not forward. | Signed | | ||
| | `heuristic_pass` | Code guard ran, no known dangerous constructs found. Not a proof of safety. | Signed | | ||
| | `unverifiable` | No engine could evaluate the payload (`GENERAL`/`DATA_QUERY`, empty/malformed finance or logic payload). No attestation is issued. | **None** | | ||
| | `error` | Internal exception during verification. Behavior depends on `block_on_error`. | Signed | |
There was a problem hiding this comment.
Error status contract conflicts
The new table presents error as the status for internal exceptions, while the error-handling section says those exceptions return blocked or forwarded according to block_on_error. Callers therefore cannot determine which status represents an internal failure and can implement an unreachable or incomplete branch.
| ### Passthrough (unverifiable) | ||
|
|
||
| Messages with `payload_type` of `GENERAL` or `DATA_QUERY` are forwarded without verification. | ||
| Messages with `payload_type` of `GENERAL` or `DATA_QUERY` have no verification engine. The interceptor returns an **`UNVERIFIABLE`** verdict with `engine="passthrough"`, **no JWT attestation**, and reason `"No verification engine available for this payload type"`. The message is not silently forwarded — callers must decide whether to route unverified content downstream based on their own policy. |
There was a problem hiding this comment.
Passthrough field name differs
This prose names the returned field engine, but the adjacent example and documented VerificationVerdict model expose engine_used. Copying this contract leads integrations to access a nonexistent verdict.engine attribute and mishandle the passthrough result.
| Messages with `payload_type` of `GENERAL` or `DATA_QUERY` have no verification engine. The interceptor returns an **`UNVERIFIABLE`** verdict with `engine="passthrough"`, **no JWT attestation**, and reason `"No verification engine available for this payload type"`. The message is not silently forwarded — callers must decide whether to route unverified content downstream based on their own policy. | |
| Messages with `payload_type` of `GENERAL` or `DATA_QUERY` have no verification engine. The interceptor returns an **`UNVERIFIABLE`** verdict with `engine_used="passthrough"`, **no JWT attestation**, and reason `"No verification engine available for this payload type"`. The message is not silently forwarded — callers must decide whether to route unverified content downstream based on their own policy. |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
Summary
Align the A2A docs with the interceptor's
UNVERIFIABLEfail-closed behavior and correct five materially false claims that previously described the pipeline differently from the code.Changes
a2a/interceptor.mdx— removed the "Trusted Agent Bypass" step (trusted agents are only pre-added to the allowlist), added a verdict-status table, rewrote Code Guard as AST-first + regex-heuristic (withBLOCKED/HEURISTIC_PASS), reframed passthrough asUNVERIFIABLEwith no JWT, noted that empty/malformed finance and logic payloads now returnUNVERIFIABLE, and updated thetrusted_agentsconfig row.a2a/quickstart.mdx— updated theGENERALgateway response example to showstatus: "unverifiable",attestation_jwt: null, and the reason string.a2a/architecture.mdx— pipeline table and payload-type routing table now reflectunverifiable+heuristic_passand the AST-first Code Guard.a2a/overview.mdx— small wording tweaks (Code Guard blurb and diagram label).a2a/crypto-attestations.mdx— JWTexpdefault corrected to 300 seconds (5 minutes); signing example updated fromvalidity_seconds=86400tovalidity_seconds=300.changelog.mdx— new top-of-file entry summarizing the behavior change, the JWT-attestation contract, and the caller-side impact.Context
UNVERIFIABLEinstead of a signedFORWARDED.Bypassstage,GENERAL/DATA_QUERYareUNVERIFIABLE, CodeGuard is AST + heuristics, JWT expiry is 300 s, no JWT onUNVERIFIABLE).