Skip to content

Reject non-ASCII characters in GraphQL name validation - #10389

Merged
glen-84 merged 1 commit into
mainfrom
gai/reject-non-ascii-graphql-names
Sep 14, 2026
Merged

glen-84 merged 1 commit into
mainfrom
gai/reject-non-ascii-graphql-names

Conversation

@glen-84

@glen-84 glen-84 commented Sep 14, 2026

Copy link
Copy Markdown
Member

Summary

NameUtils compared characters by casting char to byte. The cast is unchecked, so any code point above U+00FF was truncated to its low byte, and a character whose low byte happens to be an ASCII letter or digit passed as one. U+0141 truncates to A, U+0157 to W, and U+0130 to 0.

Three public members inherited the hole: IsValidGraphQLName returned true for a name the parser rejects, MakeValidGraphQLName returned such a name unchanged, and EnsureGraphQLName accepted it instead of throwing.

"Łar".IsValidGraphQLName()            // true
NameUtils.MakeValidGraphQLName("Łar") // "Łar", unchanged
Utf8GraphQLParser.Parse("query Łar { a }")
// SyntaxException: Unexpected character `Å` (197)

The two char overloads now compare the ASCII ranges directly instead of delegating to the byte overloads, which are correct as they stand and are what the UTF-8 reader paths use.

This is a tightening, so it is worth knowing where it lands. EnsureGraphQLName is the validation behind most Fusion and Mutable type definitions and now throws where it used to accept. MakeValidGraphQLName is what DefaultNamingConventions and NameFormattingHelpers use to derive a GraphQL name from a CLR type or member name, so a CLR identifier carrying such a character previously produced a schema the parser would reject and now sanitizes it to an underscore.

Test plan

  • NameUtilsTests gains three code points on the existing invalid-name theory, covering a counterfeit letter in the leading position (U+0141), a counterfeit letter mid-name (U+0157), and a counterfeit digit mid-name (U+0130), plus a new theory for MakeValidGraphQLName. All six cases fail before the change.
  • dotnet test src/HotChocolate/Primitives/test/Primitives.Tests passes, 22 tests.
  • Every area that calls EnsureGraphQLName or MakeValidGraphQLName passes: Mutable 123, ApolloFederation 130, Data 1102, and Core 8020.
  • No snapshot moved, because nothing in the repo derives a GraphQL name from a CLR identifier containing such a character.
  • A micro-benchmark over realistic GraphQL names puts the two forms within noise of each other, 12.3 to 13.8 ns per name for the new form against 11.7 to 14.8 ns for the old. Building the predicates on char.IsAsciiLetterOrDigit instead measured consistently slower, around 15.1 ns.

Copilot AI lite review requested due to automatic review settings September 14, 2026 11:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No unresolved blocking issues were identified.

Pull request overview

Tightens GraphQL name validation to reject non-ASCII characters previously accepted due to unchecked char-to-byte conversion.

Changes:

  • Adds direct ASCII validation checks.
  • Adds regression tests for validation and sanitization.
File summaries
File Description
src/HotChocolate/Primitives/test/Primitives.Tests/NameUtilsTests.cs Adds non-ASCII validation and sanitization tests.
src/HotChocolate/Primitives/src/Primitives/Utilities/NameUtils.cs Corrects GraphQL name validation predicates.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

Copy link
Copy Markdown
Contributor

Patch coverage

100.0% of changed lines covered (2/2)

File Covered Changed Patch %
…/Primitives/src/Primitives/Utilities/NameUtils.cs 2 2 100.0% 🟢

Project coverage: 57.9% (288295/497915 lines)

@glen-84
glen-84 merged commit 8fb539a into main Sep 14, 2026
152 checks passed
@glen-84
glen-84 deleted the gai/reject-non-ascii-graphql-names branch September 14, 2026 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants