The ten reduce to a few habits: validate input · separate code from data · verify integrity · enforce
authz server-side · configure to a baseline · log the right events.Web-specifics (SQLi/XSS/CSRF/SSRF)
are dissected in Chapter 13.
Two patterns that prevent the most bugs
INPUT ─▶ [INPUT VALIDATION] ─▶ logic ─▶ [OUTPUT ENCODING] ─▶ destination
allowlist, SERVER-SIDE, make inert FOR (HTML / SQL /
parse to expected type THIS interpreter shell / URL)
Validate on the way IN; encode on the way OUT. Different moments, different jobs — run both
(defense in depth). Neither replaces the other.
Positive validation (allowlist) > denylist — you can define what's allowed; you can't list every
bad input.
Client-side validation is NOT a security control (client is attacker-controlled) — re-do it server-side.
Encoding is context-specific — HTML ≠ JS ≠ URL ≠ SQL; wrong-context encoding = no protection.
Parameterized queries move the code/data boundary into the driver — the robust fix for injection.
SAST vs DAST vs SCA — when to use what
SAST
DAST
SCA
Examines
Your code, at rest
Running app, from outside
Third-party dependencies
SDLC phase
Code (early)
Test (needs deployed app)
Build + continuous
Points to a line?
Yes
No (a request)
Yes (component/version)
Main weakness
False positives
False negatives
Only as good as its vuln DB
Answers "do we use Log4j, where?"
No
Maybe
Yes
Use all three + human review + threat modeling. Tools find recognizable bugs; design & business-logic
flaws need threat modeling (the 4th blind spot). Don't drown devs in unfiltered output — tune, prioritize
by risk, gate on the high-confidence/high-severity subset (Ch.31 ci_gate).
Log4Shell (CVE-2021-44228) — the anchor in one box
Why brutal: a deeply transitive dependency in countless products — orgs didn't know they ran it.
The decisive question wasn't "how does it work?" but "do we use it, and WHERE?"
Lesson: the bottleneck is discovery, not patching → inventory deps (SBOM), monitor advisories,
patch fast. You cannot protect what you don't know you have (Ch.1), in the language of dependencies.
Four questions: What are we building? What can go wrong (STRIDE)? What do we do about it? Did we do a
good job? Deliverable = verifiable security requirements, not a diagram. Threat-model anything
crossing a trust boundary or touching sensitive data — even "simple" features (they hide the worst flaws).
Certification crosswalk
Concept
CompTIA Security+
(ISC)² CISSP domain
Secure SDLC / shift left
2.0 / 3.0 / 4.0
Software Development Security
OWASP Top 10 / injection / XSS
2.3 App attacks; 3.0 Architecture
Software Development Security
Input validation / output encoding
3.0 Secure coding
Software Development Security
SAST / DAST / SCA
4.0 Security Operations (tooling)
Software Development Security; Security Assessment
Supply-chain / dependency risk
2.0 Threats; 5.0 GRC
Security & Risk Management; Software Dev Security
Threat modeling / STRIDE
1.0 / 3.0
Security Architecture & Engineering
Project additions this chapter
Meridian program: one-page Secure SDLC policy (gates per phase: threat-model → SAST → SCA+secret
scan → DAST → log+monitor).
bluekit toolkit:appsec.py — scan_dependencies(reqs) (SCA in miniature; hand-traced vs Log4Shell).
Common pitfalls
Treating the OWASP Top 10 as a one-time test instead of risks to manage continuously.
Relying on client-side validation, or on input validation alone (you also need output encoding).
"Fixing" injection by stripping characters (denylist) instead of parameterizing.
Deleting a hard-coded secret without rotating it (version control keeps history → it leaked).
Ignoring transitive dependencies; declaring victory after Log4Shell without adopting SCA/SBOM.
Drowning developers in unfiltered scanner output until they ignore the findings that matter.
Skipping threat modeling on "simple" features — where the worst design flaws hide.
We use cookies to improve your experience and show relevant ads. Privacy Policy