Socket
Socket
Sign inDemoInstall

ssri

Package Overview
Dependencies
1
Maintainers
6
Versions
38
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 10.0.1 to 10.0.2

177

lib/index.js

@@ -6,3 +6,4 @@ 'use strict'

const SPEC_ALGORITHMS = ['sha256', 'sha384', 'sha512']
const SPEC_ALGORITHMS = ['sha512', 'sha384', 'sha256']
const DEFAULT_ALGORITHMS = ['sha512']

@@ -16,25 +17,9 @@ // TODO: this should really be a hardcoded list of algorithms we support,

const defaultOpts = {
algorithms: ['sha512'],
error: false,
options: [],
pickAlgorithm: getPrioritizedHash,
sep: ' ',
single: false,
strict: false,
}
const getOptString = options => options?.length ? `?${options.join('?')}` : ''
const ssriOpts = (opts = {}) => ({ ...defaultOpts, ...opts })
class IntegrityStream extends MiniPass {
#emittedIntegrity
#emittedSize
#emittedVerified
const getOptString = options => !options || !options.length
? ''
: `?${options.join('?')}`
const _onEnd = Symbol('_onEnd')
const _getOptions = Symbol('_getOptions')
const _emittedSize = Symbol('_emittedSize')
const _emittedIntegrity = Symbol('_emittedIntegrity')
const _emittedVerified = Symbol('_emittedVerified')
class IntegrityStream extends MiniPass {
constructor (opts) {

@@ -46,6 +31,6 @@ super()

// may be overridden later, but set now for class consistency
this[_getOptions]()
this.#getOptions()
// options used for calculating stream. can't be changed.
const { algorithms = defaultOpts.algorithms } = opts
const algorithms = opts?.algorithms || DEFAULT_ALGORITHMS
this.algorithms = Array.from(

@@ -57,29 +42,23 @@ new Set(algorithms.concat(this.algorithm ? [this.algorithm] : []))

[_getOptions] () {
const {
integrity,
size,
options,
} = { ...defaultOpts, ...this.opts }
#getOptions () {
// For verification
this.sri = integrity ? parse(integrity, this.opts) : null
this.expectedSize = size
this.sri = this.opts?.integrity ? parse(this.opts?.integrity, this.opts) : null
this.expectedSize = this.opts?.size
this.goodSri = this.sri ? !!Object.keys(this.sri).length : false
this.algorithm = this.goodSri ? this.sri.pickAlgorithm(this.opts) : null
this.digests = this.goodSri ? this.sri[this.algorithm] : null
this.optString = getOptString(options)
this.optString = getOptString(this.opts?.options)
}
on (ev, handler) {
if (ev === 'size' && this[_emittedSize]) {
return handler(this[_emittedSize])
if (ev === 'size' && this.#emittedSize) {
return handler(this.#emittedSize)
}
if (ev === 'integrity' && this[_emittedIntegrity]) {
return handler(this[_emittedIntegrity])
if (ev === 'integrity' && this.#emittedIntegrity) {
return handler(this.#emittedIntegrity)
}
if (ev === 'verified' && this[_emittedVerified]) {
return handler(this[_emittedVerified])
if (ev === 'verified' && this.#emittedVerified) {
return handler(this.#emittedVerified)
}

@@ -92,3 +71,3 @@

if (ev === 'end') {
this[_onEnd]()
this.#onEnd()
}

@@ -104,5 +83,5 @@ return super.emit(ev, data)

[_onEnd] () {
#onEnd () {
if (!this.goodSri) {
this[_getOptions]()
this.#getOptions()
}

@@ -132,8 +111,8 @@ const newSri = parse(this.hashes.map((h, i) => {

} else {
this[_emittedSize] = this.size
this.#emittedSize = this.size
this.emit('size', this.size)
this[_emittedIntegrity] = newSri
this.#emittedIntegrity = newSri
this.emit('integrity', newSri)
if (match) {
this[_emittedVerified] = match
this.#emittedVerified = match
this.emit('verified', match)

@@ -151,4 +130,3 @@ }

constructor (hash, opts) {
opts = ssriOpts(opts)
const strict = !!opts.strict
const strict = opts?.strict
this.source = hash.trim()

@@ -172,3 +150,3 @@

}
if (strict && !SPEC_ALGORITHMS.some(a => a === match[1])) {
if (strict && !SPEC_ALGORITHMS.includes(match[1])) {
return

@@ -194,4 +172,3 @@ }

toString (opts) {
opts = ssriOpts(opts)
if (opts.strict) {
if (opts?.strict) {
// Strict mode enforces the standard as close to the foot of the

@@ -202,3 +179,3 @@ // letter as it can.

// https://www.w3.org/TR/CSP2/#source-list-syntax
SPEC_ALGORITHMS.some(x => x === this.algorithm) &&
SPEC_ALGORITHMS.includes(this.algorithm) &&
// Usually, if someone insists on using a "different" base64, we

@@ -217,9 +194,39 @@ // leave it as-is, since there's multiple standards, and the

}
const options = this.options && this.options.length
? `?${this.options.join('?')}`
: ''
return `${this.algorithm}-${this.digest}${options}`
return `${this.algorithm}-${this.digest}${getOptString(this.options)}`
}
}
function integrityHashToString (toString, sep, opts, hashes) {
const toStringIsNotEmpty = toString !== ''
let shouldAddFirstSep = false
let complement = ''
const lastIndex = hashes.length - 1
for (let i = 0; i < lastIndex; i++) {
const hashString = Hash.prototype.toString.call(hashes[i], opts)
if (hashString) {
shouldAddFirstSep = true
complement += hashString
complement += sep
}
}
const finalHashString = Hash.prototype.toString.call(hashes[lastIndex], opts)
if (finalHashString) {
shouldAddFirstSep = true
complement += finalHashString
}
if (toStringIsNotEmpty && shouldAddFirstSep) {
return toString + sep + complement
}
return toString + complement
}
class Integrity {

@@ -239,17 +246,24 @@ get isIntegrity () {

toString (opts) {
opts = ssriOpts(opts)
let sep = opts.sep || ' '
if (opts.strict) {
let sep = opts?.sep || ' '
let toString = ''
if (opts?.strict) {
// Entries must be separated by whitespace, according to spec.
sep = sep.replace(/\S+/g, ' ')
for (const hash of SPEC_ALGORITHMS) {
if (this[hash]) {
toString = integrityHashToString(toString, sep, opts, this[hash])
}
}
} else {
for (const hash of Object.keys(this)) {
toString = integrityHashToString(toString, sep, opts, this[hash])
}
}
return Object.keys(this).map(k => {
return this[k].map(hash => {
return Hash.prototype.toString.call(hash, opts)
}).filter(x => x.length).join(sep)
}).filter(x => x.length).join(sep)
return toString
}
concat (integrity, opts) {
opts = ssriOpts(opts)
const other = typeof integrity === 'string'

@@ -268,3 +282,2 @@ ? integrity

merge (integrity, opts) {
opts = ssriOpts(opts)
const other = parse(integrity, opts)

@@ -285,3 +298,2 @@ for (const algo in other) {

match (integrity, opts) {
opts = ssriOpts(opts)
const other = parse(integrity, opts)

@@ -304,4 +316,3 @@ if (!other) {

pickAlgorithm (opts) {
opts = ssriOpts(opts)
const pickAlgorithm = opts.pickAlgorithm
const pickAlgorithm = opts?.pickAlgorithm || getPrioritizedHash
const keys = Object.keys(this)

@@ -319,3 +330,2 @@ return keys.reduce((acc, algo) => {

}
opts = ssriOpts(opts)
if (typeof sri === 'string') {

@@ -335,3 +345,3 @@ return _parse(sri, opts)

// https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata
if (opts.single) {
if (opts?.single) {
return new Hash(integrity, opts)

@@ -355,3 +365,2 @@ }

function stringify (obj, opts) {
opts = ssriOpts(opts)
if (obj.algorithm && obj.digest) {

@@ -368,4 +377,3 @@ return Hash.prototype.toString.call(obj, opts)

function fromHex (hexDigest, algorithm, opts) {
opts = ssriOpts(opts)
const optString = getOptString(opts.options)
const optString = getOptString(opts?.options)
return parse(

@@ -380,5 +388,4 @@ `${algorithm}-${

function fromData (data, opts) {
opts = ssriOpts(opts)
const algorithms = opts.algorithms
const optString = getOptString(opts.options)
const algorithms = opts?.algorithms || DEFAULT_ALGORITHMS
const optString = getOptString(opts?.options)
return algorithms.reduce((acc, algo) => {

@@ -406,3 +413,2 @@ const digest = crypto.createHash(algo).update(data).digest('base64')

function fromStream (stream, opts) {
opts = ssriOpts(opts)
const istream = integrityStream(opts)

@@ -424,6 +430,5 @@ return new Promise((resolve, reject) => {

function checkData (data, sri, opts) {
opts = ssriOpts(opts)
sri = parse(sri, opts)
if (!sri || !Object.keys(sri).length) {
if (opts.error) {
if (opts?.error) {
throw Object.assign(

@@ -442,3 +447,4 @@ new Error('No valid integrity hashes to check against'), {

const match = newSri.match(sri, opts)
if (match || !opts.error) {
opts = opts || {}
if (match || !(opts.error)) {
return match

@@ -467,3 +473,3 @@ } else if (typeof opts.size === 'number' && (data.length !== opts.size)) {

function checkStream (stream, sri, opts) {
opts = ssriOpts(opts)
opts = opts || Object.create(null)
opts.integrity = sri

@@ -493,3 +499,3 @@ sri = parse(sri, opts)

module.exports.integrityStream = integrityStream
function integrityStream (opts = {}) {
function integrityStream (opts = Object.create(null)) {
return new IntegrityStream(opts)

@@ -500,5 +506,4 @@ }

function createIntegrity (opts) {
opts = ssriOpts(opts)
const algorithms = opts.algorithms
const optString = getOptString(opts.options)
const algorithms = opts?.algorithms || DEFAULT_ALGORITHMS
const optString = getOptString(opts?.options)

@@ -505,0 +510,0 @@ const hashes = algorithms.map(crypto.createHash)

{
"name": "ssri",
"version": "10.0.1",
"version": "10.0.2",
"description": "Standard Subresource Integrity library -- parses, serializes, generates, and verifies integrity metadata according to the SRI spec.",

@@ -54,3 +54,3 @@ "main": "lib/index.js",

"@npmcli/eslint-config": "^4.0.0",
"@npmcli/template-oss": "4.10.0",
"@npmcli/template-oss": "4.13.0",
"tap": "^16.0.1"

@@ -63,4 +63,5 @@ },

"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"version": "4.10.0"
"version": "4.13.0",
"publish": "true"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc