Skip to content

Commit

Permalink
fetch: don't set an invalid origin header (#3235)
Browse files Browse the repository at this point in the history
* don't set an invalid origin header (fetch)

* fixup

* fixup

* fixup
  • Loading branch information
KhafraDev committed May 9, 2024
1 parent 71bf81b commit 0a66d30
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 15 deletions.
3 changes: 1 addition & 2 deletions lib/web/fetch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,7 @@ function fetching ({
// 9. If request’s origin is "client", then set request’s origin to request’s
// client’s origin.
if (request.origin === 'client') {
// TODO: What if request.client is null?
request.origin = request.client?.origin
request.origin = request.client.origin
}

// 10. If all of the following conditions are true:
Expand Down
32 changes: 20 additions & 12 deletions lib/web/fetch/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,16 +255,23 @@ function appendFetchMetadata (httpRequest) {

// https://fetch.spec.whatwg.org/#append-a-request-origin-header
function appendRequestOriginHeader (request) {
// 1. Let serializedOrigin be the result of byte-serializing a request origin with request.
// 1. Let serializedOrigin be the result of byte-serializing a request origin
// with request.
// TODO: implement "byte-serializing a request origin"
let serializedOrigin = request.origin

// 2. If request’s response tainting is "cors" or request’s mode is "websocket", then append (`Origin`, serializedOrigin) to request’s header list.
if (request.responseTainting === 'cors' || request.mode === 'websocket') {
if (serializedOrigin) {
request.headersList.append('origin', serializedOrigin, true)
}
// "'client' is changed to an origin during fetching."
// This doesn't happen in undici (in most cases) because undici, by default,
// has no concept of origin.
if (serializedOrigin === 'client') {
return
}

// 2. If request’s response tainting is "cors" or request’s mode is "websocket",
// then append (`Origin`, serializedOrigin) to request’s header list.
// 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
if (request.responseTainting === 'cors' || request.mode === 'websocket') {
request.headersList.append('origin', serializedOrigin, true)
} else if (request.method !== 'GET' && request.method !== 'HEAD') {
// 1. Switch on request’s referrer policy:
switch (request.referrerPolicy) {
Expand All @@ -275,13 +282,16 @@ function appendRequestOriginHeader (request) {
case 'no-referrer-when-downgrade':
case 'strict-origin':
case 'strict-origin-when-cross-origin':
// If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`.
// If request’s origin is a tuple origin, its scheme is "https", and
// request’s current URL’s scheme is not "https", then set
// serializedOrigin to `null`.
if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) {
serializedOrigin = null
}
break
case 'same-origin':
// If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null`.
// If request’s origin is not same origin with request’s current URL’s
// origin, then set serializedOrigin to `null`.
if (!sameOrigin(request, requestCurrentURL(request))) {
serializedOrigin = null
}
Expand All @@ -290,10 +300,8 @@ function appendRequestOriginHeader (request) {
// Do nothing.
}

if (serializedOrigin) {
// 2. Append (`Origin`, serializedOrigin) to request’s header list.
request.headersList.append('origin', serializedOrigin, true)
}
// 2. Append (`Origin`, serializedOrigin) to request’s header list.
request.headersList.append('origin', serializedOrigin, true)
}
}

Expand Down
3 changes: 2 additions & 1 deletion lib/web/websocket/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ try {
* @param {(response: any) => void} onEstablish
* @param {Partial<import('../../types/websocket').WebSocketInit>} options
*/
function establishWebSocketConnection (url, protocols, ws, onEstablish, options) {
function establishWebSocketConnection (url, protocols, client, ws, onEstablish, options) {
// 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s
// scheme is "ws", and to "https" otherwise.
const requestURL = url
Expand All @@ -48,6 +48,7 @@ function establishWebSocketConnection (url, protocols, ws, onEstablish, options)
// and redirect mode is "error".
const request = makeRequest({
urlList: [requestURL],
client,
serviceWorkers: 'none',
referrer: 'no-referrer',
mode: 'websocket',
Expand Down
2 changes: 2 additions & 0 deletions lib/web/websocket/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class WebSocket extends EventTarget {
this[kWebSocketURL] = new URL(urlRecord.href)

// 11. Let client be this's relevant settings object.
const client = environmentSettingsObject.settingsObject

// 12. Run this step in parallel:

Expand All @@ -132,6 +133,7 @@ class WebSocket extends EventTarget {
this[kController] = establishWebSocketConnection(
urlRecord,
protocols,
client,
this,
(response) => this.#onConnectionEstablished(response),
options
Expand Down
25 changes: 25 additions & 0 deletions test/fetch/issue-rsshub-15532.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict'

const { once } = require('node:events')
const { createServer } = require('node:http')
const { test } = require('node:test')
const { fetch } = require('../..')
const { tspl } = require('@matteo.collina/tspl')

// https://github.com/DIYgod/RSSHub/issues/15532
test('An invalid Origin header is not set', async (t) => {
const { deepStrictEqual } = tspl(t, { plan: 1 })

const server = createServer((req, res) => {
deepStrictEqual(req.headers.origin, undefined)

res.end()
}).listen(0)

await once(server, 'listening')
t.after(server.close.bind(server))

await fetch(`http://localhost:${server.address().port}`, {
method: 'POST'
})
})

0 comments on commit 0a66d30

Please sign in to comment.