Safeguard
Developer Tools•

How do you test that your app actually logs security events?

Write tests that trigger a login failure, a denial or a role change and assert the log event appears. Steps, a test matrix and failure cases to simulate.

Safeguard Security Team
4 min read

Treat logging as behaviour with tests. Trigger a failed login, an access denial and a role change in a test environment, capture the log output, and assert that each event appears with the right name and fields and without secrets. Run these tests in CI so a refactor cannot silently remove an event.

Why test it at all

OWASP Top 10 A09 lists conditions that mark a logging failure, and two stand out for testing: auditable events such as logins and failed logins are not logged, and penetration tests and DAST scans trigger no alerts. Both are discovered late if no one checks.

The OWASP Logging Cheat Sheet says logging should be part of code review and security testing. Its checks include whether events are classified consistently and fields are defined correctly, whether logs resist injection, how the app behaves when logging fails, whether logging can be used to exhaust resources, and whether access controls on log data work.

A test matrix

TestActionAssert
Failed login loggedPost a wrong passwordOne authn failure event with account and source, no password
Successful login loggedLog in correctlyOne success event
Denial loggedRequest another user's recordOne authz failure event with resource ID
Role change loggedChange a role as adminAudit event with old and new values
Injection resistanceSend a username with a newline and fake log textOne event, newline escaped or encoded
Secret not loggedSend a known fake token in a header and bodyFake value absent from all output
Logging failureMake the log sink unavailableThe request still completes, an error is raised elsewhere
VolumeSend a burst of failuresRate controlled, no disk or memory blow up

How to build them

  1. Configure the logger in tests to write to an in memory buffer you can read.
  2. Write each test as a small request, then search the buffer for the expected event name.
  3. Check the fields by key, not by matching a whole string, so formatting changes do not break tests.
  4. Add a negative test for each secret type you handle, using obvious fake values.
  5. Add one test per audit event that your auditors will ask about.
  6. Run the suite in your pull request pipeline so missing events block a merge.

Keep the number of tests small and meaningful. A short list that always runs beats a long one people disable.

Test detection too

Logs only help if something reads them. Once a month, run a harmless simulation, such as twenty failed logins across ten test accounts, and check that the alert fires and reaches a person. If a DAST scan against staging triggers nothing, that is the A09 condition in action.

Simulate logging failure

The Cheat Sheet specifically asks for simulated failures such as database loss, disk full and permission errors. The result you want is that the user request still works and an alert says logging is broken. See logging failures must not crash your app.

Try it yourself

Click through it at your own pace, or open it full screen.

Quick check

Where should these tests run?

In the same pipeline as your other tests, on every pull request, so a missing event blocks the merge.

Do I need to test every event?

No. Cover authentication, authorization, privilege changes and any event auditors rely on.

Safeguard's policies and gates run checks on pull requests in the same way. Try a free scan at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.