npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@hackylabs/deep-redact

v2.2.0

Published

A fast, safe and configurable zero-dependency library for redacting strings or deeply redacting arrays and objects.

Downloads

3,371

Readme

Deep Redact

npm version GitHub license

Faster than Fast Redact 1 as well as being safer and more configurable than many other redaction solutions, Deep Redact is a zero-dependency tool that redacts sensitive information from strings and objects. It is designed to be used in a production environment where sensitive information needs to be redacted from logs, error messages, files, and other outputs. Supporting both strings and objects or a mix of both, Deep Redact can be used to redact sensitive information from more data structures than any other redaction library. Even partially redacting sensitive information from strings is supported, by way of custom regex patterns and replacers.

Circular references and other unsupported values are handled gracefully, and the library is designed to be as fast as possible while still being easy to use and configure.

Supporting both CommonJS and ESM, with named and default exports, Deep Redact is designed to be versatile and easy to use in any modern JavaScript or TypeScript project in Node or the browser.

ko-fi

Installation

npm install @hackylabs/deep-redact

Usage

// ./src/example.ts
import {DeepRedact} from '@hackylabs/deep-redact'; // If you're using CommonJS, import with require('@hackylabs/deep-redact') instead. Both CommonJS and ESM support named and default imports.

const objRedaction = new DeepRedact({
  blacklistedKeys: ['sensitive', 'password', /name/i],
})

const obj = {
  keepThis: 'This is fine',
  sensitive: 'This is not fine',
  user: {
    id: 1,
    password: '<h1><strong>Password</strong></h1>',
    firstName: 'John',
  }
}

// Recursively redact sensitive information from an object
objRedaction.redact(obj)
// {
//  keepThis: 'This is fine',
//  sensitive: '[REDACTED]',
//  user: {
//    id: 1,
//    password: '[REDACTED]',
//    firstName: '[REDACTED]'
//  }
// }

const strRedaction = new DeepRedact({
  partialStringTests: [
    {
      pattern: /<(email|password)>([^<]+)<\/\1>/gi,
      replacer: (value: string, pattern: RegExp) => value.replace(pattern, '<$1>[REDACTED]</$1>'),
    },
  ],
})

// Partially redact sensitive information from a string
strRedaction.redact('<email>[email protected]</email><keepThis>This is fine</keepThis><password>secret</password>')
// '<email>[REDACTED]</email><keepThis>This is fine</keepThis><password>[REDACTED]</password>'

Configuration

Main Options

| key | description | type | options | default | required | | --- | --- | --- | --- | --- | --- | | blacklistedKeys | Deeply compare names of these keys against the keys in your object. | array | Array<string│RegExp│BlacklistKeyConfig> | [] | N | | stringTests | Array of regular expressions to perform against string values, whether that value is a flat string or nested within an object. Will redact whole string values. If you want to redact only part of the string, use partialStringTests instead. If a replacer function is provided in the config for the associated test, it will be used to redact the value. | array | Array<RegExp│StringTestConfig> | [] | N | | partialStringTests | Array of regular expressions to perform against string values, whether that value is a flat string or nested within an object. Will redact only the matched part of the string using the replacer function provided in the config for the associated test. | array | StringTestConfig[] | [] | N | | fuzzyKeyMatch | Loosely compare key names by checking if the key name of your unredacted object is included anywhere within the name of your blacklisted key. For example, is "pass" (your key) included in "password" (from config). | boolean | | false | N | | caseSensitiveKeyMatch | Loosely compare key names by normalising the strings. This involves removing non-word characters and transforms the string to lowercase. This means you never have to worry having to list duplicate keys in different formats such as snake_case, camelCase, PascalCase or any other case. | boolean | | true | N | | remove | Determines whether or not to remove the key from the object when it is redacted. | boolean | | false | N | | retainStructure | Determines whether or not keep all nested values of a key that is going to be redacted. Circular references are always removed. | boolean | | false | N | | replacement | When a value is going to be redacted, what would you like to replace it with? | string │ function | | [REDACTED] | N | | replaceStringByLength | When a string value is going to be replaced, optionally replace it by repeating the replacement to match the length of the value. For example, if replaceStringByLength were set to true and replacement was set to "x", then redacting "secret" would return "xxxxxx". This is sometimes useful for debugging purposes, although it may be less secure as it could give hints to the original value. | boolean | | false | N | | types | JS types (values of typeof keyword). Only values with a typeof equal to string, number, bigint, boolean, symbol, object, or function will be redacted. Undefined values will never be redacted, although the type undefined is included in this list to keep TypeScript happy. | array | Array<'string'│'number'│'bigint'│'boolean'│'symbol'│'undefined'│'object'│'function'> | ['string'] | N | | serialise | Determines whether or not to serialise the object after redacting. Typical use cases for this are when you want to send it over the network or save to a file, both of which are common use cases for redacting sensitive information. | boolean | | false | N | | serialize | Alias of serialise for International-English users. | boolean | | false | N |

