Skip to content

Add cargo-fuzz targets + scheduled CI fuzz workflow #6

@jaschadub

Description

@jaschadub

Why

v0.3.0 ships with several untrusted-input parsers that are excellent fuzz targets, currently covered only by unit tests:

  • JWT parsing (crates/agentpin/src/jwt.rs) — inline header/payload/signature parsing with algorithm rejection. AgentPin does NOT use a third-party JWT crate; algorithm validation is hand-rolled. Any malformed JWT must bounce off this code without panicking or hanging.
  • JSON discovery doc parsing (crates/agentpin/src/discovery.rs, crates/agentpin/src/types/*) — .well-known/agent-identity.json is fetched from untrusted publishers.
  • A2A AgentCard parsing + canonicalisation for signing (crates/agentpin/src/a2a.rs, crates/agentpin/src/types/a2a.rs) — wire format must round-trip byte-identically with the other three SDKs; canonical-form bugs are signature-bypass primitives.
  • JWK ↔ PEM conversion (crates/agentpin/src/jwk.rs) — public-key parsing, RFC 7638 thumbprint construction.
  • DNS TXT record parsing (crates/agentpin/src/dns.rs) — _agentpin.{domain} TXT values come from third-party DNS providers and registrars.
  • Capability string parsing (crates/agentpin/src/types/capability.rs) — wildcard/scope-matching grammar.

These are exactly the kinds of parsers where a single panic, infinite loop, OOM, or off-by-one is either a denial-of-service or (in the canonicalisation case) a potential signature-bypass.

Scope

  1. Add a new workspace member crates/agentpin-fuzz/ using cargo-fuzz with at least one fuzz target per parser listed above.
  2. Provide a seed corpus for each target — JWTs issued by the test suite, real-world discovery doc JSON, AgentCards generated in Rust/JS/Python/Go interop tests, DNS TXT samples from the test vectors in src/dns.rs.
  3. Add a scheduled GitHub Actions workflow (.github/workflows/fuzz.yml, e.g. nightly at 02:00 UTC) that runs each target for a fixed time budget (5–10 minutes per target) and uploads any crashes as artifacts. Do not make this a PR-blocking check.
  4. Wire crashes back into the test suite as regression fixtures when found.

Non-goals (for the initial PR)

  • Cross-language fuzzing (the JS/Python/Go SDKs would need their own harnesses — file separately if they accumulate enough parser surface to justify it). The wire format is shared so a corpus crash in Rust is likely a crash in all four.
  • Long fuzz campaigns in CI — the scheduled workflow is intended as a smoke check, not a continuous-fuzzing service. Run longer campaigns locally before tagging a release.

Target release

v0.3.1 or v0.4.0. Not a v0.3.0 blocker — unit-test coverage of the parsers is solid, and adding fuzz targets requires writing per-parser harnesses across four SDKs to do properly. Better to ship v0.3.0 and follow up than to delay.

Context

Filed as a follow-up after a brief pre-release fuzz-coverage discussion during the v0.3.0 release. See https://github.com/ThirdKeyAI/AgentPin/releases/tag/v0.3.0 for what shipped.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions