Table of Contents
1. Safe Defaults in Modern PHP — A Foundation for Secure Code
Security is not a checklist.
It’s a posture
— a way of writing code that
reduces risk before vulnerabilities even have a chance to appear.
Modern PHP gives us tools that
make secure behavior the default,
not an afterthought.
This page introduces a mindset of how to
design code that is predictable, explicit, and difficult to misuse.
Security begins with shape,
clarity, and boundaries.
1. Prefer Explicitness Over Convenience
Ambiguity is the enemy of security.
Safe defaults come from:
- explicit types
- explicit boundaries
- explicit data shapes
- explicit error handling
- explicit dependencies
When the code is clear, the behavior is predictable.
Predictability is security.
2. Validate Early, Reject Early
A secure system does not accept “almost valid” input.
Safe defaults mean:
- validate at the boundary
- reject unknown fields
- enforce stable shapes
- avoid implicit coercion
- treat missing data as an error, not a default
A predictable input shape
prevents entire classes of vulnerabilities.
3. Use Modern PHP Features to Reduce Risk
Modern PHP gives us tools that make unsafe behavior harder:
- readonly properties prevent accidental mutation
- enums prevent invalid states
- typed properties prevent loose data
- exceptions make failure explicit
- attributes clarify intent
- constructor promotion reduces boilerplate that hides mistakes
These features aren’t “nice to have”.
They are security features disguised as language improvements.
4. Keep Data Structures Stable and Boring
Security thrives on boring code.
Avoid:
- arrays with mixed shapes
- dynamic keys
- silent fallbacks
- magic behavior
- implicit defaults
Prefer:
- DTOs
- stable return types
- predictable structures
- clear contracts
When the data shape is stable,
the system is harder to exploit.
5. Minimize Surface Area
Every public method, every global state,
every entry point is a potential risk.
Safe defaults include:
- small classes
- narrow interfaces
- minimal public API
- no unnecessary statics
- no global state
- no hidden behavior
The smaller the surface,
the smaller the attack vector.
6. Fail Loudly, Not Quietly
Silent failure is a security vulnerability.
Safe defaults:
- throw exceptions
- log meaningfully
- avoid swallowing errors
- avoid “best effort” behavior
- avoid magical recovery
A system that fails loudly
is easier to secure
and easier to debug.
7. Avoid Invention — Use Real, Documented Mechanisms
Security collapses when developers invent:
- custom hashing
- custom encryption
- custom token formats
- custom session logic
- custom sanitization
Safe defaults mean:
- use password_hash()
- use password_verify()
- use libsodium
- use prepared statements
- use built‑in escaping
- use framework‑provided CSRF protection
Security is not 🦋💥🐟
a place for creativity.
8. Treat Boundaries as Sacred
Every boundary is a security checkpoint:
- HTTP request → validation
- database → parameterization
- template → escaping
- filesystem → explicit paths
- session → regeneration
- authentication → hashing
Safe defaults mean
treating each boundary as a place where
untrusted data must be shaped, validated, or rejected.
Summary
Safe defaults in modern PHP come from:
- explicitness
- stable shapes
- early validation
- modern language features
- minimal surface area
- loud failures
- using real, proven mechanisms
- respecting boundaries
Security is not a checklist.
It’s a way of writing code that is predictable,
intentional, and difficult to misuse.
This page describes secure defaults and common practices in modern PHP. It is not a complete security guide, and it does not replace formal audits or framework‑specific documentation. These principles are consistent enough to be useful, but security always requires context, judgment, and ongoing review.
