Socket
Socket
Sign inDemoInstall

ssri

Package Overview
Dependencies
3
Maintainers
9
Versions
39
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 7.0.1 to 7.1.0

12

CHANGELOG.md

@@ -5,2 +5,14 @@ # Changelog

## [7.1.0](https://github.com/npm/ssri/compare/v7.0.1...v7.1.0) (2019-10-24)
### Bug Fixes
* Do not blow up if the opts object is mutated ([806e8c8](https://github.com/npm/ssri/commit/806e8c8))
### Features
* Add Integrity#merge method ([0572c1d](https://github.com/npm/ssri/commit/0572c1d)), closes [#4](https://github.com/npm/ssri/issues/4)
### [7.0.1](https://github.com/npm/ssri/compare/v7.0.0...v7.0.1) (2019-09-30)

@@ -7,0 +19,0 @@

78

index.js

@@ -26,2 +26,7 @@ 'use strict'

const getOptString = options => !options || !options.length ? ''
: `?${options.join('?')}`
const _onEnd = Symbol('_onEnd')
const _getOptions = Symbol('_getOptions')
class IntegrityStream extends MiniPass {

@@ -32,8 +37,7 @@ constructor (opts) {

this.opts = opts
// For verification
this.sri = opts.integrity && parse(opts.integrity, opts)
this.goodSri = this.sri && Object.keys(this.sri).length
this.algorithm = this.goodSri && this.sri.pickAlgorithm(opts)
this.digests = this.goodSri && this.sri[this.algorithm]
// Calculating stream
// may be overridden later, but set now for class consistency
this[_getOptions]()
// options used for calculating stream. can't be changed.
this.algorithms = Array.from(

@@ -43,7 +47,17 @@ new Set(opts.algorithms.concat(this.algorithm ? [this.algorithm] : []))

this.hashes = this.algorithms.map(crypto.createHash)
this.onEnd = this.onEnd.bind(this)
}
[_getOptions] () {
const opts = this.opts
// For verification
this.sri = opts.integrity ? parse(opts.integrity, opts) : null
this.expectedSize = opts.size
this.goodSri = this.sri ? !!Object.keys(this.sri).length : false
this.algorithm = this.goodSri ? this.sri.pickAlgorithm(opts) : null
this.digests = this.goodSri ? this.sri[this.algorithm] : null
this.optString = getOptString(opts.options)
}
emit (ev, data) {
if (ev === 'end') this.onEnd()
if (ev === 'end') this[_onEnd]()
return super.emit(ev, data)

@@ -58,19 +72,19 @@ }

onEnd () {
const optString = (this.opts.options && this.opts.options.length)
? `?${this.opts.options.join('?')}`
: ''
[_onEnd] () {
if (!this.goodSri) {
this[_getOptions]()
}
const newSri = parse(this.hashes.map((h, i) => {
return `${this.algorithms[i]}-${h.digest('base64')}${optString}`
return `${this.algorithms[i]}-${h.digest('base64')}${this.optString}`
}).join(' '), this.opts)
// Integrity verification mode
const match = this.goodSri && newSri.match(this.sri, this.opts)
if (typeof this.opts.size === 'number' && this.size !== this.opts.size) {
const err = new Error(`stream size mismatch when checking ${this.sri}.\n Wanted: ${this.opts.size}\n Found: ${this.size}`)
if (typeof this.expectedSize === 'number' && this.size !== this.expectedSize) {
const err = new Error(`stream size mismatch when checking ${this.sri}.\n Wanted: ${this.expectedSize}\n Found: ${this.size}`)
err.code = 'EBADSIZE'
err.found = this.size
err.expected = this.opts.size
err.expected = this.expectedSize
err.sri = this.sri
this.emit('error', err)
} else if (this.opts.integrity && !match) {
} else if (this.sri && !match) {
const err = new Error(`${this.sri} integrity checksum failed when using ${this.algorithm}: wanted ${this.digests} but got ${newSri}. (${this.size} bytes)`)

@@ -191,2 +205,20 @@ err.code = 'EINTEGRITY'

// add additional hashes to an integrity value, but prevent
// *changing* an existing integrity hash.
merge (integrity, opts) {
opts = SsriOpts(opts)
const other = parse(integrity, opts)
for (const algo in other) {
if (this[algo]) {
if (!this[algo].find(hash =>
other[algo].find(otherhash =>
hash.digest === otherhash.digest))) {
throw new Error('hashes do not match, cannot update integrity')
}
} else {
this[algo] = other[algo]
}
}
}
match (integrity, opts) {

@@ -268,5 +300,3 @@ opts = SsriOpts(opts)

opts = SsriOpts(opts)
const optString = opts.options && opts.options.length
? `?${opts.options.join('?')}`
: ''
const optString = getOptString(opts.options)
return parse(

@@ -283,5 +313,3 @@ `${algorithm}-${

const algorithms = opts.algorithms
const optString = opts.options && opts.options.length
? `?${opts.options.join('?')}`
: ''
const optString = getOptString(opts.options)
return algorithms.reduce((acc, algo) => {

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

const algorithms = opts.algorithms
const optString = opts.options.length
? `?${opts.options.join('?')}`
: ''
const optString = getOptString(opts.options)

@@ -390,0 +416,0 @@ const hashes = algorithms.map(crypto.createHash)

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

@@ -41,3 +41,3 @@ "main": "index.js",

"figgy-pudding": "^3.5.1",
"minipass": "^3.0.0"
"minipass": "^3.1.1"
},

@@ -47,3 +47,3 @@ "devDependencies": {

"standard-version": "^7.0.0",
"tap": "^14.6.9",
"tap": "^14.8.2",
"weallbehave": "^1.2.0",

@@ -50,0 +50,0 @@ "weallcontribute": "^1.0.8"

@@ -22,2 +22,3 @@ # ssri [![npm version](https://img.shields.io/npm/v/ssri.svg)](https://npm.im/ssri) [![license](https://img.shields.io/npm/l/ssri.svg)](https://npm.im/ssri) [![Travis](https://img.shields.io/travis/npm/ssri.svg)](https://travis-ci.org/npm/ssri) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/npm/ssri?svg=true)](https://ci.appveyor.com/project/npm/ssri) [![Coverage Status](https://coveralls.io/repos/github/npm/ssri/badge.svg?branch=latest)](https://coveralls.io/github/npm/ssri?branch=latest)

* [`Integrity#concat`](#integrity-concat)
* [`Integrity#merge`](#integrity-merge)
* [`Integrity#toString`](#integrity-to-string)

@@ -188,2 +189,41 @@ * [`Integrity#toJSON`](#integrity-to-json)

#### <a name="integrity-merge"></a> `> Integrity#merge(otherIntegrity, [opts])`
Safely merges another IntegrityLike or integrity string into an `Integrity`
object.
If the other integrity value has any algorithms in common with the current
object, then the hash digests must match, or an error is thrown.
Any new hashes will be added to the current object's set.
This is useful when an integrity value may be upgraded with a stronger
algorithm, you wish to prevent accidentally supressing integrity errors by
overwriting the expected integrity value.
##### Example
```javascript
const data = fs.readFileSync('data.txt')
// integrity.txt contains 'sha1-X1UT+IIv2+UUWvM7ZNjZcNz5XG4='
// because we were young, and didn't realize sha1 would not last
const expectedIntegrity = ssri.parse(fs.readFileSync('integrity.txt', 'utf8'))
const match = ssri.checkData(data, expectedIntegrity, {
algorithms: ['sha512', 'sha1']
})
if (!match) {
throw new Error('data corrupted or something!')
}
// get a stronger algo!
if (match && match.algorithm !== 'sha512') {
const updatedIntegrity = ssri.fromData(data, { algorithms: ['sha512'] })
expectedIntegrity.merge(updatedIntegrity)
fs.writeFileSync('integrity.txt', expectedIntegrity.toString())
// file now contains
// 'sha1-X1UT+IIv2+UUWvM7ZNjZcNz5XG4= sha512-yzd8ELD1piyANiWnmdnpCL5F52f10UfUdEkHywVZeqTt0ymgrxR63Qz0GB7TKPoeeZQmWCaz7T1+9vBnypkYWg=='
}
```
#### <a name="integrity-to-string"></a> `> Integrity#toString([opts]) -> String`

@@ -190,0 +230,0 @@

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