Skip to content

Fix HTTP response splitting via unvalidated reason phrase in dart:io - #63500

Open
Sengtocxoen wants to merge 1 commit into
dart-lang:mainfrom
Sengtocxoen:fix/reason-phrase-crlf-validation
Open

Fix HTTP response splitting via unvalidated reason phrase in dart:io#63500
Sengtocxoen wants to merge 1 commit into
dart-lang:mainfrom
Sengtocxoen:fix/reason-phrase-crlf-validation

Conversation

@Sengtocxoen

@Sengtocxoen Sengtocxoen commented Jun 2, 2026

Copy link
Copy Markdown

Problem

HttpResponse.reasonPhrase in dart:io accepts CRLF characters without validation. Every other HTTP wire-output API in the SDK validates against CRLF via _isValueChar() / _validateValue(). The reasonPhrase setter is the single gap.

An attacker who controls the value passed to reasonPhrase can inject CRLF sequences to split the HTTP response, injecting arbitrary headers and response bodies.

API consistency

// Headers: VALIDATED — throws FormatException on CRLF
response.headers.set('X-Test', 'value\r\nInjected'); // FormatException

// Reason phrase: NOT VALIDATED before this fix
response.reasonPhrase = 'OK\r\nInjected: header\r\n\r\n<script>alert(1)</script>'; // silently accepted

Fix

Adds CRLF validation to the reasonPhrase setter using the existing _HttpHeaders._isValidValueString() function — the same validation already applied to all header values in http_headers.dart.

 void set reasonPhrase(String reasonPhrase) {
   if (_outgoing.headersWritten) throw StateError("Header already sent");
+  var errorAt = _HttpHeaders._isValidValueString(reasonPhrase);
+  if (errorAt >= 0) {
+    throw FormatException(
+      "Invalid HTTP reason phrase",
+      reasonPhrase,
+      errorAt,
+    );
+  }
   _reasonPhrase = reasonPhrase;
 }

Zero new validation infrastructure — reuses the existing _isValidValueString() that rejects bytes <= 31 (CR, LF, NUL) except HT.

Impact

  • Header injection: Set-Cookie, Access-Control-Allow-Origin, CSP override
  • Response body injection / XSS: CRLF + CRLF terminates headers, body controlled by attacker
  • Cache poisoning: Inject a complete second HTTP response into the stream

Validation

headers.set('X', 'a\r\nb')FormatException (existing, correct behavior)
reasonPhrase = 'OK\r\n...' → now also throws FormatException (new, consistent)

@google-cla

google-cla Bot commented Jun 2, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@mraleph

mraleph commented Jun 2, 2026

Copy link
Copy Markdown
Member

Please fix CLA issue and make sure to add a regression test.

@Sengtocxoen
Sengtocxoen force-pushed the fix/reason-phrase-crlf-validation branch from e9f9254 to 37a9fab Compare June 2, 2026 08:44
@copybara-service

Copy link
Copy Markdown

Thank you for your contribution! This project uses Gerrit for code reviews. Your pull request has automatically been converted into a code review at:

https://dart-review.googlesource.com/c/sdk/+/508540

Please wait for a developer to review your code review at the above link; you can speed up the review if you sign into Gerrit and manually add a reviewer that has recently worked on the relevant code. See CONTRIBUTING.md to learn how to upload changes to Gerrit directly.

Additional commits pushed to this PR will update both the PR and the corresponding Gerrit CL. After the review is complete on the CL, your reviewer will merge the CL (automatically closing this PR).

@copybara-service

Copy link
Copy Markdown

Thank you for your contribution! This project uses Gerrit for code reviews. Your pull request has automatically been converted into a code review at:

https://dart-review.googlesource.com/c/sdk/+/508560

Please wait for a developer to review your code review at the above link; you can speed up the review if you sign into Gerrit and manually add a reviewer that has recently worked on the relevant code. See CONTRIBUTING.md to learn how to upload changes to Gerrit directly.

Additional commits pushed to this PR will update both the PR and the corresponding Gerrit CL. After the review is complete on the CL, your reviewer will merge the CL (automatically closing this PR).

@mraleph

mraleph commented Jun 8, 2026

Copy link
Copy Markdown
Member

Please add a regression test, as I have asked above.

@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

1 similar comment
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

@Sengtocxoen

Copy link
Copy Markdown
Author

I miss the test first time, i hope it ok now

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

@mraleph

mraleph commented Jun 22, 2026

Copy link
Copy Markdown
Member

@Sengtocxoen would you like to fix test failures?

@Sengtocxoen
Sengtocxoen force-pushed the fix/reason-phrase-crlf-validation branch from 1fa0e1b to 22245af Compare June 22, 2026 13:35
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

1 similar comment
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

1 similar comment
@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

@mraleph

mraleph commented Jul 1, 2026

Copy link
Copy Markdown
Member

