Логирование — ключевой инструмент наблюдаемости: позволяет отслеживать поведение системы, выявлять ошибки, анализировать производительность. Однако вместе с полезной информацией в логи нередко попадают чувствительные данные: токены доступа, пароли, cookie, персональные данные пользователей. Это создает прямую угрозу безопасности, поскольку журналы часто доступны широкой группе разработчиков, систем мониторинга или внешним сервисам.
Основная задача — обеспечить максимальную информативность логов при полном исключении утечек секретов.
К категории данных, которые не должны попадать в логи:
Даже частичное логирование таких данных может привести к компрометации системы.
Замена чувствительных данных на безопасные значения:
const mask = (value) => '***';
Пример:
{
email: "user@example.com",
password: "***"
}
Используется для сохранения возможности идентификации без раскрытия данных:
const crypto = require('crypto');
const hash = (value) =>
crypto.createHash('sha256').update(value).digest('hex');
Применяется, например, для email или user ID.
Самый безопасный вариант — не логировать данные вовсе:
delete payload.password;
Библиотека Iron предоставляет гибкую систему логирования с возможностью внедрения middleware и трансформации данных перед записью.
Ключевая идея: централизованная обработка логируемых данных перед их выводом.
import { createLogger } from 'iron';
const logger = createLogger({
level: 'info'
});
logger.info('User login', {
email: 'user@example.com',
password: 'secret123'
});
Без дополнительной обработки пароль попадет в лог.
Iron поддерживает цепочку middleware, через которую проходят все лог-сообщения.
const redactMiddleware = (log) => {
if (log.meta?.password) {
log.meta.password = '***';
}
return log;
};
const logger = createLogger({
middleware: [redactMiddleware]
});
Теперь любые поля password автоматически
маскируются.
Реальные структуры данных сложны, поэтому требуется рекурсивная обработка.
const SENSITIVE_KEYS = ['password', 'token', 'authorization', 'apiKey'];
const redact = (obj) => {
if (Array.isArray(obj)) {
return obj.map(redact);
}
if (obj && typeof obj === 'object') {
return Object.keys(obj).reduce((acc, key) => {
if (SENSITIVE_KEYS.includes(key.toLowerCase())) {
acc[key] = '***';
} else {
acc[key] = redact(obj[key]);
}
return acc;
}, {});
}
return obj;
};
Интеграция:
const logger = createLogger({
middleware: [
(log) => {
log.meta = redact(log.meta);
return log;
}
]
});
Наиболее частый источник утечек — логирование HTTP-запросов.
logger.info('Request', {
headers: req.headers,
body: req.body
});
const safeHeaders = { ...req.headers };
delete safeHeaders.authorization;
const safeBody = redact(req.body);
logger.info('Request', {
headers: safeHeaders,
body: safeBody
});
Вместо удаления опасных полей можно явно разрешать только безопасные:
const pickSafeFields = (obj, allowed) =>
Object.fromEntries(
Object.entries(obj).filter(([key]) => allowed.includes(key))
);
Пример:
const safeUser = pickSafeFields(user, ['id', 'email']);
Этот подход снижает риск пропустить новое чувствительное поле.
Ошибки часто содержат стек вызовов и контекст, включающий секреты.
try {
// ...
} catch (err) {
logger.error('Error occurred', {
message: err.message,
stack: err.stack
});
}
Рекомендуется:
Iron поддерживает структурированные логи:
logger.info({
event: 'user_login',
userId: 123
});
Преимущества:
Чувствительность данных может зависеть от уровня:
debug — максимум информации (в dev-среде)info — безопасные событияerror — минимально необходимый контекстif (process.env.NODE_ENV === 'production') {
logger.setLevel('info');
}
Даже при очистке данных важно:
При отправке логов в сторонние сервисы (например, ELK, Datadog):
Регулярная проверка:
test('password is not logged', () => {
const log = captureLog(() =>
logger.info('test', { password: '123456' })
);
expect(log).not.toContain('123456');
});
Автоматизация предотвращает регрессии.
const createSafeLogger = () => {
return createLogger({
middleware: [
(log) => {
log.meta = redact(log.meta);
return log;
}
]
});
};
export const logger = createSafeLogger();
Единая точка входа гарантирует соблюдение правил по всей системе.
Во многих стандартах (GDPR, ISO 27001) логирование регулируется:
Полное удаление данных снижает полезность логов. Компромисс достигается через:
user@example.com →
u***@example.com)Грамотно настроенная система логирования позволяет эффективно диагностировать проблемы без риска утечки конфиденциальной информации.