agentsclimarketplace

Security logging alerting failures

Skill scholarly360/owasp-top10-web-skills/skills/security-logging-alerting-failures

Agent Skills for OWASP Top 10 Application Security Risks (https://owasp.org/Top10/2025/)

Install
npx -y skills add scholarly360/owasp-top10-web-skills --skill security-logging-alerting-failures

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 9 stars9 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use this skill whenever auditing, reviewing, or testing Python web applications (FastAPI or Flask) for OWASP A09:2025 — Security Logging & Alerting Failures. Trigger this skill when the user mentions: logging security, audit trails, log injection, sensitive data in logs, alerting gaps, insufficient logging, SIEM integration, log monitoring, incident detection readiness, or any request to audit or fix logging/alerting in a Python backend. Also trigger when a user asks "are we logging the right things?", "how do I detect attacks?", or "what should we be alerting on?". Do NOT skip this skill just because the request sounds simple — log-related security issues are consistently underestimated and require systematic coverage across all five CWEs.

SKILL.md

9.5 KB, as published. Nobody here has run it

A09:2025 — Security Logging & Alerting Failures

OWASP rank: #9 (community-voted for third consecutive cycle)
Renamed in 2025: Added "Alerting" — logging without alerting provides minimal security value.
Stats: 5 CWEs, 723 CVEs, 3.91% average incidence rate
Coverage CWEs: CWE-778, CWE-117, CWE-532, CWE-223, CWE-390


What This Category Covers

Failure TypeDescription
Insufficient LoggingAuditable events (logins, access control failures, validation errors) not logged
Log InjectionUser input flows unescaped into log messages — enables log forgery
Sensitive Data in LogsPasswords, tokens, PII, card numbers written to log output
Omission of Security-Relevant InfoErrors/warnings logged without context (IP, user, timestamp, action)
No AlertingLogs exist but no thresholds, rules, or platform routes them to incident response

Audit Checklist — FastAPI & Flask

Work through each section systematically. For each item, note: PASS, FAIL, or NOT APPLICABLE.

1. Log Injection (CWE-117)

User-controlled input must never flow raw into log statements.

What to look for:

# VULNERABLE — newline injection, ANSI escape injection
logger.info(f"User logged in: {request.form['username']}")
logger.warning("Failed login for: " + username)

# SAFE — sanitize before logging
import re
safe_username = re.sub(r'[\r\n\x1b]', '_', username)
logger.info("Failed login for: %s", safe_username)

Checklist:

  • No f-strings or + concatenation with raw request data in log calls
  • Newlines (\r, \n) stripped from all user-supplied log values
  • ANSI escape codes (\x1b[) stripped (prevent terminal injection)
  • Structured logging used (JSON format) — field separation prevents injection by design

2. Sensitive Data in Logs (CWE-532)

Secrets must never appear in log output — even at DEBUG level.

Patterns to flag:

# VULNERABLE
logger.debug(f"Auth token: {token}")
logger.info(f"Processing payment for card: {card_number}")
app.logger.debug(request.json)         # May contain password field
print(f"Password reset for {email}, token={reset_token}")

# SAFE
logger.info("Auth token validated for user_id=%s", user_id)
logger.info("Payment processed for user_id=%s, last4=%s", user_id, card_number[-4:])

What to scan for:

  • No logging of: password, passwd, secret, token, api_key, authorization header values
  • No logging of: credit card numbers, SSNs, full email+password combos
  • request.json / request.form not logged wholesale without field filtering
  • No print() statements containing sensitive variables in production code
  • Bandit rule B506 (and similar) passes in CI/CD

3. Insufficient Logging (CWE-778)

The following events must produce log entries with full context.

Required log events:

EventMinimum Fields
Failed authenticationtimestamp, IP, username attempted, user-agent
Successful authenticationtimestamp, IP, user_id, method (password/OAuth/MFA)
Authorization failure (403)timestamp, IP, user_id, resource attempted, HTTP method
Input validation failuretimestamp, IP, user_id, field name (not value if sensitive), error
High-value transactiontimestamp, user_id, action, resource ID, before/after state
Account changes (password reset, role change)timestamp, actor_user_id, target_user_id, change type
Admin actionstimestamp, admin_user_id, action, affected resource

FastAPI implementation pattern:

import logging
import structlog  # recommended for structured logs

log = structlog.get_logger()

# In auth endpoint
@router.post("/login")
async def login(credentials: LoginSchema, request: Request):
    user = await authenticate(credentials)
    if not user:
        log.warning(
            "auth.failed",
            ip=request.client.host,
            username=credentials.username,    # OK — username is not a secret
            user_agent=request.headers.get("user-agent"),
        )
        raise HTTPException(status_code=401, detail="Invalid credentials")
    log.info("auth.success", user_id=user.id, ip=request.client.host)

Flask implementation pattern:

from flask import request
import logging

@app.route("/login", methods=["POST"])
def login():
    user = authenticate(request.form["username"], request.form["password"])
    if not user:
        app.logger.warning(
            "auth.failed ip=%s username=%s ua=%s",
            request.remote_addr,
            request.form.get("username"),
            request.user_agent.string,
        )
        return {"error": "Invalid credentials"}, 401

Checklist:

  • All 401/403 responses have a corresponding logger.warning() or logger.error() call
  • Log entries include: timestamp (automatic with logging), source IP, user identifier
  • Password reset and account modification flows are logged
  • Admin panel actions are logged with actor identity
  • High-value business transactions produce audit log entries

4. Structured Logging & SIEM Compatibility

Log format must be parseable by observability platforms (ELK, Splunk, Datadog, Sentry).

FastAPI — structlog + JSON:

# main.py
import structlog
import logging

structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.stdlib.add_log_level,
        structlog.processors.JSONRenderer(),  # machine-parseable
    ],
    wrapper_class=structlog.BoundLogger,
    logger_factory=structlog.PrintLoggerFactory(),
)

