@ -59925,6 +59925,132 @@ function onConnectTimeout (socket) {
module . exports = buildConnector
/***/ } ) ,
/***/ 4462 :
/***/ ( ( module ) => {
"use strict" ;
/** @type {Record<string, string | undefined>} */
const headerNameLowerCasedRecord = { }
// https://developer.mozilla.org/docs/Web/HTTP/Headers
const wellknownHeaderNames = [
'Accept' ,
'Accept-Encoding' ,
'Accept-Language' ,
'Accept-Ranges' ,
'Access-Control-Allow-Credentials' ,
'Access-Control-Allow-Headers' ,
'Access-Control-Allow-Methods' ,
'Access-Control-Allow-Origin' ,
'Access-Control-Expose-Headers' ,
'Access-Control-Max-Age' ,
'Access-Control-Request-Headers' ,
'Access-Control-Request-Method' ,
'Age' ,
'Allow' ,
'Alt-Svc' ,
'Alt-Used' ,
'Authorization' ,
'Cache-Control' ,
'Clear-Site-Data' ,
'Connection' ,
'Content-Disposition' ,
'Content-Encoding' ,
'Content-Language' ,
'Content-Length' ,
'Content-Location' ,
'Content-Range' ,
'Content-Security-Policy' ,
'Content-Security-Policy-Report-Only' ,
'Content-Type' ,
'Cookie' ,
'Cross-Origin-Embedder-Policy' ,
'Cross-Origin-Opener-Policy' ,
'Cross-Origin-Resource-Policy' ,
'Date' ,
'Device-Memory' ,
'Downlink' ,
'ECT' ,
'ETag' ,
'Expect' ,
'Expect-CT' ,
'Expires' ,
'Forwarded' ,
'From' ,
'Host' ,
'If-Match' ,
'If-Modified-Since' ,
'If-None-Match' ,
'If-Range' ,
'If-Unmodified-Since' ,
'Keep-Alive' ,
'Last-Modified' ,
'Link' ,
'Location' ,
'Max-Forwards' ,
'Origin' ,
'Permissions-Policy' ,
'Pragma' ,
'Proxy-Authenticate' ,
'Proxy-Authorization' ,
'RTT' ,
'Range' ,
'Referer' ,
'Referrer-Policy' ,
'Refresh' ,
'Retry-After' ,
'Sec-WebSocket-Accept' ,
'Sec-WebSocket-Extensions' ,
'Sec-WebSocket-Key' ,
'Sec-WebSocket-Protocol' ,
'Sec-WebSocket-Version' ,
'Server' ,
'Server-Timing' ,
'Service-Worker-Allowed' ,
'Service-Worker-Navigation-Preload' ,
'Set-Cookie' ,
'SourceMap' ,
'Strict-Transport-Security' ,
'Supports-Loading-Mode' ,
'TE' ,
'Timing-Allow-Origin' ,
'Trailer' ,
'Transfer-Encoding' ,
'Upgrade' ,
'Upgrade-Insecure-Requests' ,
'User-Agent' ,
'Vary' ,
'Via' ,
'WWW-Authenticate' ,
'X-Content-Type-Options' ,
'X-DNS-Prefetch-Control' ,
'X-Frame-Options' ,
'X-Permitted-Cross-Domain-Policies' ,
'X-Powered-By' ,
'X-Requested-With' ,
'X-XSS-Protection'
]
for ( let i = 0 ; i < wellknownHeaderNames . length ; ++ i ) {
const key = wellknownHeaderNames [ i ]
const lowerCasedKey = key . toLowerCase ( )
headerNameLowerCasedRecord [ key ] = headerNameLowerCasedRecord [ lowerCasedKey ] =
lowerCasedKey
}
// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
Object . setPrototypeOf ( headerNameLowerCasedRecord , null )
module . exports = {
wellknownHeaderNames ,
headerNameLowerCasedRecord
}
/***/ } ) ,
/***/ 8045 :
@ -60757,6 +60883,7 @@ const { InvalidArgumentError } = __nccwpck_require__(8045)
const { Blob } = _ _nccwpck _require _ _ ( 4300 )
const nodeUtil = _ _nccwpck _require _ _ ( 3837 )
const { stringify } = _ _nccwpck _require _ _ ( 3477 )
const { headerNameLowerCasedRecord } = _ _nccwpck _require _ _ ( 4462 )
const [ nodeMajor , nodeMinor ] = process . versions . node . split ( '.' ) . map ( v => Number ( v ) )
@ -60966,6 +61093,15 @@ function parseKeepAliveTimeout (val) {
return m ? parseInt ( m [ 1 ] , 10 ) * 1000 : null
}
/ * *
* Retrieves a header name and returns its lowercase value .
* @ param { string | Buffer } value Header name
* @ returns { string }
* /
function headerNameToString ( value ) {
return headerNameLowerCasedRecord [ value ] || value . toLowerCase ( )
}
function parseHeaders ( headers , obj = { } ) {
// For H2 support
if ( ! Array . isArray ( headers ) ) return headers
@ -61237,6 +61373,7 @@ module.exports = {
isIterable ,
isAsyncIterable ,
isDestroyed ,
headerNameToString ,
parseRawHeaders ,
parseHeaders ,
parseKeepAliveTimeout ,
@ -67884,14 +68021,18 @@ const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(3983
const assert = _ _nccwpck _require _ _ ( 9491 )
const { isUint8Array } = _ _nccwpck _require _ _ ( 9830 )
let supportedHashes = [ ]
// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable
/** @type {import('crypto')|undefined} */
let crypto
try {
crypto = _ _nccwpck _require _ _ ( 6113 )
const possibleRelevantHashes = [ 'sha256' , 'sha384' , 'sha512' ]
supportedHashes = crypto . getHashes ( ) . filter ( ( hash ) => possibleRelevantHashes . includes ( hash ) )
/* c8 ignore next 3 */
} catch {
}
function responseURL ( response ) {
@ -68419,66 +68560,56 @@ function bytesMatch (bytes, metadataList) {
return true
}
// 3. If parsedMetadata is the empty set, return true.
// 3. If response is not eligible for integrity validation, return false.
// TODO
// 4. If parsedMetadata is the empty set, return true.
if ( parsedMetadata . length === 0 ) {
return true
}
// 4 . Let metadata be the result of getting the strongest
// 5 . Let metadata be the result of getting the strongest
// metadata from parsedMetadata.
const list = parsedMetadata . sort ( ( c , d ) => d . algo . localeCompare ( c . algo ) )
// get the strongest algorithm
const strongest = list [ 0 ] . algo
// get all entries that use the strongest algorithm; ignore weaker
const metadata = list . filter ( ( item ) => item . algo === strongest )
const strongest = getStrongestMetadata ( parsedMetadata )
const metadata = filterMetadataListByAlgorithm ( parsedMetadata , strongest )
// 5 . For each item in metadata:
// 6. For each item in metadata:
for ( const item of metadata ) {
// 1. Let algorithm be the alg component of item.
const algorithm = item . algo
// 2. Let expectedValue be the val component of item.
le t expectedValue = item . hash
cons t expectedValue = item . hash
// See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e
// "be liberal with padding". This is annoying, and it's not even in the spec.
if ( expectedValue . endsWith ( '==' ) ) {
expectedValue = expectedValue . slice ( 0 , - 2 )
}
// 3. Let actualValue be the result of applying algorithm to bytes.
let actualValue = crypto . createHash ( algorithm ) . update ( bytes ) . digest ( 'base64' )
if ( actualValue . endsWith ( '==' ) ) {
if ( actualValue [ actualValue . length - 1 ] === '=' ) {
if ( actualValue [ actualValue . length - 2 ] === '=' ) {
actualValue = actualValue . slice ( 0 , - 2 )
} else {
actualValue = actualValue . slice ( 0 , - 1 )
}
}
// 4. If actualValue is a case-sensitive match for expectedValue,
// return true.
if ( actualValue === expectedValue ) {
return true
}
let actualBase64URL = crypto . createHash ( algorithm ) . update ( bytes ) . digest ( 'base64url' )
if ( actualBase64URL . endsWith ( '==' ) ) {
actualBase64URL = actualBase64URL . slice ( 0 , - 2 )
}
if ( actualBase64URL === expectedValue ) {
if ( compareBase64Mixed ( actualValue , expectedValue ) ) {
return true
}
}
// 6 . Return false.
// 7. Return false.
return false
}
// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options
// https://www.w3.org/TR/CSP2/#source-list-syntax
// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1
const parseHashWithOptions = /( (?<algo>sha256|sha384|sha512)-(?<hash>[A-z0-9+/]{1}.*={0,2}))( +[\x21-\x7e] ?)?/i
const parseHashWithOptions = /( ?<algo>sha256|sha384|sha512)-((?<hash>[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*) ?)?/i
/ * *
* @ see https : //w3c.github.io/webappsec-subresource-integrity/#parse-metadata
@ -68492,8 +68623,6 @@ function parseMetadata (metadata) {
// 2. Let empty be equal to true.
let empty = true
const supportedHashes = crypto . getHashes ( )
// 3. For each token returned by splitting metadata on spaces:
for ( const token of metadata . split ( ' ' ) ) {
// 1. Set empty to false.
@ -68503,7 +68632,11 @@ function parseMetadata (metadata) {
const parsedToken = parseHashWithOptions . exec ( token )
// 3. If token does not parse, continue to the next token.
if ( parsedToken === null || parsedToken . groups === undefined ) {
if (
parsedToken === null ||
parsedToken . groups === undefined ||
parsedToken . groups . algo === undefined
) {
// Note: Chromium blocks the request at this point, but Firefox
// gives a warning that an invalid integrity was given. The
// correct behavior is to ignore these, and subsequently not
@ -68512,11 +68645,11 @@ function parseMetadata (metadata) {
}
// 4. Let algorithm be the hash-algo component of token.
const algorithm = parsedToken . groups . algo
const algorithm = parsedToken . groups . algo . toLowerCase ( )
// 5. If algorithm is a hash function recognized by the user
// agent, add the parsed token to result.
if ( supportedHashes . includes ( algorithm .toLowerCase ( ) )) {
if ( supportedHashes . includes ( algorithm )) {
result . push ( parsedToken . groups )
}
}
@ -68529,6 +68662,82 @@ function parseMetadata (metadata) {
return result
}
/ * *
* @ param { { algo : 'sha256' | 'sha384' | 'sha512' } [ ] } metadataList
* /
function getStrongestMetadata ( metadataList ) {
// Let algorithm be the algo component of the first item in metadataList.
// Can be sha256
let algorithm = metadataList [ 0 ] . algo
// If the algorithm is sha512, then it is the strongest
// and we can return immediately
if ( algorithm [ 3 ] === '5' ) {
return algorithm
}
for ( let i = 1 ; i < metadataList . length ; ++ i ) {
const metadata = metadataList [ i ]
// If the algorithm is sha512, then it is the strongest
// and we can break the loop immediately
if ( metadata . algo [ 3 ] === '5' ) {
algorithm = 'sha512'
break
// If the algorithm is sha384, then a potential sha256 or sha384 is ignored
} else if ( algorithm [ 3 ] === '3' ) {
continue
// algorithm is sha256, check if algorithm is sha384 and if so, set it as
// the strongest
} else if ( metadata . algo [ 3 ] === '3' ) {
algorithm = 'sha384'
}
}
return algorithm
}
function filterMetadataListByAlgorithm ( metadataList , algorithm ) {
if ( metadataList . length === 1 ) {
return metadataList
}
let pos = 0
for ( let i = 0 ; i < metadataList . length ; ++ i ) {
if ( metadataList [ i ] . algo === algorithm ) {
metadataList [ pos ++ ] = metadataList [ i ]
}
}
metadataList . length = pos
return metadataList
}
/ * *
* Compares two base64 strings , allowing for base64url
* in the second string .
*
* @ param { string } actualValue always base64
* @ param { string } expectedValue base64 or base64url
* @ returns { boolean }
* /
function compareBase64Mixed ( actualValue , expectedValue ) {
if ( actualValue . length !== expectedValue . length ) {
return false
}
for ( let i = 0 ; i < actualValue . length ; ++ i ) {
if ( actualValue [ i ] !== expectedValue [ i ] ) {
if (
( actualValue [ i ] === '+' && expectedValue [ i ] === '-' ) ||
( actualValue [ i ] === '/' && expectedValue [ i ] === '_' )
) {
continue
}
return false
}
}
return true
}
// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request
function tryUpgradeRequestToAPotentiallyTrustworthyURL ( request ) {
// TODO
@ -68944,7 +69153,8 @@ module.exports = {
urlHasHttpsScheme ,
urlIsHttpHttpsScheme ,
readAllBytes ,
normalizeMethodRecord
normalizeMethodRecord ,
parseMetadata
}
@ -71031,12 +71241,17 @@ function parseLocation (statusCode, headers) {
// https://tools.ietf.org/html/rfc7231#section-6.4.4
function shouldRemoveHeader ( header , removeContent , unknownOrigin ) {
return (
( header . length === 4 && header . toString ( ) . toLowerCase ( ) === 'host' ) ||
( removeContent && header . toString ( ) . toLowerCase ( ) . indexOf ( 'content-' ) === 0 ) ||
( unknownOrigin && header . length === 13 && header . toString ( ) . toLowerCase ( ) === 'authorization' ) ||
( unknownOrigin && header . length === 6 && header . toString ( ) . toLowerCase ( ) === 'cookie' )
)
if ( header . length === 4 ) {
return util . headerNameToString ( header ) === 'host'
}
if ( removeContent && util . headerNameToString ( header ) . startsWith ( 'content-' ) ) {
return true
}
if ( unknownOrigin && ( header . length === 13 || header . length === 6 || header . length === 19 ) ) {
const name = util . headerNameToString ( header )
return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization'
}
return false
}
// https://tools.ietf.org/html/rfc7231#section-6.4