tls_inspector: fix GREASE filtering in JA4_c signature algorithms - #46658
Open
dangle1 wants to merge 2 commits into
Open
tls_inspector: fix GREASE filtering in JA4_c signature algorithms#46658dangle1 wants to merge 2 commits into
dangle1 wants to merge 2 commits into
Conversation
The JA4 fingerprint's third component hashes the ClientHello's extension list joined to its signature_algorithms list. Per the JA4 spec, GREASE codepoints must be excluded everywhere they appear -- including in signature_algorithms. `getJA4ExtensionHash` already applies `isNotGrease` to extension type IDs, and `getJA4CipherHash`, `countCiphers`, and `countExtensions` apply it to their respective inputs. The signature_algorithms collection loop was the sole exception, pushing every 16-bit codepoint from the extension body unconditionally. Clients that inject a GREASE value into signature_algorithms (e.g. Chrome's per-handshake random GREASE selection) therefore produce a different JA4_c hash per connection while all other parts of the fingerprint are identical -- resulting in many-to-one hash collapse when compared to spec-compliant implementations. Guard the `sig_algs.push_back` call with `isNotGrease(sig_alg)`, matching the treatment already applied elsewhere in the file. Adds a regression test that asserts JA4 fingerprint equality between two ClientHellos that differ only in the presence of a GREASE codepoint in signature_algorithms. Spec reference: https://github.com/FoxIO-LLC/ja4/blob/main/technical_details/JA4.md Note: this change was drafted with AI assistance and reviewed by the author. Signed-off-by: dangle <dangle@pinterest.com>
dangle1
had a problem deploying
to
external-contributors
August 11, 2026 22:04 — with
GitHub Actions
Error
|
Hi @dangle1, welcome and thank you for your contribution. We will try to review your Pull Request as quickly as possible. In the meantime, please take a look at the contribution guidelines if you have not done so already. |
Extend the JA4 GREASE-in-signature_algorithms fix with two integration tests that exercise the full wire-bytes -> ClientHello parse -> fingerprint pipeline: 1. In tls_inspector_ja4_test.cc, add a new JA4_TEST_VECTORS entry "Browser-1-Grease-SigAlg" derived from the existing Browser-1 capture. It injects one GREASE codepoint (0x0a0a) at the head of the signature_algorithms extension body and shrinks the trailing padding extension by the same 2 bytes to preserve outer record and handshake lengths. The expected fingerprint matches Browser-1's exactly, so the parameterized suite proves the GREASE codepoint is stripped at every layer of the listener-filter pipeline (mocked recv -> Filter -> ssl early callback -> JA4Fingerprinter::create -> setJA4Hash). 2. In ja4_fingerprint_test.cc, add a companion test that decodes the same captured hex, uses BoringSSL's SSL_parse_client_hello to populate an SSL_CLIENT_HELLO, and asserts JA4Fingerprinter::create returns the expected spec-conformant fingerprint. Requires adding an ssl external dep and //source/common/ssl:ssl_lib for the SSL_SELECT macro. Both tests fail without the sig-alg GREASE-filter fix in getJA4ExtensionHash. Note: this change was drafted with AI assistance and reviewed by the author. Signed-off-by: dangle <dangle@pinterest.com>
dangle1
requested a deployment
to
external-contributors
August 13, 2026 17:46 — with
GitHub Actions
Waiting
KBaichoo
reviewed
Aug 15, 2026
Comment on lines
+245
to
+247
| if (isNotGrease(sig_alg)) { | ||
| sig_algs.push_back(sig_alg); | ||
| } |
Contributor
There was a problem hiding this comment.
probably worth runtime guarding in-case it breaks anyone operationally
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The JA4 fingerprint's third component hashes the ClientHello's extension list joined to its
signature_algorithmslist. Per the JA4 spec, GREASE codepoints must be excluded everywhere they appear — including insignature_algorithms.getJA4ExtensionHashalready appliesisNotGreaseto extension type IDs, andgetJA4CipherHash,countCiphers, andcountExtensionsapply it to their respective inputs. Thesignature_algorithmscollection loop was the sole exception, pushing every 16-bit codepoint from the extension body unconditionally.Clients that inject a GREASE value into
signature_algorithms(e.g. Chrome's per-handshake random GREASE selection, drawn from the 16 reserved code points0x0a0a,0x1a1a, …,0xfafa) therefore produce a different JA4_c hash per connection while all other parts of the fingerprint are identical — resulting in many-to-one hash collapse when compared against spec-compliant implementations.Fix
Guard the
sig_algs.push_back(sig_alg)call ingetJA4ExtensionHashwithisNotGrease(sig_alg), matching the treatment already applied everywhere else in the file.Test plan
TEST(JA4Fingerprinter, GreaseValueFilteredFromSignatureAlgorithms)inja4_fingerprint_test.ccthat constructs two `SSL_CLIENT_HELLO`s identical except for a GREASE codepoint (`0x0a0a`) in `signature_algorithms` and asserts `JA4Fingerprinter::create` produces the same fingerprint for both.Notes