From 1d66bc7490c91aa7edc3532edf5e7ea432ab37a6 Mon Sep 17 00:00:00 2001 From: Jelmer van der Linde Date: Wed, 10 Aug 2022 19:14:06 +0100 Subject: [PATCH] Implement matchRequestIntegrity --- lib/fetch/index.js | 26 ++++++++++++++++++++++++-- lib/fetch/util.js | 4 +++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/fetch/index.js b/lib/fetch/index.js index f9b09547edb..3884b6d5c24 100644 --- a/lib/fetch/index.js +++ b/lib/fetch/index.js @@ -721,7 +721,9 @@ async function mainFetch (fetchParams, recursive = false) { } // 3. Let processBody given bytes be these steps: - const processBody = (bytes) => { + const processBody = async (response) => { + const bytes = await readBodyToArrayBuffer(response) + // 1. If bytes do not match request’s integrity metadata, // then run processBodyError and abort these steps. [SRI] if (!matchRequestIntegrity(request, bytes)) { @@ -739,7 +741,7 @@ async function mainFetch (fetchParams, recursive = false) { // 4. Fully read response’s body given processBody and processBodyError. try { - processBody(await response.arrayBuffer()) + processBody(response) } catch (err) { processBodyError(err) } @@ -749,6 +751,26 @@ async function mainFetch (fetchParams, recursive = false) { } } +async function readBodyToArrayBuffer (response) { + const size = parseInt(response.headersList.get('content-length')) + const bytes = new Uint8Array(size) + + const reader = response.body.stream.getReader() + let offset = 0 + + while (true) { + const { done, value } = await reader.read() + if (done) { + break + } else { + bytes.set(value, offset) + offset += value.length + } + } + + return bytes +} + // https://fetch.spec.whatwg.org/#concept-scheme-fetch // given a fetch params fetchParams async function schemeFetch (fetchParams) { diff --git a/lib/fetch/util.js b/lib/fetch/util.js index 9806e331871..35a84fc229f 100644 --- a/lib/fetch/util.js +++ b/lib/fetch/util.js @@ -4,6 +4,7 @@ const { redirectStatus } = require('./constants') const { performance } = require('perf_hooks') const { isBlobLike, toUSVString, ReadableStreamFrom } = require('../core/util') const assert = require('assert') +const { createHash } = require('crypto') let File @@ -340,7 +341,8 @@ function determineRequestsReferrer (request) { } function matchRequestIntegrity (request, bytes) { - return false + const [algo, expectedHashValue] = request.integrity.split('-', 2) + return createHash(algo).update(bytes).digest('hex') === expectedHashValue } // https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request