Web Security / Advanced: assurance, supply chain, and recovery / Lesson 15
Security logging and safe error handling
Create useful evidence for authorized investigation without exposing credentials or converting alerts into unsupported conclusions.
On this page
Lesson goals
- Define bounded event and public-error contracts.
- Distinguish observation, hypothesis, and confirmed impact.
Log to answer a concrete security question
Useful events can explain authentication changes, denied access, sensitive updates, file processing, and policy failures. Define what responders need to know: time, source, action, outcome, relevant opaque identifiers, and correlation context. Avoid collecting every request body or header merely because storage is available. Private notes, passwords, session values, reset links, and unnecessary personal information do not belong in ordinary diagnostics. Logs are sensitive assets with their own access, retention, integrity, and availability requirements. A large archive is not useful if responders cannot identify the relevant candidate, event, and decision safely.
Keep the evidence envelope small and explicit
The event is a fictional access denial with no real person or private payload. Its identifiers support a controlled investigation relationship rather than public disclosure. A real schema should validate event types, timestamps, sources, and field bounds, and preserve the difference between source time and collection time where needed. Structured logging can reduce ambiguity, but encoding a message as JSON does not itself make the source trustworthy or the storage tamper-resistant. Protect collection failures and dropped data as observable states; no events is not proof that no security issue occurred.
{
"event": "authorization-decision",
"source": "synthetic-portal",
"subjectRef": "lab-subject-a",
"resourceRef": "lab-note-1",
"operation": "edit-note",
"outcome": "denied",
"correlationRef": "lab-request-17"
}
The record is not sent or collected from a system. References are synthetic and contain no credentials. A production envelope needs trusted sources, access controls, retention, and verification of collection completeness.
Allowlist diagnostic fields rather than dumping objects
The pure function copies only three declared fields from synthetic input and verifies that an unrelated private-body field is absent. This demonstrates minimization at one boundary, not a general redaction engine. A real logger must validate types, control multiline content appropriately, and handle nested or transformed sensitive values according to policy. Removing a few familiar key names cannot guarantee secrets are gone. Review error trackers, browser traces, analytics, and support attachments as part of the same information flow. Keep diagnostic access limited to people with a justified need and expire records according to purpose.
def diagnostic_fields(event):
allowed = ("action", "outcome", "correlationRef")
return {key: event[key] for key in allowed if key in event}
original = {"action": "edit-note", "outcome": "denied", "correlationRef": "lab-17", "privateBody": "synthetic-content-not-collected"}
summary = diagnostic_fields(original)
assert set(summary) == {"action", "outcome", "correlationRef"}
assert "privateBody" not in summary
The program reads only invented in-memory data and sends nothing. It shows one allowlist behavior, not detection of every secret or verification of a real logging platform. The original object is not modified.
Expose useful failures without unnecessary internals
A public error should support the legitimate next action without disclosing stack traces, query text, tokens, or private record existence beyond the intended policy. Keep detailed diagnostics behind controlled access and use an opaque correlation reference where helpful. Choose status and message behavior consistently with the API contract instead of relying on one universal error code to prevent information leakage. Error handling must not continue a protected mutation after reporting denial. Failed downstream jobs, retries, and partial results need explicit state semantics. A generic message alone does not establish safe rollback or correct transaction behavior.
Use evidence to test a hypothesis
A detection rule identifies patterns worth review; a count of failures alone does not confirm compromise. Correlate authorized context and preserve uncertainty about clocks, missing events, and source reliability. Test malformed, missing, delayed, and repeated event cases with benign fixtures. Verify collection and access paths in an authorized environment rather than triggering real abuse to make an alert fire. Route findings to an accountable owner with an approved runbook. Feedback from incidents should improve event quality and error behavior. Neither a quiet dashboard nor a local field-copy assertion proves the complete service is secure.
Common errors and fixes
An error response exposes a stack or token
- Why it happens
- Internal diagnostics are returned to an untrusted audience.
- How to fix it
- Separate public failure fields from protected diagnostics.
- Prevent it next time
- Test failure paths for data minimization.
No logs is called no incident
- Why it happens
- Collection health is assumed rather than verified.
- How to fix it
- Verify evidence completeness and preserve the observation gap.
- Prevent it next time
- Monitor missing and delayed evidence states.
A failed request leaves partial protected work
- Why it happens
- Error reporting is confused with transactional refusal.
- How to fix it
- Verify state and downstream effects under the operation contract.
- Prevent it next time
- Assert unchanged state where denial requires it.
Check your understanding
1. A log function omits a password key. Does that prove every diagnostic is safe?
Show worked solution
No. Sensitive data can appear in nested values, URLs, transformed fields, traces, and other channels. Minimize collection, validate the approved schema, and review the complete diagnostic flow rather than relying on one name-based filter.
2. A burst of failures precedes one success. What conclusion is justified?
Show worked solution
It is a pattern for authorized triage, not proof of compromise by itself. Review method, user intent, device and operation context, timing, and related outcomes while keeping unknowns explicit.
Key takeaways
- Logs and errors are information-disclosure boundaries.
- Minimize fields and verify collection completeness.
- Signals support investigation rather than automatic certainty.