Skip to content

Tardigrade v0.7.0

Choose a tag to compare

@github-actions github-actions released this 18 Sep 00:40
· 48 commits to main since this release
2576b07

[0.7.0] - 2026-09-17

Added

  • Fuzz-campaign orchestration and evidence capture are now available
    (#740, #741, #755)
    — reproducible local and Proxmox campaign runners now
    record manifests, watchdog outcomes, exact crash inputs, provenance, and
    preservable fuzzer state. The control plane handles detached long-running
    rows, SSH keepalives, remote-stage cleanup, and evidence-integrity failures
    explicitly so a clean run, a finding, and an interrupted row remain
    distinguishable. The sustained #675 validation flow now pins each campaign
    to an explicitly requested published release tag and its resolved commit,
    rather than following a moving development branch.

Changed

  • Release security hardening closes cross-protocol ambiguity, memory, and
    origin-crash paths (#756)
    — HTTP/1 now rejects duplicate/malformed Host fields
    and absolute-form/Host authority disagreement. HTTP/2 validates the complete
    pseudo-header envelope and values before its HTTP/1 adapter, strips padding,
    ignores extension frames safely, validates SETTINGS, bounds HPACK state, and
    enforces concurrent-stream plus aggregate request-memory limits. HTTP/3 now
    applies equivalent header/framing checks and per-request plus aggregate
    request-memory ceilings. Valid unregistered origin status codes no longer
    trap response conversion, while malformed FastCGI/SCGI/uWSGI statuses fail
    closed instead of becoming 200. Persistent session and approval credentials
    are atomically written with owner-only permissions and temporary plaintext
    buffers are wiped. Authorization policy time windows now reject malformed or
    out-of-range hours, and device request authentication uses the documented
    HMAC-SHA256 construction with constant-time MAC verification. Policy regex
    compilation/execution failures and invalid approval booleans also deny the
    request instead of silently skipping the affected rule. Configured ACL and
    HSTS state is now prepared transactionally for startup/reload rather than
    being disabled on parse/allocation failure. Policy enforcement now runs on
    the production H1, H2, and H3 paths; denied H1 bodies are never mirrored,
    valid identities satisfy H2/H3 required-auth locations, and H3 ACL/rate-limit
    decisions use the QUIC transport peer rather than a spoofable X-Real-IP.
    Malformed policy/scope/approval mappings fail configuration validation.
    SMTP/IMAP upstream TLS now verifies hostname and CA without permitting
    truncation, mail replies are bounded, UDP proxy reads have deadlines, and
    memcached JSON/TTL parsing rejects invalid input without traps or leaks.
    Failed session, approval, and TLS ticket-key persistence also removes its
    owner-only temporary credential file instead of leaving secret/key material
    behind after write, sync, or rename errors. Transcript files are created
    owner-only atomically, closing the prior create-then-chmod exposure window.
    JWT and session-derived identity fields are validated at asserted-header
    boundaries, preventing CR/LF-bearing claims from injecting upstream HTTP or
    SMTP headers. Geo-blocking configurations now require an explicit trusted
    proxy/CDN source and reject country headers received from any other peer.
    Best-effort mirror delivery now uses bounded native HTTP/TLS transport and a
    bounded ignored response, preventing a stalled mirror from holding a worker
    indefinitely. The SMTP asserted-identity boundary rejects any inbound
    X-Tardigrade-* field in the message-header section — whether or not the
    request is authenticated — so a client can neither forge an identity nor
    suppress the authoritative one, with case-insensitive DATA and header
    matching. Trusted-peer matching compares parsed IP addresses instead of
    truncated text, closing a bypass where two IPv6 addresses differing only in
    the final hextet compared equal. Mirror targets must name http or https
    explicitly, rejected at startup/reload rather than silently downgraded to
    cleartext. IP access-control policy is now owned by the configuration
    generation a request leased, so a reload can neither free rules underneath an
    in-flight request nor let an older request skip a denial its own configuration
    requires. Approval persistence serializes snapshot and write under one lock so
    a delayed writer cannot overwrite newer approval state, and approval restore
    works at all (it previously failed on every non-empty store). Approval,
    session, and device-HMAC credential copies are wiped through the canonical
    secureZero path, and the device registry is created owner-only and refuses
    to append to a group/world-accessible file or serialize delimiter-bearing
    credential fields. Approved tokens now expire at their configured TTL and
    bind exactly to their issued method, path, and identity rather than treating
    request paths or * methods as patterns. Location auth required denials no
    longer mirror the denied request body. HTTP/2 gates inbound HEADERS and
    DATA on the stream state machine rather than request-assembly bookkeeping, so
    a peer cannot open a second request on a stream whose response is still
    outstanding, and CONNECT is refused at stream scope instead of failing inside
    the shared HTTP/1 adapter. Approval and command state mutations now remain
    atomic on allocation failure instead of retaining dangling pointers, and all
    related JSON — including command envelopes sent upstream — uses structural
    encoding rather than interpolating identities, paths, actors, errors, IDs,
    params, or upstream bodies. Structured/application logs,
    health/status responses, and Prometheus device labels likewise escape
    request-controlled data, preventing forged audit records and metrics.
    Authentication subrequests and approval webhooks now use bounded native
    transports; webhook payloads and response heads are capped, and both trust
    boundaries require certificate/URL-host verification. Auth subrequests cannot
    inherit a normal origin's verification bypass or SNI override.

  • Secret zeroization is now materially faster on x86_64, and the
    guarantee is now Tardigrade-owned (#741)
    — crypto.secrets.secureZero
    no longer wraps std.crypto.secureZero, which is @memset over a
    volatile slice. LLVM drops the volatile there and lowers it to an
    ordinary memset libcall; on x86_64-linux that binds to
    compiler_rt.memset, a byte-at-a-time store loop, even with libc
    linked. The clear was always performed, so this was never a correctness
    or non-elision defect — but it made every bulk wipe roughly 22x more
    expensive on x86_64 than on aarch64. secureZero now writes through
    wide volatile vector stores, which cannot be merged, widened, or
    dropped. A QUIC connection teardown (QuicTlsAdapter.deinit, 529,944
    bytes of wipeable state, reachable by connection churn) drops from
    ~414 µs to ~254 µs of CPU on x86_64. Every production secret wipe now
    routes through the canonical helper, including
    encrypted_stream.ByteQueue's plaintext cleanup, which previously used
    a plain @memset.

  • HTTP/2 and HTTP/3/QUIC are promoted to stable (#738) — the support
    matrix and public/operator docs now describe the stable native downstream
    protocol contract for HTTP/1.1, HTTP/2, and HTTP/3/QUIC. The promotion is
    tied to the retained H2 baseline, #593/#699 real-H3 baseline, the v0.6.5
    installed-artifact #677 sweep, ngtcp2/GnuTLS plus aioquic black-box H3
    closeout, and the passing Public Homebrew Smoke run for the published
    artifact path. The docs also call out the stable-contract limits explicitly:
    H2 is TLS/ALPN-only downstream, H3 requires UDP reachability and
    Tardigrade-owned Alt-Svc advertisement, and H3 listener-owned transport
    changes require restart.

  • Fuzz verification is faster and keeps leak detection enabled (#757, #758,
    #774, #775)
    — the TLS encrypted-stream cleanup oracle now compares storage in
    vector-sized byte chunks while retaining full-capacity clearing checks, and
    the HTTP/3 command-sequence target uses a target-local debug allocator that
    preserves leak checking without the otherwise unbounded diagnostic stack
    metadata cost during sustained fuzzing.

Fixed

  • TLS and HTTP/3 error-state handling is stricter and remains bounded under
    hostile transitions (#741, #755)
    — TLS 1.3 HelloRetryRequest key-share
    violations now return illegal_parameter; HTTP/3 stops accepting new state
    after close, rejects bytes after a request FIN, skips streams reset before
    first acceptance, and caps retained peer unidirectional-stream state with
    H3_EXCESSIVE_LOAD.

  • QUIC stream reassembly resists fragmented-input CPU and final-size attacks
    (#741, #749)
    — per-stream out-of-order receive state now caps disjoint
    segments at 256, preventing a peer from growing the repeated-scan
    reassembly path into an O(n²) CPU denial of service. A STREAM FIN that
    undercuts already buffered out-of-order bytes is also rejected rather than
    resurrecting an invalid smaller final size.

  • TLS queue discard is now amortized O(1) without retaining stale plaintext
    copies (#741)
    — ByteQueue and PlaintextProvenanceQueue advance a lazy
    read prefix instead of shifting every remaining byte on each discard.
    Subsequent compaction securely wipes the obsolete plaintext duplicate before
    reusing its backing storage.

  • HTTP/3/QPACK protocol validation now handles fragmented and malformed peer
    input without ambiguous state (#775)
    — QPACK dynamic references fail when
    capacity is zero; fragmented unidirectional stream-type prefixes retain
    parser state; peer request streams require a header section; invalid
    response pseudo-headers and status values fail closed; informational
    responses do not complete a request; and transport/application close codes
    remain distinguishable.

Testing

  • Campaign models and their independent oracles were hardened (#741, #755,
    #757, #758)
    — TLS resumption and transcript models now match their actual
    contracts, bounded HTTP/3 stream-pressure paths have deterministic
    regressions, fuzz findings are detected even when the Zig runner exits zero,
    and the encrypted-stream cleanup oracle compares bool storage through an
    exact byte view on every supported architecture.

Build

  • GitHub CodeQL SARIF upload action was updated (#703).