Closed sramam closed 6 years ago
An alternative to this is using a rewriter.
// Redact all sensitive information contained in the meta
logger.rewriters.push((level, msg, meta) => redact.map(meta));
In winston@3.0.0
you can implement this using a custom format. Please consider upgrading.
const redact = require('redact-secrets')('[REDACTED]');
const { createLogger, format, transports } = require('winston');
const logger = createLogger({
format: format.combine(
// Redact any properties
format(info => redact.map(info))(),
// Then make it JSON
format.json()
)
transports: [new transports.Console()]
});
This doesn't work for me for some reason, there is no output when adding the redact formatter
This doesn't work for me for some reason, there is no output when adding the redact formatter
It seems the traverse(info).map
result is missing the Symbol(level)
and Symbol(splat)
keys from the info
object.
re-adding them to the traverse result seems to make it work. I'm not sure on how to clean up the typing yet, but the following works
const sensitiveKeys = ['client_secret'];
const redact = format(info => {
const result = traverse(info).map(function redactor() {
if (this.key && sensitiveKeys.includes(this.key)) {
this.update('[REDACTED]');
}
});
const levelSym = Symbol.for('level');
const splatSym = Symbol.for('splat');
result[levelSym] = info[(levelSym as unknown) as string];
result[splatSym] = info[(splatSym as unknown) as string];
return result;
});
UPDATE: Found this issue in the traverse package https://github.com/substack/js-traverse/issues/65
I ended up doing this, for those of you interested (winston: v3.3.3
):
import traverse from "traverse";
import { klona } from "klona/full";
const sensitiveKeys = [
/cookie/i,
/passw(or)?d/i,
/^pw$/,
/^pass$/i,
/secret/i,
/token/i,
/api[-._]?key/i,
];
function isSensitiveKey(keyStr) {
if (keyStr) {
return sensitiveKeys.some(regex => regex.test(keyStr));
}
}
function redactObject(obj) {
traverse(obj).forEach(function redactor() {
if (isSensitiveKey(this.key)) {
this.update("[REDACTED]");
}
});
}
function redact(obj) {
const copy = klona(obj); // Making a deep copy to prevent side effects
redactObject(copy);
const splat = copy[Symbol.for("splat")];
redactObject(splat); // Specifically redact splat Symbol
return copy;
}
const logger = winston.createLogger({
format: winston.format.combine(
format(info => redact(info))(), // Prevent logging sensitive data
...
@romain-ortega traverse replace de original obj
I am interested in integrating a library that optionally redacts-secrets from log messages. Perhaps something like - https://www.npmjs.com/package/redact-secrets.
Wondering if there is an appetite for a PR of this nature?
One way to accomplish this today is to do something like this. However, this is harder to do when the output format is not an object.
This proposal would apply this internally before the log message is serialized, make it's application more reliable. Thoughts?