diff --git a/.env.example b/.env.example index 5b46707..c96d7f7 100644 --- a/.env.example +++ b/.env.example @@ -67,6 +67,15 @@ DB_PASSWORD=changeme # production so log aggregators get the structured JSON they expect. # LOG_PRETTY= +# Set to '1' to route Sequelize query logs through pino at debug +# level (visible when LOG_LEVEL=debug, silent otherwise). Default +# unset: Sequelize query logging is OFF entirely, because the +# default `console.log` Sequelize uses would otherwise dump SQL + +# bound parameters (including secrets like authKey values) to +# stdout, bypassing pino's redact paths. Turn this on for targeted +# query-shape debugging only; turn it off again when done. +# DB_LOG_QUERIES= + # ---- Rate limiting ---- # Per-key request budget for /v1/* in the window below. Defaults to 100. diff --git a/app/config/db.config.js b/app/config/db.config.js index d55d9f0..21aa585 100644 --- a/app/config/db.config.js +++ b/app/config/db.config.js @@ -3,11 +3,30 @@ const env = require('./env.js'); const Sequelize = require('sequelize'); +const log = require('./logger.js'); + +// Sequelize's default `logging` is `console.log`, which dumps every +// executed SQL statement — INCLUDING bound parameter values — to +// stdout. In production that means a query like +// `SELECT * FROM "dbo"."ApiKey" WHERE "akKey" = $1` followed by the +// bound array containing the raw authKey lands in the operator's +// log stream alongside our structured JSON output, mixing log +// formats and surfacing secrets that pino's redact paths never see +// (those only know about HTTP header structures, not Sequelize SQL +// strings). Disable by default; let operators opt back in for +// targeted debugging by setting DB_LOG_QUERIES=1, in which case +// queries are routed through pino at debug level (silent at the +// default LOG_LEVEL=info, visible when LOG_LEVEL=debug, and never +// emitted as bare console.log). +const dbQueryLog = process.env.DB_LOG_QUERIES === '1' + ? (sql, timing) => log.debug({ sql, timing }, 'sequelize query') + : false; const sequelize = new Sequelize(env.database, env.username, env.password, { host: env.host, port: env.port, dialect: 'postgres', + logging: dbQueryLog, define: { schema: 'dbo', timestamps: false,