Skip to content

Comments

Fix substring check used instead of equality for cookie header name#1313

Open
bysiber wants to merge 2 commits intopython-hyper:masterfrom
bysiber:fix/cookie-header-substring-check
Open

Fix substring check used instead of equality for cookie header name#1313
bysiber wants to merge 2 commits intopython-hyper:masterfrom
bysiber:fix/cookie-header-substring-check

Conversation

@bysiber
Copy link

@bysiber bysiber commented Feb 20, 2026

Summary

Fix _secure_headers incorrectly matching header names that are substrings of "cookie".

Problem

In _secure_headers, the cookie header check uses:

header[0] in b"cookie"

The in operator on bytes performs substring search, not equality. This means any header name that is a byte-level substring of b"cookie" will match:

>>> b"co" in b"cookie"
True
>>> b"ok" in b"cookie"
True
>>> b"e" in b"cookie"
True

Any such header with a value shorter than 20 bytes will be incorrectly promoted to a NeverIndexedHeaderTuple, which tells HPACK to never add it to the dynamic compression table. While the security impact is minimal (the wrong headers are over-protected, not under-protected), it changes the HPACK encoding behavior in unexpected ways and could affect compression efficiency.

The same pattern exists in _reject_pseudo_header_fields for the :method check, though it is harmless in practice because only validated pseudo-headers reach that point.

Fix

Change both in checks to == for exact equality:

# Before
header[0] in b"cookie"
header[0] in b":method"

# After
header[0] == b"cookie"
header[0] == b":method"

The `in` operator on `bytes` performs substring search, not equality.
`header[0] in b"cookie"` matches any header name that is a substring
of "cookie" (e.g. b"co", b"ok", b"e"), not just b"cookie" itself.

This means short header names that happen to be substrings of "cookie"
get incorrectly promoted to NeverIndexedHeaderTuple when their value
is under 20 bytes, potentially affecting HPACK compression behavior.

Changed both occurrences to use `==` for exact comparison:
- Line 91: cookie header check in _secure_headers
- Line 350: :method pseudo-header check in _reject_pseudo_header_fields
@Kriechi
Copy link
Member

Kriechi commented Feb 20, 2026

Thanks! This might be a left-over from the time when we had bytes and strings to compare against.
Would you mind adding / adjusting the tests?

- Add test data with header names that are substrings of 'cookie' but
  not equal to 'cookie' to verify they are not treated as sensitive
- Add test for extract_method_header to verify substring names like
  ':me' do not falsely match ':method'
@bysiber
Copy link
Author

bysiber commented Feb 21, 2026

Added regression tests:

  • test_non_cookie_substring_headers_can_be_indexed: verifies that headers with names like cook, okie, cooki (substrings of cookie but not equal) are not incorrectly treated as sensitive
  • test_extract_method_header_no_false_substring_match: verifies that a header named :me (substring of :method) does not falsely match in extract_method_header

All 324 tests in the affected files pass.

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