Skip to content

fix(adapters): validate iat before it reaches the record, not after - #343

Open
harshnair75567-cloud wants to merge 1 commit into
agentrust-io:mainfrom
harshnair75567-cloud:fix/iat-type-bypass-in-adapters
Open

harshnair75567-cloud wants to merge 1 commit into
agentrust-io:mainfrom
harshnair75567-cloud:fix/iat-type-bypass-in-adapters

Conversation

@harshnair75567-cloud

Copy link
Copy Markdown
Contributor

SandboxSessionResult and AGTSessionResult wrote session.iat straight into build_trust_record's top-level "iat" key with no type check. Every other field reaches the record through a models.py pydantic constructor, which coerces or refuses a bad value before it is dumped -- iat bypassed all of them.

TrustRecord.model_validate(), which sign_record's own docstring recommends for structural validity before writing, gave a false pass on a numeric-string iat: pydantic's lax mode coerces "1800000000" -> 1800000000 during validation, but that happens on a new object and never touches the dict being signed. The wire bytes kept the string, which jsonschema.validate against trace-v0.2.json and this library's own verify_record both then reject.

AGTSessionResult additionally had no post_init at all.

Same failure mode as provenance.build_record's pre-#320 issued_at coercion, fixed there by validating the caller's explicit value before use instead of converting it. This applies the same fix to both adapters, mirroring _check_structure's bound (non-negative, <= JCS_SAFE_INTEGER, bool excluded since bool subclasses int).

1561 passed, 1 skipped. ruff and mypy clean on both changed source files.

What this changes

Type of change

  • Editorial (typo, link fix, clarification: no normative effect)
  • Non-breaking spec change (new optional field, new platform profile, informative addition)
  • Breaking spec change (requires 14-day comment period and Project Lead sign-off)
  • Schema change
  • Example addition

Spec section

Checklist

  • [.] DCO sign-off on all commits (git commit -s)
  • CHANGELOG.md updated (for any normative change)
  • Breaking changes marked with <!-- CHANGED: #NNN: description --> in spec text
  • Backward compatibility statement included (for breaking changes)

SandboxSessionResult and AGTSessionResult wrote session.iat straight into
build_trust_record's top-level "iat" key with no type check. Every other
field reaches the record through a models.py pydantic constructor, which
coerces or refuses a bad value before it is dumped -- iat bypassed all of
them.

TrustRecord.model_validate(), which sign_record's own docstring recommends
for structural validity before writing, gave a false pass on a numeric-string
iat: pydantic's lax mode coerces "1800000000" -> 1800000000 during
validation, but that happens on a new object and never touches the dict being
signed. The wire bytes kept the string, which jsonschema.validate against
trace-v0.2.json and this library's own verify_record both then reject.

AGTSessionResult additionally had no __post_init__ at all.

Same failure mode as provenance.build_record's pre-agentrust-io#320 issued_at coercion,
fixed there by validating the caller's explicit value before use instead of
converting it. This applies the same fix to both adapters, mirroring
_check_structure's bound (non-negative, <= JCS_SAFE_INTEGER, bool excluded
since bool subclasses int).

1561 passed, 1 skipped. ruff and mypy clean on both changed source files.

Signed-off-by: harshnair75567-cloud <harshnair75567@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant