Skip to content

HTTP/2 requests with an invalid :path header are not rejected #57988

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sapphi-red opened this issue Apr 23, 2025 · 0 comments
Open

HTTP/2 requests with an invalid :path header are not rejected #57988

sapphi-red opened this issue Apr 23, 2025 · 0 comments

Comments

@sapphi-red
Copy link
Contributor

sapphi-red commented Apr 23, 2025

Version

22.14.0

Platform

Linux DESKTOP-TJ5RQRK 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

  1. Save the following script as server.mjs
  2. Run node server.mjs
  3. Run curl --request-target /#/ --http2-prior-knowledge -v http://localhost:3000
  4. req.url /#/ /#/ is output and the curl successfully receives Hello World
import http2 from 'node:http2'

const server = http2.createServer((req, res) => {
  console.log('req.url', req.url, req.headers[':path'])
  res.writeHead(200, { 'Content-Type': 'text/plain' })
  res.end('Hello World\n')
})
server.listen(3000)

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior? Why is that the expected behavior?

The request to be rejected with PROTOCOL_ERROR.

In the HTTP/2 spec (RFC9113), it is specified that requests MUST include one valid value for :path pseudo-header field and if the request omits it, the request is considered as malformed (8.3.1).
If the request is malformed, it is specified that it MUST be treated as a stream error of type PROTOCOL_ERROR (8.1.1).

But Node.js does not return an error when the :path header contained #, which makes the :path header invalid.

:path header field consists of absolute-path part and query part (8.3.1).
Neither of them can contain # and thus :path header that contains # is invalid.

absolute-path = 1*( "/" segment )
segment = <segment, see [URI], Section 3.3>
query = <query, see [URI], Section 3.4>
(quoted from RFC9110 4.1)

segment = *pchar
query = ( pchar / "/" / "?" )
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "
" / "+" / "," / ";" / "="
(quoted from RFC3986 Appendix A)

What do you see instead?

The request is not rejected and the response "Hello World" is output.

Additional information

I first reported on HackerOne just in case this might be treated as a security bug (SECURITY.md) and was redirected to make a public issue. I found this behavior when fixing GHSA-356w-63v5-8wf4.

Related behaviors:

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

No branches or pull requests

1 participant