@lidofinance/satanizer
v0.64.0
Published
Tool, which mask secrets
Readme
@lidofinance/satanizer
Zero dependencies tool, which masks secrets 🕵️
Installation
yarn add @lidofinance/satanizer
Usage
There are two types of usage, you can provide secrets first and then appy mask function.
import { satanizer } from '@lidofinance/satanizer'
const mask = satanizer([/0x[a-zA-Z0-9]+/])
const target = 'qwe 0xABC1 asd'
const result = 'qwe ****** asd'
expect(mask(target)).toBe(result)Alternatively you can execute satanizer right away.
import { satanizer } from '@lidofinance/satanizer'
const target = 'qwe secret asd'
const result = 'qwe ****** asd'
expect(satanizer(['secret'], target)).toBe(result)Pattern can be string or regular expression.
import { satanizer } from '@lidofinance/satanizer'
assert(satanizer(['secret', /0x[s]ecret/], 'qwe secret 0xsecret asd') === 'qwe ****** ******** asd')Target can be a anything - string, object, array or Error.
import { satanizer } from '@lidofinance/satanizer'
const mask = satanizer(['secret'])
const target = { message: `there are secret` }
const result = { message: `there are ******` }
expect(mask(target)).toMatchObject(result)
const target = ['some secret item', 'some item']
const result = ['some ****** item', 'some item']
expect(mask(target)).toMatchObject(result)
const target = new Error(`there are secret`)
const result = { message: `there are ******` }
expect(mask(target)).toMatchObject(result)Configuration
You can specify as well as your own secrets, as well as use some pre-build secrets patterns:
blockchainAddress(ETH and others).ensAddress.ipAddress.macAddress.
You can use them one by one or all together.
import { commonPatterns } from '@lidofinance/satanizer'
const secrets = [
/* your secrets */
]
const mask = satanizer([...commonPatterns, ...secrets])Limits
Masking untrusted input has to stay cheap, so the traversal is bounded. Anything cut off is marked in the output, nothing is dropped silently.
MAX_STRING_LENGTH(10 000) — longer strings are truncated before scanning, the result ends with[Truncated].MAX_KEYS(1 000) — only the first keys of an object or items of an array are masked. Objects get a[Truncated]key holding the number of skipped keys, arrays get a trailing[Truncated]item.MAX_DEPTH(10) — deeper values are replaced with[MaxDepth].MAX_VALUES(10 000) — the total number of masked values per call, everything past it becomes[Truncated]. The limits above bound a single object, this one bounds the whole traversal.
Every limit applies to a single call. A satanizer is meant to be built once and reused, so nothing carries over — the next call starts from the full budget.
The constants are exported, so you can assert against them.
Only a value that references itself, directly or through its own children, is replaced with [Cycle]. The
same value referenced twice side by side is not a cycle and is masked twice — which is why MAX_VALUES
exists, as a shared value is walked once per path that reaches it.
Your own patterns are not used as is — every pattern is recompiled with the g flag (a string pattern is
escaped first), so any other flag on the original regular expression, such as i, is dropped. Put what you
need into the pattern itself.
A pattern that backtracks catastrophically will still be slow, even though the input length is capped. The
bundled commonPatterns are safe on any input.
