Skip to content

fix(quic): bound decrypt header associated data#11

Open
alanhoff wants to merge 4 commits intoendel:mainfrom
alanhoff:fix/quic-decrypt-header-bounds
Open

fix(quic): bound decrypt header associated data#11
alanhoff wants to merge 4 commits intoendel:mainfrom
alanhoff:fix/quic-decrypt-header-bounds

Conversation

@alanhoff
Copy link

Summary

  • reject QUIC packet headers that exceed the fixed associated-data buffer before any decrypt-path memcpy
  • reuse the same bounded helper in both the regular decrypt path and the key-update decrypt path
  • add regression tests for the oversized-header rejection and the unprotected-first-byte copy behavior

Vulnerability

decrypt() and decryptWithKeyUpdate() rebuild AEAD associated data by copying the unprotected packet header into a fixed 512-byte stack buffer. For long-header packets, that reconstructed header length includes the Initial token field. Because QUIC Initial packets carry a variable-length token, a malicious peer can send an internally well-formed packet whose header grows past 512 bytes and drive the memcpy past the end of the stack buffer.

Concrete examples:

  • an Initial packet with a token long enough to make the unprotected header 513 bytes reaches the decrypt path and previously overflowed the 512-byte AD buffer
  • a larger token keeps increasing the copied header length even though only the associated-data scratch buffer is fixed-size
  • on safety-enabled builds this becomes a remote crash; on unchecked builds it becomes memory corruption on the packet decryption path

Validation

  • zig build test
  • zig build
  • zig build fuzz
  • gh issue list --repo endel/quic-zig --search "header buffer overflow decrypt token length initial packet" --limit 20

References

Reject oversized QUIC headers before copying them into the fixed-size associated-data buffer used during packet decryption, and add regression tests covering the oversize and unprotected-first-byte cases.

Co-authored-by: Codex <noreply@openai.com>
Copilot AI review requested due to automatic review settings March 17, 2026 21:00
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens QUIC packet decryption by bounding construction of AEAD associated data (AD) to prevent stack-buffer overflow when reconstructing long headers (notably QUIC Initial packets with large tokens), and adds regression tests for the new behavior.

Changes:

  • Introduce buildHeaderBytes() to safely rebuild the unprotected header bytes into a fixed-size AD scratch buffer with length checks.
  • Reuse the bounded helper from both decrypt() and decryptWithKeyUpdate().
  • Add tests covering oversized-header rejection and ensuring the first byte in AD is the unprotected value.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Codex <noreply@openai.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to harden QUIC packet decryption against malformed/attacker-controlled length fields and oversized headers used to build AEAD associated data (AD) during decryption.

Changes:

  • Adds guards in decrypt() and decryptWithKeyUpdate() to prevent remainder_len underflow and out-of-bounds payload slicing.
  • Minor cleanup of encrypted_payload slicing syntax.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add shared header rebuilding bounds checks and regression tests for malformed payload lengths in both decrypt paths.

Co-authored-by: Codex <noreply@openai.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a QUIC decryption-time stack-buffer overflow risk by bounding reconstruction of AEAD associated data (the unprotected header) before copying it into a fixed-size scratch buffer, and adds regression tests to prevent reintroduction.

Changes:

  • Added a shared buildHeaderBytes() helper to reconstruct header bytes into a bounded 512-byte buffer (rejecting oversized headers early).
  • Reused the helper in both decrypt() and decryptWithKeyUpdate(), and added explicit malformed-length guards before slicing the encrypted payload.
  • Added unit tests covering oversized-header rejection, preservation of the unprotected first byte, and malformed payload length rejection in both decrypt paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Use an explicit InvalidPacket-only error set for buildHeaderBytes so decrypt APIs do not inherit a broader helper error surface.

Co-authored-by: Codex <noreply@openai.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.

2 participants