"We have logs" is one of the most reassuring sentences in security operations and one of the most misleading. Logs nobody parses, alerts nobody routes, and event streams that omit application-meaningful fields produce the false confidence that has extended breach dwell times into the hundreds of days. Security logging and monitoring failures sit at A09 on the OWASP Top 10 for a simple reason: most teams have logging and monitoring, and most still cannot detect a credential-stuffing run or an exfiltration in progress until something downstream forces the question. This guide walks the gaps that produce that outcome and the engineering discipline that closes them.
What A09 Actually Means in 2026
The category formerly known as A10 "Insufficient Logging & Monitoring" was renamed in the 2021 revision to "Security Logging and Monitoring Failures" and promoted to A09. The rename was not cosmetic. The old framing implied a quantity problem — log more, monitor more. The current framing reframes it as a failure mode: the question is not whether logs exist but whether the right events are captured, in a form that supports detection, and whether detection actually happens. A team can ship a hundred gigabytes of logs per day and still meet the A09 pattern because none of those bytes contain the authentication-failure event that would have surfaced the credential-stuffing run.
The 2025 OWASP refresh keeps A09 in roughly the same position. Owasp a09 is about the application's role in the detection pipeline — what events it emits, with what fields, into what sink. It is explicitly not about platform monitoring or alert tuning. It is the upstream slice that, when missing, makes every downstream investment in SIEMs ineffective. "We log to stdout, the platform aggregates it, the SOC queries it" only works if the events are application-meaningful — authentication outcomes, authorization decisions, sensitive data access, administrative actions, anomalous input rejections. Stdout logs of "request handled in 47ms" are operationally useful and security-irrelevant.
Why Logging Failures Are an Application-Layer Problem
A common misallocation is treating logging as an infrastructure concern owned by the platform team. The platform genuinely owns part of the pipeline — shipping, retention, indexing, query performance. But events reaching the platform are produced by the application code, and the platform has no visibility into events the application never emits. A SIEM cannot alert on a privilege-escalation event the application did not log. The semantic content of the event stream is set in the application, which is why logging security is an application-engineering responsibility before it is an SOC one.
Platform telemetry — request counts, latency distributions, error rates — is observable without application code changes and is what gets emitted by default. Application-meaningful events — "user X authenticated from IP Y", "user X was denied access to resource Z", "admin X impersonated user Y" — require deliberate emission with the right fields. Teams without deliberate event emission have telemetry that tells them how the application is performing and almost nothing about whether it is being attacked.
The canonical references are well known. Equifax's 2017 intrusion ran for roughly 76 days before detection, with post-incident analyses converging on expired TLS certificates on inspection devices and gaps in log review. Target's 2013 breach featured FireEye telemetry that generated alerts on the malware activity which were either deprioritized or not routed to a team that could act. Capital One's 2019 breach ran for roughly three months between exfiltration and awareness. In each case, the events that would have made the intrusion visible were either not captured at the application boundary, not surfaced to detection, or not actionable when they did surface.
The Three Detection Gaps Every Team Has
When we audit application logging programs, the failures cluster into three distinct gaps that compound rather than overlap. Each requires a different kind of engineering investment, and closing one without the others produces partial coverage with the same end-state outcome.
Gap 1: Events not logged. The application code does not emit the security-relevant event at all. The login flow records the success-path metric for the SRE dashboard but does not record an auth.login.failure event when authentication fails. The authorization check returns a 403 but does not record an authz.denied event with the actor, resource, and action. The administrative action is logged for the admin's audit trail but not in a form the SOC can correlate. The events an attacker generates are simply absent from the event stream because no code path emits them. This is the most common failure pattern and the hardest to close because it requires touching every security-relevant code path.
Gap 2: Events logged but not actionable. The application emits the event, but it is missing fields that would let a detection rule act on it, or is emitted in a format that requires expensive parsing, or is mixed with operational logs in a way that makes high-fidelity filtering impossible. An auth.login.failure event without the source IP cannot detect credential stuffing across multiple accounts. A free-form log line that says "user logged in" cannot be aggregated, correlated, or alerted on at scale. The signal is present in the bytes but absent from the queryable surface.
Gap 3: Events actionable but no alerting path. The application emits well-structured events with all the fields a rule needs, and the rule does not exist or routes to a queue with no on-call. The credential-stuffing pattern is technically detectable, and nobody has written the correlation rule. The alert that would fire has been silenced for six months because of historical noise. The events make it through the pipeline; the human or automated process that turns them into action does not exist or has decayed.
Each gap requires a different fix. Gap 1 is closed by application code changes. Gap 2 is closed by schema and format discipline. Gap 3 is closed by detection-engineering investment. The three have to move together — closing any one without the others leaves the same end-state outcome.
What to Log (and What Not to Log)
The minimum security-event coverage for an application that handles authentication and sensitive data is well established. A team that emits all of the following consistently has closed Gap 1 for the most common attack patterns. Audit logging best practices in 2026 converge on roughly this surface.
Authentication events. Every successful and failed login, every MFA challenge, every password reset, every session created and terminated. Fields: actor (user ID or null), source IP, user agent, auth method, outcome, failure reason, timestamp in UTC ISO-8601. Authentication events are the single highest-value log source for breach detection — covered in depth in our A07 authentication failures guide.
Authorization decisions. Every access-control denial. Fields: actor, requested resource, requested action, deny reason, request context. Privilege-probing — a single actor attempting access to many resources they do not own — is invisible without authorization-denial logs.
Input validation rejections. A burst of rejections from a single source IP, or rejections that look like injection payloads, is detection material. Field set: source IP, endpoint, failed field, failure reason, hash or truncated version of the offending input (never the full payload). Injection attempts, covered in our A03 injection guide, almost always produce a validation-rejection signature before a successful exploit.
Administrative actions. Every privilege grant, role change, configuration change, data export, impersonation, or security toggle — logged with actor, action, target, and before/after state. Both the most damaging if abused and the rarest in normal operation.
Sensitive data access. Financial, health, identity, payment records — log actor, record identifier, access type, and business justification where the data model captures one. Feeds both detection (exfiltration patterns) and compliance (HIPAA, PCI).
System errors. Unhandled exceptions, downstream failures, deserialization errors. Operational by default, but errors that consistently appear from a single source IP can indicate active probing.
The do-not-log list is just as important, and it is where most logging security failures originate. Passwords must never appear in logs — not plaintext, hash, or truncated. Tokens, session IDs, API keys, and refresh tokens must never be logged in full; if a session identifier must appear for correlation, use a hash or first-six-characters with the rest redacted. Full PAN is forbidden under PCI; last-four with the rest masked is conventional. Full PII payloads should not flow into the log stream because the log store itself becomes a high-value exfiltration target. The principle: enough to correlate the event with its actor, not enough to be useful to an attacker who breaches the log store.
The bad-versus-good logging contrast in Python:
# BAD — secrets and PII flow into logs
logger.info(
f"User {email} logged in with password {password} "
f"from {request.remote_addr}, session={session_id}, "
f"card={user.card_number}"
)
# GOOD — structured event, no secrets
logger.info("auth.login.success", extra={
"event_type": "auth.login.success",
"actor_id": user.id,
"actor_email_hash": hash_email(email),
"source_ip": request.remote_addr,
"user_agent": request.headers.get("User-Agent"),
"session_id_prefix": session_id[:6],
"auth_method": "password",
"timestamp": datetime.utcnow().isoformat() + "Z",
"trace_id": request.headers.get("X-Trace-Id"),
})The good form is queryable, correlatable, and contains nothing valuable to an attacker who reads the logs. The bad form contains material that would, by itself, allow an attacker to take over the account.
Log Format Discipline
Once events are emitted, format discipline is what makes them actionable. Free-form log lines — the logger.info("user logged in") shape — are legible to humans tailing the log file and effectively unqueryable at scale. Every aggregation, correlation, and alerting rule in a SIEM is built against structured fields; a log entry without them is, for detection purposes, a comment.
The discipline has converged on roughly the same shape across the industry. Structured JSON as the format, one event per line. Consistent timestamps in UTC ISO-8601 with milliseconds — the 2026-04-25T14:32:11.847Z shape — eliminate timezone confusion across services. Correlation IDs (request, trace, session) present on every log entry an event chain produces, so a single user action can be reconstructed across service boundaries. Severity levels limited to a small agreed set (debug, info, warn, error, critical) and used consistently. Source attribution — service, version, host — for debugging across versions. Schema validation at write time so a typo in a field name is caught in the application, not in SIEM ingestion.
A canonical structured log entry for a failed authentication:
{
"timestamp": "2026-04-25T14:32:11.847Z",
"level": "warn",
"event_type": "auth.login.failure",
"service": "auth-api",
"service_version": "2.14.3",
"host": "auth-api-7d4f-x9k2",
"trace_id": "01HW8Q9F3MJ4Z2RVPK5T7XB6CN",
"session_id_prefix": "a3f291",
"actor_id": null,
"actor_email_hash": "sha256:b4f9...e2c1",
"source_ip": "203.0.113.47",
"source_country": "US",
"user_agent": "Mozilla/5.0 ...",
"auth_method": "password",
"failure_reason": "invalid_credentials",
"attempt_count_24h": 7,
"schema_version": "1.2"
}Every field above earns its place. The event_type is the single most important field — the join key a SIEM rule uses to find every authentication failure across the entire log stream regardless of which service emitted it. The trace ID lets investigators reconstruct the full request chain. The hashed email and prefixed session ID correlate events to a specific actor without exposing the underlying identifier. The attempt_count_24h is application-computed context that turns a single event into a signal — a single failure is noise, the seventh failure from the same hashed email in 24 hours is detection material the SIEM does not have to reconstruct.
The schema version is small but load-bearing. As the application evolves, fields are added, deprecated, or change meaning. A schema-version field lets detection rules adapt rather than silently drifting into matching against fields that no longer mean what they used to. Teams that ship without schema versioning find that rules tuned six months ago no longer fire correctly because the event shape changed and nobody noticed.
The Storage and Retention Problem
The events that close A09 are valuable specifically across time. A single authentication failure is noise; the same source IP failing across thirty days is a campaign. An exfiltration pattern invisible against one day of access logs is obvious against ninety days. Retention is therefore a detection-capability decision and, in regulated environments, a compliance obligation.
Compliance baselines. PCI-DSS requires twelve months of audit log retention with three months immediately accessible. HIPAA requires six years for covered entities. SOX requires seven years for financial-system access logs. Regulated applications have obligations that frequently exceed any reasonable hot-storage horizon.
Hot, warm, cold tiers. Hot storage (14-30 days) keeps logs in the SIEM index for sub-second query, suitable for live rules and active investigation. Warm (30 days to a year) sits in cheaper indexed storage, queryable in seconds-to-minutes. Cold (beyond a year) lives in object storage with rehydration measured in hours, suitable for compliance retention. The cost differential is often an order of magnitude per tier — a team that retains everything hot will run out of budget before compliance horizon.
Immutability and tamper-evidence. An attacker who has compromised the application has, by extension, the application's write access — including to the log store. The mitigation is write-once-read-many storage at the destination, signed log entries that detect tampering, and segregation of log-store credentials from the application's normal credential set. Compromising the application should not be sufficient to compromise the audit trail of that compromise.
End-of-life destruction. Retention has both a minimum (compliance) and a maximum (privacy). Logs that contain personal data are regulated by data-protection law, and retaining them past need creates legal exposure rather than security value. Automated destruction on schedule is the only sustainable pattern.
Detection Engineering — Turning Logs into Alerts
The transition from "we have logs" to "we detect breaches" is detection engineering, and it is the discipline most underinvested in across application security programs. Events flowing into the SIEM are raw material; the rules that turn them into alerts are the actual detection capability, and they require a lifecycle as deliberate as any other engineering artifact.
The rule lifecycle. A detection rule is a versioned, tested, owned engineering artifact. It starts as a hypothesis — "credential stuffing produces N failed logins from one source IP across M accounts in T minutes." The hypothesis is encoded as a query, tuned against historical data to establish a false-positive baseline, then deployed with a defined severity, routing destination, and runbook. The rule is reviewed on cadence and updated when the underlying event schema changes. Rules written once and never revisited drift into either silent failure (no longer matching anything) or alert fatigue (false-positive rate has grown until the alert is ignored). Both produce zero detection capability.
Alert fatigue is the silent killer. A rule producing ten true positives and a hundred false positives per week is equivalent to no rule — the on-call learns to filter it out. The resistance is a false-positive budget per rule (typical: under five false positives per true positive, tighter for high-severity) and quarterly audits that retire rules over budget. Programs that ignore the budget end up with a long list of "active" rules the on-call has internally classified as ignorable.
MITRE ATT&CK mapping. Detection rules in 2026 are typically mapped to MITRE ATT&CK tactic and technique identifiers. The mapping gives the program a coverage matrix independent of rule count and gives the on-call analyst a starting point for response — the technique identifier points to documented attacker behavior, expected follow-up steps, and known defensive responses.
A representative detection rule for credential stuffing, expressed as Splunk SPL:
index=auth event_type="auth.login.failure"
| bin _time span=10m
| stats dc(actor_email_hash) as unique_accounts,
count as total_failures
by source_ip, _time
| where unique_accounts >= 10 AND total_failures >= 50
| eval severity="high",
attack_pattern="credential_stuffing",
mitre_technique="T1110.004",
runbook="https://wiki/runbooks/credential-stuffing"
| sort -_timeThe query bins failures into ten-minute windows, counts distinct accounts and total failures per source IP, and surfaces IPs that hit at least ten distinct accounts with at least fifty total failures. The threshold is tuned against historical baselines — too low and the rule fires on legitimate password reset campaigns, too high and it misses slow-and-low credential stuffing. The annotations bind the alert to its severity, attack pattern, MITRE technique, and runbook URL so the on-call has full context the moment the alert fires. The same rule in Elasticsearch DSL or any other SIEM follows the same shape: event filter, time binning, aggregation, threshold, severity, routing.
Rules are typically expressed in pseudocode during design before platform-specific implementation:
RULE credential_stuffing
WHEN event_type = "auth.login.failure"
AND COUNT(distinct actor_email_hash) BY source_ip OVER 10m >= 10
AND COUNT(*) BY source_ip OVER 10m >= 50
THEN
severity = HIGH
action = ALERT to security-oncall
runbook = "credential-stuffing"
mitre = T1110.004
suppress_duplicates = 30mPseudocode makes the rule reviewable by security and application teams together before platform-specific encoding obscures the logic. The suppress-duplicates clause is small but critical — without it, a sustained attack floods the on-call with an alert per evaluation cycle.
The MTTD/MTTR Reality
The metrics that quantify A09 are mean time to detect (MTTD) and mean time to respond (MTTR). The IBM Cost of a Data Breach Report has tracked these annually for over a decade, and the 2024 edition reported a global mean MTTD of roughly 200 days from initial compromise to internal detection plus 70-plus days for containment — total dwell time near 270 days. The numbers improve modestly each year and remain shocking. Two-thirds of a year is a long time for an attacker to operate inside an environment.
The cost correlation is direct. Breaches detected and contained in under 200 days cost on average roughly $1.0M less than breaches that exceed 200 days. The investments that compress breach detection time are the ones this guide names — application-layer event emission, structured log discipline, detection-rule lifecycle, alert routing. None are exotic. The collective program cost is order-of-magnitude lower than one extended-dwell breach. Mttd mttr are the metrics by which the investment is measured, and the economics are unambiguous.
The Equifax 76-day window, the Capital One three-month window, and the Target weeks-long window are not outliers; they are representative of the median for organizations that have not yet matured their detection programs. Organizations that detect in hours or single-digit days have specifically invested in the disciplines this category names. MTTR is somewhat separable from MTTD but tracks the same investment — runbook quality, on-call tooling, and upstream observability are all downstream of the same engineering culture that produced the detection rule.
SIEM Integration Patterns
Splunk, Elastic Security, Datadog Cloud SIEM, Sumo Logic, Google Chronicle, Microsoft Sentinel — wherever the SIEM lives, the integration between application and SIEM has two sides with distinct failure modes.
What application teams owe the SOC. Events that conform to a stable schema. Field names that don't change without a schema-version bump and coordinated update. New event types added with notification, not surprise. Required fields — timestamp, event type, actor, source IP, trace ID — present on every event regardless of emitting service. Volume that is roughly predictable; sudden order-of-magnitude shifts communicated, not absorbed silently. Sensitive fields scrubbed at the application boundary, not assumed to be filtered downstream.
What the SOC owes application teams. Detection rules documented and reviewable by application teams. Thresholds and false-positive rates visible. Runbooks kept current. When a rule stops firing — because the application changed or the attacker pattern shifted — notification rather than silent decay. The schema feedback runs in both directions: if the SOC needs an additional field, the request goes upstream rather than the rule being abandoned.
Integration mechanics. The application emits structured JSON to stdout; a shipper (Fluent Bit, Vector, Logstash, OpenTelemetry Collector) tails stdout, parses, optionally enriches, and forwards to the SIEM. Application-direct connections to the SIEM are avoided because they couple the application's availability to the SIEM's and create credential complexity. The strongest A09 mitigation comes from treating the event schema as a shared API — same versioning discipline, same backward-compatibility expectations, same change-notification process that apply to any other contract.
The A09 Mitigation Playbook
The patterns above converge into a playbook that closes the structural gaps producing A09 findings. The discipline is applying them across every service rather than the one or two where security has had recent attention.
Build a log-coverage matrix. For each service, list the security-relevant events it should emit and verify each has a code path. Services as rows, event types as columns, coverage state as cells. The gaps are immediately visible. Teams that maintain the matrix can answer "are we logging credential stuffing attempts?" with a yes-or-no rather than a hopeful "I think so."
Run a periodic log review. Detection rules are the automated review; periodic human review catches what rules miss. A monthly cadence where security and application teams together review authentication anomalies, authorization-denial patterns, and administrative-action volumes catches drift the rules don't detect — shifting baselines, new attack patterns, emerging false-positive clusters.
Integrate with incident response runbooks. Each high-severity alert has a runbook describing response steps, lives in the same documentation system the on-call uses, and is reviewed when the rule is reviewed. Runbooks decay quickly without exercise; tabletops and fire drills keep them current. DevSecOps engineers who own the log pipeline frequently also own the runbook lifecycle.
Adopt OWASP-aligned logging libraries. The OWASP Logging Cheat Sheet and ASVS specify fields, formats, and practices refined over multiple revisions. Libraries aligned with the cheat sheet produce events downstream tooling has already been built to parse, compressing integration cost across SIEMs. Reinventing the schema per service produces the same content with higher integration friction.
Audit alerts quarterly. Rules that haven't fired are examined — either the threat is no longer relevant (retire) or the rule has decayed (update). Rules that fire frequently are checked against the false-positive budget. Rules that produced response are checked for runbook adequacy and response time.
Connect to configuration discipline. The logging configuration is itself a configuration surface. A logging level set to "error only" silently drops warn-level security events. A shipper misconfigured to drop high-volume events drops the credential-stuffing signal at the source. A05 security misconfiguration is the upstream category that produces logging failures when configuration is wrong; the two are tightly linked in any honest audit.
Treat the logging stack as supply chain. The library that emits events, the shipper that forwards them, the agent that enriches them — each is third-party code in the security path and part of your overall logging security posture. Apply the same discipline as for other dependencies: version pinning, vulnerability scanning, signed artifacts.
Detection Engineering Starts in the Application Code.
SIEMs cannot detect what the application does not emit. The largest single investment in compressing breach detection time is upstream of the SOC — it is the engineering culture that emits the right events with the right fields at the right boundaries, and treats the event schema as an API rather than as operational debris. SecureCodingHub trains developers to log the right things, in the right format, without leaking secrets, with a detection-engineering perspective baked in. If your team is shipping logs the SOC cannot use, we'd be glad to show you what changes when developers internalize security observability as a first-class engineering discipline.
See the PlatformClosing: Logs Are Not Detection
"We have logs" satisfies the box-check and answers no operational question. The category at A09 — owasp security logging failures — is the systematic shape of the gap between log existence and detection capability, and it closes only when application, detection-engineering, and response teams hold the same expectation about what events produce what alerts. Events have to be emitted. The format has to support querying. Rules have to fire. Alerts have to route. The on-call has to act. Each link is owned by a different group; each link's failure produces the same outcome.
Most application logging programs are weakest at the application-emission slice and strongest at the SIEM-storage slice — exactly the inverse of where the leverage is. Storing logs nobody parses is cheap and unhelpful. Emitting events rules can act on is the load-bearing investment, and it requires application-team engagement that platform-only programs cannot substitute for. Companies that have compressed detection time share a pattern: application teams treat security event emission as a feature requirement, and detection engineers treat the event schema as a contract worth defending.
Post-incident reports will continue to feature insufficient logging as a contributing factor because the gap is structural — every piece of the pipeline has been solved, and the integration is the work that doesn't happen by default. Application security monitoring is an engineering culture question. A09 will keep its place until that calculus shifts, one team at a time deciding that "we have logs" is no longer a sufficient answer to "can we detect a breach in progress?"