Skip to content

Commit

Permalink
fix: Integrity#match prioritizes overlapping hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
wraithgar committed Apr 11, 2023
1 parent dce3dab commit 4e94d15
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 17 deletions.
43 changes: 28 additions & 15 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,12 @@ class IntegrityStream extends MiniPass {

if (!this.sri) {
this.algorithm = null
} else if (this.sri.isIntegrity) {
this.goodSri = !this.sri.isEmpty()

if (this.goodSri) {
this.algorithm = this.sri.pickAlgorithm(this.opts)
}
} else if (this.sri.isHash) {
this.goodSri = true
this.algorithm = this.sri.algorithm
} else {
this.goodSri = !this.sri.isEmpty()
this.algorithm = this.sri.pickAlgorithm(this.opts)
}

this.digests = this.goodSri ? this.sri[this.algorithm] : null
Expand Down Expand Up @@ -184,8 +181,13 @@ class Hash {
if (!other) {
return false
}
if (other instanceof Integrity) {
const algo = other.pickAlgorithm(opts)
if (other.isIntegrity) {
const algo = other.pickAlgorithm(opts, [this.algorithm])

if (!algo) {
return false
}

const foundHash = other[algo].find(hash => hash.digest === this.digest)

if (foundHash) {
Expand Down Expand Up @@ -323,8 +325,9 @@ class Integrity {
if (!other) {
return false
}
const algo = other.pickAlgorithm(opts)
const algo = other.pickAlgorithm(opts, Object.keys(this))
return (
!!algo &&
this[algo] &&
other[algo] &&
this[algo].find(hash =>
Expand All @@ -335,12 +338,22 @@ class Integrity {
) || false
}

pickAlgorithm (opts) {
// Pick the highest priority algorithm present, optionally also limited to a
// set of hashes found in another integrity. When limiting it may return
// nothing.
pickAlgorithm (opts, hashes) {
const pickAlgorithm = opts?.pickAlgorithm || getPrioritizedHash
const keys = Object.keys(this)
return keys.reduce((acc, algo) => {
return pickAlgorithm(acc, algo) || acc
const keys = Object.keys(this).filter(k => {
if (hashes?.length) {
return hashes.includes(k)
}
return true
})
if (keys.length) {
return keys.reduce((acc, algo) => pickAlgorithm(acc, algo) || acc)
}
// no intersection between this and hashes,
return null
}
}

Expand Down Expand Up @@ -550,7 +563,7 @@ function createIntegrity (opts) {
}
}

const NODE_HASHES = new Set(crypto.getHashes())
const NODE_HASHES = crypto.getHashes()

// This is a Best Effort™ at a reasonable priority for hash algos
const DEFAULT_PRIORITY = [
Expand All @@ -560,7 +573,7 @@ const DEFAULT_PRIORITY = [
'sha3',
'sha3-256', 'sha3-384', 'sha3-512',
'sha3_256', 'sha3_384', 'sha3_512',
].filter(algo => NODE_HASHES.has(algo))
].filter(algo => NODE_HASHES.includes(algo))

function getPrioritizedHash (algo1, algo2) {
/* eslint-disable-next-line max-len */
Expand Down
9 changes: 7 additions & 2 deletions test/match.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ function hash (data, algorithm) {
}

test('hashes should match when valid', t => {
const sha = hash(TEST_DATA, 'sha512')
const integrity = `sha512-${sha}`
const integrity = `sha512-${hash(TEST_DATA, 'sha512')}`
const otherIntegrity = `sha512-${hash('mismatch', 'sha512')}`
const parsed = ssri.parse(integrity, { single: true })
t.same(
parsed.match(integrity, { single: true }),
Expand Down Expand Up @@ -47,5 +47,10 @@ test('hashes should match when valid', t => {
false,
'null integrity just returns false'
)
t.same(
parsed.match(otherIntegrity),
false,
'should not match with a totally different integrity'
)
t.end()
})

0 comments on commit 4e94d15

Please sign in to comment.