
Research
/Security News
Mini Shai-Hulud Campaign Hits Red Hat Cloud Services npm Packages
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.
slow-redact
Advanced tools
Smart object redaction for JavaScript applications - safe AND fast!
Redact JS objects with the same API as fast-redact, but uses innovative selective cloning instead of mutating the original. This provides immutability guarantees with performance competitive to fast-redact for real-world usage patterns.
npm install slow-redact
const slowRedact = require('slow-redact')
const redact = slowRedact({
paths: ['headers.cookie', 'headers.authorization', 'user.password']
})
const obj = {
headers: {
cookie: 'secret-session-token',
authorization: 'Bearer abc123',
'x-forwarded-for': '192.168.1.1'
},
user: {
name: 'john',
password: 'secret123'
}
}
console.log(redact(obj))
// Output: {"headers":{"cookie":"[REDACTED]","authorization":"[REDACTED]","x-forwarded-for":"192.168.1.1"},"user":{"name":"john","password":"[REDACTED]"}}
// Original object is completely unchanged:
console.log(obj.headers.cookie) // 'secret-session-token'
Creates a redaction function with the specified options.
string[] (required): An array of strings describing the nested location of a key in an objectany (optional, default: '[REDACTED]'): The value to replace sensitive data with. Can be a static value or function.Function|boolean (optional, default: JSON.stringify): Serialization function. Set to false to return the redacted object.boolean (optional, default: false): Remove redacted keys from serialized outputboolean (optional, default: true): Throw on non-object values or pass through primitivesSupports the same path syntax as fast-redact:
'user.name', 'headers.cookie''user["password"]', 'headers["X-Forwarded-For"]''users[0].password', 'items[1].secret''users.*.password' (redacts password for all users)'*.password' (redacts password at any level)'items.*' (redacts all array elements)Custom censor value:
const redact = slowRedact({
paths: ['password'],
censor: '***HIDDEN***'
})
Dynamic censor function:
const redact = slowRedact({
paths: ['password'],
censor: (value, path) => `REDACTED:${path}`
})
Return object instead of JSON string:
const redact = slowRedact({
paths: ['secret'],
serialize: false
})
const result = redact({ secret: 'hidden', public: 'data' })
console.log(result.secret) // '[REDACTED]'
console.log(result.public) // 'data'
// Restore original values
const restored = result.restore()
console.log(restored.secret) // 'hidden'
Custom serialization:
const redact = slowRedact({
paths: ['password'],
serialize: obj => JSON.stringify(obj, null, 2)
})
Remove keys instead of redacting:
const redact = slowRedact({
paths: ['password', 'user.secret'],
remove: true
})
const obj = { username: 'john', password: 'secret123', user: { name: 'Jane', secret: 'hidden' } }
console.log(redact(obj))
// Output: {"username":"john","user":{"name":"Jane"}}
// Note: 'password' and 'user.secret' are completely absent, not redacted
Wildcard patterns:
// Redact all properties in secrets object
const redact1 = slowRedact({ paths: ['secrets.*'] })
// Redact password for any user
const redact2 = slowRedact({ paths: ['users.*.password'] })
// Redact all items in an array
const redact3 = slowRedact({ paths: ['items.*'] })
// Remove all secrets instead of redacting them
const redact4 = slowRedact({ paths: ['secrets.*'], remove: true })
serialize: falseremove: true option to completely omit keys from outputserialize: false modeslow-redact uses selective cloning that provides good performance while maintaining immutability guarantees:
| Operation Type | slow-redact | fast-redact | Performance Ratio |
|---|---|---|---|
| Small objects | ~690ns | ~200ns | ~3.5x slower |
| Large objects (minimal redaction) | ~18μs | ~17μs | ~same performance |
| Large objects (wildcards) | ~48μs | ~37μs | ~1.3x slower |
| No redaction (large objects) | ~18μs | ~17μs | ~same performance |
slow-redact is performance-competitive with fast-redact for large objects.
Small Objects (~180 bytes):
Large Objects (~18KB, minimal redaction):
Large Objects (~18KB, wildcard patterns):
Memory Considerations:
Choose fast-redact when:
Choose slow-redact when:
Run benchmarks yourself:
npm run bench
slow-redact uses an innovative selective cloning approach that provides immutability guarantees while dramatically improving performance:
// Old approach: Deep clone entire object, then redact
const fullClone = deepClone(originalObject) // Clone everything
redact(fullClone, paths) // Then redact specific paths
// New approach: Analyze paths, clone only what's needed
const pathStructure = buildPathStructure(paths) // One-time setup
const selectiveClone = cloneOnlyNeededPaths(obj, pathStructure) // Smart cloning
redact(selectiveClone, paths) // Redact pre-identified paths
const largeConfig = {
database: { /* large config object */ },
api: { /* another large config */ },
secrets: { password: 'hidden', apiKey: 'secret' }
}
const redact = slowRedact({ paths: ['secrets.password'] })
const result = redact(largeConfig)
// Only secrets object is cloned, database and api share original references
console.log(result.database === largeConfig.database) // true - shared reference!
console.log(result.api === largeConfig.api) // true - shared reference!
console.log(result.secrets === largeConfig.secrets) // false - cloned for redaction
This approach provides immutability where it matters while sharing references where it's safe.
The remove: true option provides full compatibility with fast-redact's key removal functionality:
const redact = slowRedact({
paths: ['password', 'secrets.*', 'users.*.credentials'],
remove: true
})
const data = {
username: 'john',
password: 'secret123',
secrets: { apiKey: 'abc', token: 'xyz' },
users: [
{ name: 'Alice', credentials: { password: 'pass1' } },
{ name: 'Bob', credentials: { password: 'pass2' } }
]
}
console.log(redact(data))
// Output: {"username":"john","secrets":{},"users":[{"name":"Alice"},{"name":"Bob"}]}
| Option | Behavior | Output Example |
|---|---|---|
| Default (redact) | Replaces values with censor | {"password":"[REDACTED]"} |
remove: true | Completely omits keys | {} |
remove: true*, users.*, items.*.secret)undefined (omitted in JSON output)users.*.credentials.password)JSON.stringify serializer (like fast-redact)# Run unit tests
npm test
# Run integration tests comparing with fast-redact
npm run test:integration
# Run all tests (unit + integration)
npm run test:all
# Run benchmarks
npm run bench
MIT
Pull requests welcome! Please ensure all tests pass and add tests for new features.
FAQs
Redact JS objects
The npm package slow-redact receives a total of 957,272 weekly downloads. As such, slow-redact popularity was classified as popular.
We found that slow-redact demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.

Security News
The Rust project is moving toward formal rules on LLM use in contributions after months of internal debate over maintainer burden, code quality, and contributor experience.