BlacklistKeyConfig

| key | type | default | required | | --- | --- | --- | --- | | key | string│RegExp | | Y | | fuzzyKeyMatch | boolean | Main options fuzzyKeyMatch | N | | caseSensitiveKeyMatch | boolean | Main options caseSensitiveKeyMatch | N | | remove | boolean | Main options remove | N | | retainStructure | boolean | Main options retainStructure | N |

StringTestConfig

| key | description | type | required | | --- | --- | --- | --- | | pattern | A regular expression to perform against a string value, whether that value is a flat string or nested within an object. | RegExp | Y | | replacer | A function that will be called with the value of the string that matched the pattern and the pattern itself. This function should return the new (redacted) value to replace the original value. | function | Y |

Benchmark

Comparisons are made against JSON.stringify, Regex.replace, Fast Redact & (one of my other creations, @hackylabs/obglob) as well as different configurations of Deep Redact, using this test object. Fast Redact was configured to redact the same keys on the same object as Deep Redact without using wildcards.

The benchmark is run on a 2021 iMac with an M1 chip with 16GB memory running macOS Sequoia 15.0.0.

JSON.stringify is included as a benchmark because it is the fastest way to deeply iterate over an object, although it doesn't redact any sensitive information.

Regex.replace is included as a benchmark because it is the fastest way to redact sensitive information from a string. However, a regex pattern for all keys to be redacted is much harder to configure than a dedicated redaction library, especially when dealing with multiple types of values. It also doesn't handle circular references or other unsupported values as gracefully as deep-redact unless a third-party library is used to stringify the object beforehand.

Fast-redact is included as a benchmark because it's the next fastest library available specifically for redaction.

Neither JSON.stringify, Regex.replace nor Fast Redact offer the same level of configurability as deep-redact. Both Fast Redact and Obglob are slower and rely on dependencies.

Benchmark

| scenario | ops / sec | op duration (ms) | margin of error | sample count | | --- | --- | --- | --- | --- | | DeepRedact, partial redaction | 178183.03 | 0.0056122067 | 0.00003 | 89092 | | JSON.stringify, large object | 161672.63 | 0.0061853388 | 0.00004 | 80837 | | DeepRedact, remove item, single object | 25085.95 | 0.039862959 | 0.00033 | 12543 | | DeepRedact, default config, large object | 23164.57 | 0.0431693713 | 0.00023 | 11583 | | Regex replace, large object | 22828.32 | 0.043805244 | 0.00031 | 11415 | | DeepRedact, custom replacer function, single object | 22520.52 | 0.0444039553 | 0.00039 | 11261 | | DeepRedact, replace string by length, single object | 22470.94 | 0.0445019191 | 0.00025 | 11236 | | DeepRedact, retain structure, single object | 18315.67 | 0.0545980591 | 0.00026 | 9158 | | DeepRedact, fuzzy matching, single object | 18077.45 | 0.0553175285 | 0.00035 | 9039 | | DeepRedact, config per key, single object | 16055.96 | 0.0622821745 | 0.00031 | 8028 | | DeepRedact, default config, 1000 large objects | 8077.4 | 0.1238022 | 0.00187 | 4039 | | fast redact, large object | 5918.61 | 0.1689584628 | 0.00151 | 2960 | | ObGlob, large object | 5193.29 | 0.1925563273 | 0.00972 | 2597 | | DeepRedact, case insensitive matching, single object | 3477.6 | 0.2875549482 | 0.00324 | 1739 | | DeepRedact, fuzzy and case insensitive matching, single object | 3437.73 | 0.2908896131 | 0.00239 | 1719 | | ObGlob, 1000 large objects | 237.69 | 4.2072005126 | 0.05005 | 119 | | JSON.stringify, 1000 large objects | 230.33 | 4.3416907672 | 0.04373 | 116 | | DeepRedact, partial redaction large string | 127.18 | 7.8628400156 | 0.4176 | 64 | | fast redact, 1000 large objects | 119.33 | 8.3803393 | 0.31943 | 60 | | Regex replace, 1000 large objects | 97.12 | 10.2963537755 | 0.29341 | 49 |