JSPM

  • Created
  • Published
  • Downloads 7735741
  • Score
    100M100P100Q214398F
  • License MIT

very fast object redaction

Package Exports

  • fast-redact

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (fast-redact) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

fast-redact

very fast object redaction

Build Status

Default Usage

By default, fast-redact serializes an object with JSON.stringify, censoring any data at paths specified:

const fastRedact = require('fast-redact')
const fauxRequest = {
  headers: {
    host: 'http://example.com',
    cookie: `oh oh we don't want this exposed in logs in etc.`,
    referer: `if we're cool maybe we'll even redact this`
  }
}
const redact = fastRedact({
  paths: ['headers.cookie', 'headers.referer']
})

console.log(redact(fauxRequest))
// {"headers":{"host":"http://example.com","cookie":"[REDACTED]","referer":"[REDACTED]"}}

API

require('fast-redact')({paths, censor, serialize})

When called without any options, or with a zero length paths array, fast-redact will return JSON.stringify or the serialize option, if set.

pathsArray

An array of strings describing the nested location of a key in an object.

The syntax follows that of the EcmaScript specification, that is any JavaScript path is accepted – both bracket and dot notation is supported. For instance in each of the following cases, the c property will be redacted: a.b.c,a['b'].c, a["b"].c, a[``b``].c. Since bracket notation is supported, array indices are also supported a[0].b would redact the b key in the first object of the a array.

Wildcards

In addition to static paths, asterisk wildcards are also supported.

When an asterisk is place in the final position it will redact all keys within the parent object. For instance a.b.* will redact all keys in the b object. Similarly for arrays a.b[*] will redact all elements of an array (in truth it actually doesn't matter whether b is in an object or array in either case, both notation styles will work).

When an asterisk is in an intermediate or first position, the paths following the asterisk will be redacted for every object within the parent.

For example:

const fastRedact = require('fast-redact')
const redact = fastRedact({paths: ['*.c.d']})
const obj = {
  x: {c: {d: 'hide me', e: 'leave me be'}},
  y: {c: {d: 'and me', f: 'I want to live'}},
  z: {c: {d: 'and also I', g: 'I want to run in a stream'}}
}
console.log(redact(obj)) 
// {"x":{"c":{"d":"[REDACTED]","e":"leave me be"}},"y":{"c":{"d":"[REDACTED]","f":"I want to live"}},"z":{"c":{"d":"[REDACTED]","g":"I want to run in a stream"}}}

Another example with a nested array:

const fastRedact = require('..')
const redact = fastRedact({paths: ['a[*].c.d']})
const obj = {
  a: [
    {c: {d: 'hide me', e: 'leave me be'}},
    {c: {d: 'and me', f: 'I want to live'}},
    {c: {d: 'and also I', g: 'I want to run in a stream'}}
  ]
}
console.log(redact(obj)) 
// {"a":[{"c":{"d":"[REDACTED]","e":"leave me be"}},{"c":{"d":"[REDACTED]","f":"I want to live"}},{"c":{"d":"[REDACTED]","g":"I want to run in a stream"}}]}

censor – <Any type - Except Function>('[REDACTED]')

This is the value which overwrites redacted properties. It can be any type, except a function.

Setting censor to undefined will cause properties to removed as long as this is the behavior of the serializer – which defaults to JSON.stringify, which does remove undefined properties.

Supplying a function as a censor will cause fast-redact to throw. This means a function censor to be introduced in the future without it being a breaking change.

serialize – Function | Boolean(JSON.stringify)

The serialize option may be a function of a boolean. If a function is supplied, this will be used to serialize the redacted object. It's important to understand that for performance reasons fast-redact mutates the original object, then serializes, then restores the original values. So the object passed to the serializer is the exact same object passed to the redacting function.

The serialize option as a function example:

const fastRedact = require('fast-redact')
const redact = fastRedact({
  paths: ['a'], 
  serialize: (o) => JSON.stringify(o, 0, 2)
})
console.log(redact({a: 1, b: 2}))
// {
//   "a": "[REDACTED]",
//   "b": 2
// }

For advanced usage the serialize option can be set to false. When serialize is set to false, instead of the serialized object, the output of the redactor function will be the mutated object itself (this is the exact same as the object passed in). In addition a restore method is supplied on the redactor function allowing the redacted keys to be restored with the original data.

const fastRedact = require('fast-redact')
const redact = fastRedact({
  paths: ['a'], 
  serialize: false
})
const o = {a: 1, b: 2}
console.log(redact(o) === o) // true
console.log(o) // { a: '[REDACTED]', b: 2 }
console.log(redact.restore(o) === o) // true
console.log(o) // { a: 1, b: 2 }

Benchmarks

The fastest known predecessor to fast-redact is the non-generic pino-noir library (which was also written by myself).

In the direct calling case, fast-redact is over 25x faster than pino-noir, however a more realistic comparison is overhead on JSON.stringify.

For a static redaction case (no wildcards) pino-noir adds ~28% overhead on top of JSON.stringify whereas fast-redact adds ~2% overhead.

In the basic last-position wildcard case,fast-redact is ~5% faster than pino-noir, and intermediate wildcard redaction (which pino-noir does not support) is still faster than the pino-noir basic wildcard case.

npm run bench 
benchNoirV2*500: 52.387ms
benchFastRedact*500: 2.361ms
benchFastRedactRestore*500: 13.715ms
benchNoirV2Wild*500: 75.820ms
benchFastRedactWild*500: 29.813ms
benchFastRedactWildRestore*500: 36.182ms
benchFastRedactIntermediateWild*500: 185.323ms
benchFastRedactIntermediateWildRestore*500: 73.520ms
benchJSONStringify*500: 268.861ms
benchNoirV2Serialize*500: 372.731ms
benchFastRedactSerialize*500: 273.265ms
benchNoirV2WildSerialize*500: 330.679ms
benchFastRedactWildSerialize*500: 312.374ms
benchFastRedactIntermediateWildSerialize*500: 325.921ms

Tests

npm test  
  190 passing (569.525ms)

Coverage

npm run cov 
-----------------|----------|----------|----------|----------|-------------------|
File             |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------------|----------|----------|----------|----------|-------------------|
All files        |      100 |      100 |      100 |      100 |                   |
 fast-redact     |      100 |      100 |      100 |      100 |                   |
  index.js       |      100 |      100 |      100 |      100 |                   |
 fast-redact/lib |      100 |      100 |      100 |      100 |                   |
  modifiers.js   |      100 |      100 |      100 |      100 |                   |
  parse.js       |      100 |      100 |      100 |      100 |                   |
  redactor.js    |      100 |      100 |      100 |      100 |                   |
  restorer.js    |      100 |      100 |      100 |      100 |                   |
  rx.js          |      100 |      100 |      100 |      100 |                   |
  state.js       |      100 |      100 |      100 |      100 |                   |
  validator.js   |      100 |      100 |      100 |      100 |                   |
-----------------|----------|----------|----------|----------|-------------------|

License

MIT

Acknowledgements

Sponsored by nearForm