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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions