Skip to content

graphql: Improve GraphQL fingerprinting with specificity scoring#7118

Draft
kingthorin wants to merge 1 commit intozaproxy:mainfrom
kingthorin:copilot/improve-fingerprint-detection
Draft

graphql: Improve GraphQL fingerprinting with specificity scoring#7118
kingthorin wants to merge 1 commit intozaproxy:mainfrom
kingthorin:copilot/improve-fingerprint-detection

Conversation

@kingthorin
Copy link
Copy Markdown
Member

@kingthorin kingthorin commented Feb 8, 2026

Overview

Implements specificity-based ordering for GraphQL framework fingerprinting to increase efficiency and potentially reduce false positives by checking specific patterns before generic ones.

This is one of a set of PRs that I'm working on for GraphQL Fingerprinting.


This also fixes a bug whereby the handlers were always reset on instantiation when they should have only been reset if null. So the Tech Detection support had been broken. (I can move that fix to a separate PR if necessary.)

Changes

  • FingerprintCheck record: Encapsulates each check with a specificity score (0-100), validated at construction
  • Descending order iteration: Checks run in order of decreasing specificity; first match wins
  • Refactored structure: Extracted performPatternBasedDetection() and raiseAlertForFramework() for clarity
  • Minor fix: Added null/JSON check in checkStrawberryEngine()

Specificity Tiers

Tier Score Description Examples
A 90-95 Unique error patterns tartiflette, hasura, dgraph
B 80-89 Distinctive patterns wpgraphql, absinthe, sangria
C 70-79 Language/framework hints graphql-java, gqlgen, juniper
D 60-69 Common GraphQL errors apollo, graphene, mercurius
E 50-59 Very generic lighthouse

Scoring Guidelines for Future Contributors

When adding a new fingerprint check, assign a specificity score based on how unique the matched pattern is to that specific framework:

  • 90+: Pattern includes framework name, unique identifiers, or error text that only that framework produces
  • 70-89: Pattern is distinctive (e.g., language-specific error format, unusual field names) but could theoretically appear elsewhere
  • 60-69: Pattern uses common GraphQL error structures that multiple frameworks might produce
  • 50-59: Pattern matches very generic errors; high false-positive risk

When in doubt, start lower—a false negative (missed detection) is less harmful than a false positive (wrong framework reported).

AI Disclosure

Portions of this contribution were prepared by copilot or augment code.

@github-actions

This comment was marked as resolved.

@psiinon
Copy link
Copy Markdown
Member

psiinon commented Feb 8, 2026

Logo
Checkmarx One – Scan Summary & Detailsdcbdf96f-e3de-463d-969d-96e964446403

New Issues (3)

Checkmarx found the following issues in this Pull Request

# Severity Issue Source File / Package Checkmarx Insight
1 LOW Unpinned Actions Full Length Commit SHA /codeql.yml: 31
detailsPinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA help...
2 LOW Unpinned Actions Full Length Commit SHA /codeql.yml: 35
detailsPinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA help...
3 LOW Unpinned Actions Full Length Commit SHA /codeql.yml: 50
detailsPinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA help...

Use @Checkmarx to interact with Checkmarx PR Assistant.
Examples:
@Checkmarx how are you able to help me?
@Checkmarx rescan this PR

Copy link
Copy Markdown
Contributor

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

Updates the GraphQL add-on’s framework fingerprinter to evaluate fingerprint checks in descending “specificity” order (most unique patterns first), aiming to reduce false positives and improve detection efficiency.

Changes:

  • Introduces a FingerprintCheck record with a validated specificity score and uses it to order fingerprint checks.
  • Refactors fingerprinting flow into performPatternBasedDetection() + raiseAlertForFramework() with first-match-wins behavior.
  • Extends unit tests with stricter “no logged WARN/ERROR” assertions and adds a Juniper detection/evidence test.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
addOns/graphql/src/main/java/org/zaproxy/addon/graphql/GraphQlFingerprinter.java Adds specificity-scored checks, sorts checks by score, refactors detection/alerting, and hardens Strawberry detection against non-JSON/null responses.
addOns/graphql/src/test/java/org/zaproxy/addon/graphql/GraphQlFingerprinterUnitTest.java Updates invalid-data expectations, introduces helper for asserting no logged errors, and adds a Juniper pattern/evidence test.

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

Comment thread addOns/graphql/src/main/java/org/zaproxy/addon/graphql/GraphQlFingerprinter.java Outdated
@kingthorin kingthorin force-pushed the copilot/improve-fingerprint-detection branch 2 times, most recently from 1ca02f1 to 2a39087 Compare February 8, 2026 03:19
@thc202 thc202 changed the title Improve GraphQL fingerprinting with specificity scoring graphql: Improve GraphQL fingerprinting with specificity scoring Feb 8, 2026
@thc202
Copy link
Copy Markdown
Member

thc202 commented Feb 8, 2026

Where's the data/evidence for the claims?

@kingthorin kingthorin force-pushed the copilot/improve-fingerprint-detection branch 3 times, most recently from 69803d7 to 3d103a6 Compare February 8, 2026 12:03
@kingthorin
Copy link
Copy Markdown
Member Author

First is the removed comment:
// TODO: Check whether the order of the fingerprint checks matters.

Logically if the checks can be classified as a range of specific to generic then the order does matter.

Further summary/sources: https://gist.github.com/kingthorin/53859ce98cbe73559898dfee355dd6df

Let me know if you'd like the gist content added here somewhere/somehow.

@thc202
Copy link
Copy Markdown
Member

thc202 commented Feb 8, 2026

It's not a logical conclusion since an error is only generic if there are more than one/many GraphQL engines producing those errors, neither your comment nor the gist provide data/evidence for that (where's the sample of errors from all/some of the engines being checked to claim that they are generic). If you read the quote in the gist it says respond uniquely which implies there's no overlap between the errors being triggered, if they are unique the order does not matter (I recall that we added more checks, not sure if all from the same source, but same requirement applies, to know if something is generic you need concrete data showing so). There's also the claims of efficiency and FPs (though the latter is covered by the error uniqueness or not).

@kingthorin
Copy link
Copy Markdown
Member Author

Point taken. I'll look at another way to tackle this that's more evidence based.

I'll move the small bug fix into another PR, convert this one to draft for now.

@kingthorin kingthorin marked this pull request as draft February 8, 2026 16:08
@kingthorin
Copy link
Copy Markdown
Member Author

To your other point the additional checks were from the same source as the originals.

Signed-off-by: kingthorin <kingthorin@users.noreply.github.com>
@kingthorin kingthorin force-pushed the copilot/improve-fingerprint-detection branch from 3d103a6 to b9803bb Compare February 8, 2026 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants