Skip to content

verify_audit_bundle can raise on malformed bundle entry shapes instead of returning AuditBundleResult #593

Description

@altrudev

Current behavior

verify_audit_bundle() is a separately exported verifier entry point and returns AuditBundleResult, but at current main (2c0a601805bfb31fddc49db32ae122bae8e2251e) it assumes the externally supplied bundle and every member of entries already have object shape.

The first verification loop does:

entries = bundle_json.get("entries", [])
...
for i, entry in enumerate(entries):
    body = {k: v for k, v in entry.items() if k != "entry_hash"}

So malformed but JSON-valid inputs such as:

{"entries": ["unexpected"]}

or

{"entries": [1]}

reach .items() and escape as AttributeError instead of producing an AuditBundleResult(verified=False, ...).

A truthy non-list entries value also enters the loop. For example, a string is iterated character by character before failing on the first character's missing .items().

The optional claim-binding half has the same structural assumption in nested reads such as:

chain = claim_json.get("gateway", {}).get("audit_chain", {})
transcript = claim_json.get("trace", {}).get("tool_transcript", {})
...
x_b64 = claim_json.get("trace", {}).get("cnf", {}).get("jwk", {}).get("x", "")

which can raise if an intermediate value is a scalar/list rather than an object.

Why this is distinct from #592

#592 concerns verify_trace_claim() continuing into structure-dependent claim verification after its Pydantic schema check has already failed.

This issue is the independent public verify_audit_bundle() API. It has no schema gate at all for the bundle and returns a different result type. Fixing #592 does not change this path.

Expected invariant

Malformed external audit-bundle structure should fail closed as verifier evidence, not terminate the caller with a Python shape exception.

At minimum, verify_audit_bundle() should either:

  1. establish the bundle/entry object and array boundaries before content verification; or
  2. defensively classify malformed structure into AuditBundleResult.failures.

The verifier should not need to infer cryptographic meaning from a value whose JSON container type has not first been established.

Focused regression matrix

  • top-level bundle_json object with missing/empty entries -> existing bundle has no entries behavior preserved;
  • entries = string/object/integer/bool -> failed AuditBundleResult, never an exception;
  • entries = list containing string/integer/list/null -> failed AuditBundleResult, never an exception;
  • one valid entry control -> existing hash/link verification unchanged;
  • when claim_json is supplied, malformed gateway, gateway.audit_chain, trace, trace.tool_transcript, and trace.cnf intermediates -> failed AuditBundleResult, never an exception.

No wire-format or normative specification change appears necessary. This is verifier exception-safety and structural failure classification at the audit-bundle boundary.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions