Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

content_marking: validate record.alg against record.hash prefix, reject unknown assertion fields, and check anchor agreement

Open
#614 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@drk-ram is already working on this.

Since Oct 23, 2026.

  • #621 by @drk-ram — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
python

Research direction

Read src/agentrust_trace/content_marking.py alongside sections 2 and 4 of spec/content-marking-v1.md; focus on verify_assertion and build_assertion. Reproduce the mismatched algorithm and hash prefix case described in the issue, then inspect the unknown-field and anchor cases. Done means the three validation gaps behave as specified, with malformed assertions raising ContentMarkingError and anchor disagreement raising RecordMismatch; pull request #621 is already open.

Written by the indexing model from the issue text.

Description

needs-review:MEDIUM

What is wrong

At main (a8e3559), src/agentrust_trace/content_marking.py has three consumer validation and error-classification gaps in verify_assertion and build_assertion:

  1. verify_assertion raises RecordMismatch (accusing the server at record.url) when the assertion's own record.alg and record.hash prefix disagree, and checks record_bytes before validating record.alg:

    • In src/agentrust_trace/content_marking.py:391-418, alg = ref.get("alg") is only checked for isinstance(alg, str) before record_bytes is validated, and expected = ref.get("hash") is matched against _DIGEST_RE (^sha(256:[0-9a-f]{64}|384:[0-9a-f]{96})$), which admits both sha256: and sha384:.
    • When assertion["data"]["record"]["alg"] = "sha256" and assertion["data"]["record"]["hash"] = "sha384:" + "a" * 96 (or alg = "sha384" and hash = "sha256:" + "a" * 64), _digest(record_bytes, alg) computes a sha256: digest, compares it to "sha384:...", and raises RecordMismatch ("the record at ... does not match the assertion ... The record changed after the asset was signed, or the URL is serving a different one") for a self-contradictory assertion that no server response could ever satisfy.
    • Similarly, when alg = "md5" and record_bytes = b"", verify_assertion blames record_bytes before checking alg in _ALGS.
  2. verify_assertion does not reject unknown fields on assertion, assertion["data"], or assertion["data"]["record"]:

    • spec/content-marking-v1.md section 2 defines the exact fields of com.agentrust-io.trace ({"label", "data"}, {"version", "record", "subject", "eat_profile", "anchor"}, and {"url", "hash", "alg"}), but verify_assertion ignores arbitrary extra fields on all three objects.
  3. verify_assertion does not check anchor agreement when the resolved record carries transparency / anchor:

    • verify_assertion (lines 434-448) checks record_subject != data.get("subject") and record_profile != data.get("eat_profile"), and validates if "anchor" in record at line 434, but never checks whether a present data["anchor"] disagrees with record["anchor"] / record["transparency"] (raising RecordMismatch when they disagree).

Reproduction on a8e3559:

import json
from agentrust_trace.content_marking import build_assertion, verify_assertion

raw = json.dumps({
    "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2",
    "iat": 1760000000,
    "subject": "spiffe://example.org/agent/image-bot",
}).encode()
a = build_assertion(raw, url="https://registry.example/records/abc123.json", alg="sha384")
a["data"]["record"]["alg"] = "sha256"  # hash is sha384:..., alg is sha256
# Raises RecordMismatch (blaming the server) instead of plain ContentMarkingError:
verify_assertion(a, raw)

Spec section or file

  • src/agentrust_trace/content_marking.py (verify_assertion, build_assertion)
  • spec/content-marking-v1.md sections 2 and 4

Expected behavior

  1. In verify_assertion, validate alg in _ALGS and expected.startswith(f"{alg}:") before inspecting record_bytes, raising plain ContentMarkingError (not RecordMismatch) when record.alg is unsupported or disagrees with the prefix of record.hash.
  2. Reject unknown fields in assertion ({"label", "data"}), assertion["data"] ({"version", "record", "subject", "eat_profile", "anchor"}), and assertion["data"]["record"] ({"url", "hash", "alg"}) with ContentMarkingError.
  3. When anchor is present in assertion["data"] and the resolved record also carries anchor (or transparency), raise RecordMismatch if they disagree.

Impact

A malformed assertion with mismatched record.alg and record.hash prefix raises RecordMismatch (falsely accusing the remote server of modifying the record), and mismatched anchor values between the assertion and record pass verify_assertion.

Dominant language
Python
Stars
37
Forks
33
Avg merge
1d 7h
Merged PRs (30d)
111

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from agentrust-io/trace-spec

All issues in agentrust-io/trace-spec

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.