| name | logfrisk |
| description | Frisk your logging statements for leaked secrets and PII before you ship. Triggers automatically when you are about to report a coding task done and your diff added or changed any log/print line (or on /logfrisk). Audits only the changed logging for tokens, keys, passwords, emails, national IDs, phone/card numbers, and whole-object dumps of requests, users, or config — redacts what's safe to redact, escalates the rest, and refuses to say "done" while a secret or PII leak is still being logged. |
logfrisk — frisk your logs before they leak
You just added or changed code that logs something. Before you tell the user it's
done, frisk the log lines. Logs feel harmless while you write them, then get
shipped to stdout, files, and aggregators (Datadog, CloudWatch, Sentry) that are
broadly readable, long-retained, and outside the app's auth. A token or a user's
email in a log line is a leak that no amount of database encryption catches. A
linter sees logger.info(user); only you, with the diff in hand, know user
holds an email and a hashed password. So you frisk your own log lines.
When to run
- Automatically, right before you would say a coding task is done, merged, or
ready — any "done / finished / this should work / ✅" moment whose diff added or
changed a logging or print statement.
- On demand when the user types
/logfrisk (frisk the current diff or a named
file/range).
What it looks at
Only the logging statements in your diff — the console.*, print,
println, fmt.Print*, logger.* / log.* (debug/info/warn/error),
puts, echo, NSLog, System.out.print* lines you added or changed, plus
the structured-log fields and error reports (Sentry.captureException,
span.set_attribute) on those lines. Not the whole repo, not non-logging code —
stay scoped and fast. (Secrets sitting in non-log code are patdown's job.)
The process (run against each changed log statement)
- Secrets & credentials — is a token, API key, password, private key,
bearer/
Authorization header, session id, OTP, or DB connection string in the
logged string or fields? Includes logging the variable that holds one
(logger.info(\token=${token}`)`) and logging an error object whose message
embeds it.
- Direct PII — email, phone, full name, national ID (NIK/SSN), passport,
credit-card/PAN, CVV, full address, IP tied to a user, date of birth, precise
geolocation, health/financial detail. Logging any of these in clear is the leak.
- Whole-object dumps — the silent killer:
console.log(req.body),
logger.info(user), print(request.headers), log.debug("%+v", config),
JSON.stringify(payload). The object today may be clean; it carries
passwords, tokens, and PII the moment the schema grows. Flag logging an entire
request / response / user / account / config / headers / body / event object.
- Caught-error leakage —
logger.error(err) / captureException(e) where the
error or its stack can carry the failed query (with values), the request body,
or the credential that caused the failure. Log a stable message + error type,
not the raw error with its payload.
- Level & exposure — a real secret/PII finding is critical/high regardless of
level, but note when it sits at
debug/trace (ships the moment someone flips
log level in prod) versus a one-off console.log left over from debugging that
should just be deleted.
Severity: critical (secret/credential/full PAN logged in clear),
high (direct PII logged, whole request/user/body object dumped, raw caught
error with payload), medium (partial PII, IP/user-agent without need, internal
ids that aid correlation), low (leftover debug log, noisy dump to delete).
What to do with findings
- Do the safe, mechanical fix yourself — drop the offending field, log a
non-identifying handle instead (
userId not the user object, last4 not the
card, the email's hash or domain not the address), redact the secret
(token=***), replace a whole-object dump with the 2–3 fields actually needed
for debugging, and swap logger.error(err) for logger.error("create failed", { type: err.name }). State each fix in the report.
- Escalate anything that needs a human call — a log line that's load-bearing
for an audit/compliance trail, a field you can't tell is PII without domain
knowledge, or a redaction that would gut the log's usefulness. Describe it, give
1–2 options, ask to approve / fix / skip.
- Never invent a leak. Logging
userId, a request id, a status code, a
duration, or a non-secret enum is fine — don't flag it. False alarms train
people to mute you.
The hard rule
Do not report the task as done while a critical or high finding in your
diff — a logged secret, logged direct PII, or a whole request/user/body dump — is
unaddressed (neither redacted nor explicitly accepted by the user). If the log
lines are clean, say so in one line and finish.
Output format
logfrisk — N changed file(s), M log line(s)
✗ critical src/auth.ts:31 logs `Authorization` header (bearer token) → redacted to `***` [fixed]
✗ high src/users.ts:88 console.log(user) dumps email + passwordHash → logs { userId } only [fixed]
⚠ high src/orders.ts:54 logger.error(err) on a failed INSERT may carry card PAN — needs your call [escalated]
✓ rest clean (no secrets, no PII, no object dumps)
1 leak needs your decision before this is done.
Be terse. Real leaks only. Redact what's safe, flag what isn't, and don't sign off
while a secret or someone's PII is still going to the logs.