Flask — python-json-logger:

from pythonjsonlogger import jsonlogger

handler = logging.StreamHandler()
handler.setFormatter(jsonlogger.JsonFormatter(
    fmt="%(asctime)s %(levelname)s %(name)s %(message)s"
))
app.logger.addHandler(handler)

Checklist:

  • Log output is JSON-formatted (not plain text) in production
  • Log level is not DEBUG in production (leaks verbose info)
  • Logs ship to a centralized platform: Sentry, ELK, Splunk, Datadog, CloudWatch
  • Log retention policy exists and meets compliance requirements (e.g., 90 days minimum)

5. Alerting Integration

Logging without alerting = silent failures. Verify active monitoring exists.

Sentry (exception alerting):

# FastAPI
import sentry_sdk
from sentry_sdk.integrations.fastapi import FastApiIntegration
sentry_sdk.init(dsn=settings.SENTRY_DSN, integrations=[FastApiIntegration()])

# Flask
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(dsn=settings.SENTRY_DSN, integrations=[FlaskIntegration()])

Recommended alerting thresholds:

SignalAlert Trigger
Failed logins>10 failures for same username in 5 min
Failed logins>100 failures from same IP in 5 min
403 responses>50 from same user_id in 1 min
500 errors>5% of requests in any 1-min window
New admin accountImmediate alert, every occurrence
Privilege escalationImmediate alert, every occurrence

Checklist:

  • Sentry or equivalent is initialized and receiving events in production
  • Rate-limit violations produce alert events (not just HTTP 429 responses)
  • Repeated auth failures trigger alerts (brute force detection)
  • Alerting runbooks/playbooks exist for each alert type
  • Honeytokens deployed in high-value areas (near-zero false-positive intrusion detection)

Automated Scanning

Run these tools as part of CI/CD:

# Static analysis — catches log injection patterns, sensitive data in logs
bandit -r . -t B106,B107,B110 --severity-level medium

# Search for raw request data in log calls
grep -rn "logger\.\(info\|warning\|error\|debug\)" . \
  | grep -E "request\.(form|json|args|data|headers)\[" \
  | grep -v "\.get(" 

# Search for potential sensitive field logging
grep -rn "logger\|logging\|print" . \
  | grep -iE "password|passwd|secret|token|api_key|card|ssn|cvv"

Key CWEs Reference

CWENamePython Risk
CWE-778Insufficient LoggingNo logging on auth/authz failures
CWE-117Log Injectionf-string user input in logger calls
CWE-532Sensitive Info in LogsPasswords/tokens in debug output
CWE-223Omission of Security-Relevant InfoLogs lack IP/user context
CWE-390Detection of Error Condition Without ActionException caught, swallowed, not logged

Reference Files

  • references/remediation-patterns.md — Full before/after code fixes for each CWE
  • references/alerting-platforms.md — Integration guides for Sentry, ELK, Splunk, Datadog

Read these when the user needs detailed implementation help beyond the checklist.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.