You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
docs: Unsafe example for converting a message.url to an URL #52494
TypeError: Invalid URL
at new URL (node:internal/url:775:36)
at Server.<anonymous> (file:///server.js:3:26)
at Server.emit (node:events:518:28)
at parserOnIncoming (node:_http_server:1151:12)
at HTTPParser.parserOnHeadersComplete (node:_http_common:119:17) {
code: 'ERR_INVALID_URL',
input: '//',
base: 'http://localhost:3000'
}
changed the title [-]Unsafe example for converting a `message.url` to an `URL`[/-][+]docs: Unsafe example for converting a `message.url` to an `URL`[/+]on Apr 12, 2024
A better approach would it be to concatenate the host with the req.url instead of using the baseUrl parameter from the URL constructor.
I don't think it is a good idea. It is not better than the current example.
'use strict';consthttp=require('http');constserver=http.createServer();server.on('request',function(request,response){console.log(`http://${request.headers.host}${request.url}`);response.end();});server.listen(function(){const{ port }=server.address();constrequest=http.request({headers: {host: 'evil.com'},path: '/foo/bar',
port
});request.on('response',function(response){response.resume();});request.end()});
@lpinca your approach showcases to modify HOST header on server side but atleast the above solution is good enough for client side solutions since HOST header is controlled by the browsers and also "//" as path will crash the server.
the above solution provided by @mlegenhausen does seem to be a good practice in most cases atleast better than current examples
You can't make assumption about the client. There is not crash here
'use strict';consthttp=require('http');constserver=http.createServer();server.on('request',function(request,response){console.log(`http://${request.headers.host}${request.url}`);response.end();});server.listen(function(){const{ port }=server.address();constrequest=http.request({path: '//',
port
});request.on('response',function(response){response.resume();});request.end()});
@lpinca you are missing the point you need, it's about parsing the URL with
new URL(request.url, http://${request.headers.host}) // this is shown in docs
vs
new URL(http://${req.headers.host}${req.url})) // this is purposed solution
the later approach does not crash the code, do test all scenarios yourself
The proposed solution crashes just like the original one and is not safer either.
'use strict';consthttp=require('http');constnet=require('net');constserver=http.createServer();server.on('request',function(request,response){newURL(`http://${request.headers.host}${request.url}`);response.end();});server.listen(function(){const{ port }=server.address();constsocket=net.createConnection({ port });socket.on('connect',function(){socket.write(['GET / HTTP/1.1','Host:','\r\n'].join('\r\n'));});});
@lpinca I did not say it is perfect URL() constructor always throw error if parsing fails which crashes the server. this is same as before where you pointed out and rewrote HOST from server side.
I am not trying to say this is perfect solution but this is better than the current example as it does handle more scenarios.
I am not trying to say this is perfect solution but this is better than the current example as it does handle more scenarios.
What are those scenarios? It fails exactly like original one. You simply cannot trust the Host header as it is provided by the user. It does not matter if new URL(request.url, http://${request.headers.host}) or new URL(`http://${req.headers.host}${req.url})`) is used. They both fails in the same way if the Host header is not validated.
Thanks for your feedback. It seems in general that the concatenation has no serious flaws over the baseUrl approach.
Thanks @lpinca for pointing out the Host header I didn't had that on my watch. You are right as we can manipulate both values so both approaches are equal unsafe in theory.
In the real world I would still think that the manipulation of IncomingMessage#url leads to errors that are much more common in practice than the one of a manipulated Host header as you break the routing to the target system when the application is deployed like in a cloud environment. This will of course not fit for all scenarios.
If we would replace the Host header with a static baseUrl like http://localhost we would still have the same issues. Then my approach is superior. Maybe we could improve the docs in the following way:
Activity
[-]Unsafe example for converting a `message.url` to an `URL`[/-][+]docs: Unsafe example for converting a `message.url` to an `URL`[/+]avivkeller commentedon Apr 12, 2024
Great issue! Your issue suggested a fix (which is excellent!). If you'd like, you can also make a PR for it, or a community member can do it.
doc: correct unsafe URL example in http docs
lpinca commentedon Apr 15, 2024
I don't think it is a good idea. It is not better than the current example.
thisalihassan commentedon Apr 15, 2024
@lpinca your approach showcases to modify HOST header on server side but atleast the above solution is good enough for client side solutions since HOST header is controlled by the browsers and also "//" as path will crash the server.
the above solution provided by @mlegenhausen does seem to be a good practice in most cases atleast better than current examples
lpinca commentedon Apr 15, 2024
You can't make assumption about the client. There is not crash here
thisalihassan commentedon Apr 15, 2024
@lpinca you are missing the point you need, it's about parsing the URL with
new URL(request.url,
http://${request.headers.host}) // this is shown in docsvs
new URL(
http://${req.headers.host}${req.url})) // this is purposed solutionthe later approach does not crash the code, do test all scenarios yourself
lpinca commentedon Apr 15, 2024
The proposed solution crashes just like the original one and is not safer either.
thisalihassan commentedon Apr 15, 2024
@lpinca I did not say it is perfect URL() constructor always throw error if parsing fails which crashes the server. this is same as before where you pointed out and rewrote HOST from server side.
I am not trying to say this is perfect solution but this is better than the current example as it does handle more scenarios.
Moreover thanks for pointing out different cases.
lpinca commentedon Apr 15, 2024
What are those scenarios? It fails exactly like original one. You simply cannot trust the
Hostheader as it is provided by the user. It does not matter ifnew URL(request.url, http://${request.headers.host})ornew URL(`http://${req.headers.host}${req.url})`)is used. They both fails in the same way if theHostheader is not validated.mlegenhausen commentedon Apr 16, 2024
Thanks for your feedback. It seems in general that the concatenation has no serious flaws over the
baseUrlapproach.Thanks @lpinca for pointing out the
Hostheader I didn't had that on my watch. You are right as we can manipulate both values so both approaches are equal unsafe in theory.In the real world I would still think that the manipulation of
IncomingMessage#urlleads to errors that are much more common in practice than the one of a manipulatedHostheader as you break the routing to the target system when the application is deployed like in a cloud environment. This will of course not fit for all scenarios.If we would replace the
Hostheader with a staticbaseUrllikehttp://localhostwe would still have the same issues. Then my approach is superior. Maybe we could improve the docs in the following way:So we remove the whole manipulated
Hostheader scenario and fix the relative url resolution.WDYT?
avivkeller commentedon Apr 16, 2024
Uses
process.envisn't a bad idea, but it's probably better heard over at #52536 (which is the PR where it could be implemented)avivkeller commentedon Apr 21, 2024
Congrats on the merged PR!
I'm closing this issue as completed, but if you disagree, please let me know
doc: correct unsafe URL example in http docs
mlegenhausen commentedon Apr 25, 2024
Thanks guys. I must say it was a pleasant process to contribute to nodeJS.
doc: correct unsafe URL example in http docs
doc: correct unsafe URL example in http docs
doc: correct unsafe URL example in http docs