@Sengtocxoen would you like to fix test failures? (also when addressing test failures please rerun tests locally to make sure you have fixed all things!)

Sengtocxoen added a commit to Sengtocxoen/sdk that referenced this pull request Jul 2, 2026
HttpResponse.reasonPhrase was written verbatim into the status line
without validation. A reason phrase containing CR/LF (or other control
characters) allowed injecting arbitrary headers and body content into
the response stream (HTTP response splitting / request smuggling).

Validate the reason phrase in the setter with the same
_isValidValueString check used for header values, throwing a
FormatException on any disallowed control character.

Closes dart-lang#63500
@Sengtocxoen
Sengtocxoen force-pushed the fix/reason-phrase-crlf-validation branch from 22245af to 0fc4e5d Compare July 2, 2026 01:35
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

1 similar comment
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

Sengtocxoen added a commit to Sengtocxoen/sdk that referenced this pull request Jul 2, 2026
HttpResponse.reasonPhrase was written verbatim into the status line
without validation. A reason phrase containing CR/LF (or other control
characters) allowed injecting arbitrary headers and body content into
the response stream (HTTP response splitting / request smuggling).

Validate the reason phrase in the setter with the same
_isValidValueString check used for header values, throwing a
FormatException on any disallowed control character.

Closes dart-lang#63500
@Sengtocxoen
Sengtocxoen force-pushed the fix/reason-phrase-crlf-validation branch from 0fc4e5d to bb9fca5 Compare July 2, 2026 01:43
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

Sengtocxoen added a commit to Sengtocxoen/sdk that referenced this pull request Jul 2, 2026
HttpResponse.reasonPhrase was written verbatim into the status line
without validation. A reason phrase containing CR/LF (or other control
characters) allowed injecting arbitrary headers and body content into
the response stream (HTTP response splitting / request smuggling).

Validate the reason phrase in the setter with the same
_isValidValueString check used for header values, throwing a
FormatException on any disallowed control character.

Closes dart-lang#63500
@Sengtocxoen
Sengtocxoen force-pushed the fix/reason-phrase-crlf-validation branch from bb9fca5 to 531448b Compare July 2, 2026 02:13
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

HttpResponse.reasonPhrase was written verbatim into the status line
without validation. A reason phrase containing CR/LF (or other control
characters) allowed injecting arbitrary headers and body content into
the response stream (HTTP response splitting / request smuggling).

Validate the reason phrase in the setter with the same
_isValidValueString check used for header values, throwing a
FormatException on any disallowed control character.

Closes dart-lang#63500

Change-Id: I61a50424f7f7a55c3b4240d01f4cce8dc3187edc
Sengtocxoen added a commit to Sengtocxoen/sdk that referenced this pull request Jul 2, 2026
HttpResponse.reasonPhrase was written verbatim into the status line
without validation. A reason phrase containing CR/LF (or other control
characters) allowed injecting arbitrary headers and body content into
the response stream (HTTP response splitting / request smuggling).

Validate the reason phrase in the setter with the same
_isValidValueString check used for header values, throwing a
FormatException on any disallowed control character.

Closes dart-lang#63500

Change-Id: I61a50424f7f7a55c3b4240d01f4cce8dc3187edc
@Sengtocxoen
Sengtocxoen force-pushed the fix/reason-phrase-crlf-validation branch from 531448b to 636ca3f Compare July 2, 2026 02:23
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

1 similar comment
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

@Sengtocxoen

Copy link
Copy Markdown
Author

@mraleph i think i broke some things that the CL don't run the checking for me any more, can you help me that. Thank you a lot

@copybara-service

Copy link
Copy Markdown

CL has been abandoned, possibly because it was rejected. Please refer to the CL for more information.

@mraleph

mraleph commented Aug 12, 2026

Copy link
Copy Markdown
Member

This needs to be rebased. You can just delete changes to CHANGELOG.md, they are not necessary.

Sengtocxoen added a commit to Sengtocxoen/sdk that referenced this pull request Aug 12, 2026
HttpResponse.reasonPhrase was written verbatim into the status line
without validation. A reason phrase containing CR/LF (or other control
characters) allowed injecting arbitrary headers and body content into
the response stream (HTTP response splitting / request smuggling).

Validate the reason phrase in the setter with the same
_isValidValueString check used for header values, throwing a
FormatException on any disallowed control character.

Closes dart-lang#63500

Change-Id: I61a50424f7f7a55c3b4240d01f4cce8dc3187edc
@Sengtocxoen
Sengtocxoen force-pushed the fix/reason-phrase-crlf-validation branch from b6e9ab4 to f3b5fb7 Compare August 12, 2026 09:56
@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

@copybara-service

Copy link
Copy Markdown

https://dart-review.googlesource.com/c/sdk/+/508560 has been updated with the latest commits from this pull request.

@copybara-service

Copy link
Copy Markdown

Gerrit CL has build or test failures, please review them in Gerrit and fix them before requesting another review.

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.

3 participants