Skip to content

Fix double-encoding of escaped string variables in multipart uploads#9810

Open
BickelLukas wants to merge 1 commit into
ChilliCream:mainfrom
Consolidate-Software:multipart-text-encoding
Open

Fix double-encoding of escaped string variables in multipart uploads#9810
BickelLukas wants to merge 1 commit into
ChilliCream:mainfrom
Consolidate-Software:multipart-text-encoding

Conversation

@BickelLukas
Copy link
Copy Markdown

Summary

When a GraphQL multipart request (graphql-multipart-request-spec) is processed, HttpMultipartMiddleware rewrites the operations JSON to inject file references in place of the null placeholders. During this rewrite, any string variable that was not a file was copied using writer.WriteStringValue(reader.ValueSpan).

ValueSpan returns the raw, still-escaped JSON bytes, while WriteStringValue(ReadOnlySpan<byte>) treats its input as unescaped text and escapes it again. The result is that every escape sequence in a string variable was doubled.

For example, a variable with the value test " test (JSON: "test \" test") was rewritten to "test \\\" test", so the resolver received test \" test instead of test " test. The same applied to any backslash, newline, unicode escape, etc.

Fix

Decode the value before writing it back, but keep a zero-allocation fast path when no escaping is involved:

case JsonTokenType.String:
    if (reader.ValueIsEscaped)
    {
        writer.WriteStringValue(reader.GetString());
    }
    else
    {
        writer.WriteStringValue(reader.ValueSpan);
    }
    break;
  • Escaped values are decoded with GetString() so the writer re-escapes them correctly.
  • Unescaped values still take the raw-span path, avoiding the string allocation in the common case.

Tests

Added Upload_File_With_Escaped_String_Variable_Is_Not_Double_Encoded, which sends a file upload alongside a string variable containing an escaped quote and asserts the resolver receives the original, correctly-decoded value. Verified on net8.0, net9.0, and net10.0.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jun 1, 2026

CLA assistant check
All committers have signed the CLA.

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

This PR fixes a bug in HttpMultipartMiddleware where rewriting the operations JSON for GraphQL multipart uploads could double-encode escaped string variables (e.g., turning \" into \\\"), causing resolvers to receive incorrect string values.

Changes:

  • Update JSON rewrite logic to decode escaped string tokens (ValueIsEscaped) via Utf8JsonReader.GetString() before writing, while retaining a zero-allocation path for unescaped strings.
  • Add an integration test covering multipart upload with a non-file string variable containing an escaped quote.
  • Extend the upload test query utilities with a resolver that echoes back the provided text alongside consuming the uploaded file.

Reviewed changes

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

File Description
src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpMultipartMiddlewareTests.cs Adds a regression test ensuring escaped string variables are not double-encoded during multipart operations rewrite.
src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/UploadQuery.cs Adds UploadWithText resolver used by the new test to validate the received string value.
src/HotChocolate/AspNetCore/src/AspNetCore.Pipeline/HttpMultipartMiddleware.cs Fixes string token copying to avoid re-escaping already-escaped JSON string content.

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

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.

3 participants