Security by design: stop patching holes you dug yourself
Posted on May 29, 2026 • 12 minutes • 2382 words
Table of contents
- Security by design != a last-minute look
- Threat modeling: think like an attacker before an actual attacker does
- Basic mistakes we’re still making in 2026
- 12-Factor Apps, configuration, and secrets: don’t be your own worst enemy
- CVE: the public catalog of screw-ups and how to actually use it
- Pentesting, reviews, and security as a habit
- Security by design in practice: what you should already be doing
- Epilogue: you’re already paying the price
- Quick glossary (so nobody gets lost in the acronyms)
- Sources and references
Most of the “security problems” you end up patching at 3 a.m. aren’t accidents.
They’re decisions made months earlier under pressure, over a cup of coffee, with the unshakeable conviction that “we’ll fix it later.”
Security by design is exactly about that: building security into the development cycle from the start, instead of relying on the holy trinity of scanner + pentest + blind faith.
Let’s get concrete: threat modeling, core principles, mistakes we’ve been repeating since 2010, and how to stop shooting yourself in the foot with your own code.
Security by design != a last-minute look
The average developer’s security lifecycle is as predictable as a broken clock.
First you design the app thinking about features. Wonderful.
Then you build it thinking about deadlines, because project management has somehow turned “just rough estimates, don’t worry, they’re not binding” into “commitments carved in stone, because you said so.”
And just when the suffering seems to be over and everything is about to ship, someone pipes up quietly: “hey, did we run any security scans on this?”
Awkward silence. Someone stares at the ceiling. Someone opens a new browser tab.
The security by design approach proposes something radical: doing things in the right order.
You bake security requirements into the SDLC (Secure Development Lifecycle) from day one, you do threat modeling when you’re defining the architecture — not six months later with the app already in production and the CEO staring you down.
You also integrate static analysis, code reviews, and security tests into the pipeline, instead of crossing your fingers once a year during the annual pentest.
OWASP even has a full Secure by Design Framework dedicated to this: security embedded in architecture, design, code, and operations — instead of slapping patches on a structure that was never designed to hold up in the first place.
Threat modeling: think like an attacker before an actual attacker does
Threat modeling sounds very academic — like something you do in a blazer in front of a whiteboard, with a blue marker that always runs dry at the worst possible moment.
The reality is simpler: it means sitting down and answering four straightforward questions:
What are we building (diagrams, data flows, components)? What can go wrong? What are we doing about it? And are we actually doing it right, or are we just fooling ourselves?
Microsoft, OWASP, and pretty much every modern guide agree: threat modeling should happen in the early stages of the SDLC — in requirements and design — and be revisited every time the architecture changes significantly.
Disclaimer: I know that citing Microsoft as a security example is a bit like citing a politician as an example of integrity — sure, neither may actually practice what they preach, but they do talk about it quite a lot and quite well, which was the point I was trying to make.
Anyway, the concrete benefit is that you catch design flaws (poor separation of concerns, insecure data flows, sensitive data stored in plain text because hey, who’s ever going to break in?) before you’ve written a single line of code. Which means you can prioritize security measures based on actual risk — not based on what blew up on Hacker News this week.
What this avoids, among other things, is that conversation where — with the app already in production — someone discovers the entire data model was never designed to comply with GDPR.
Or that the permissions model assumes all users are good people with good intentions.
Basic mistakes we’re still making in 2026
OWASP has been publishing its Top 10 vulnerabilities list for years, and the fascinating part — or the devastating part, depending on how you look at it — is that the same flaws show up edition after edition, with the reliability of that one relative at Thanksgiving who always says the exact same things.
Security misconfiguration is the all-time champion: default usernames and passwords left unchanged, unnecessary ports and services exposed, admin panels and debug endpoints live in production because nobody remembered to take them down before heading to lunch.
Right next to it is catastrophic credential management: API keys and passwords hardcoded directly into source code, config files with plaintext secrets cheerfully committed to public repositories. Entire startups have discovered this way that their AWS keys had been indexed by Google for months.
Then there’s access control, as sturdy as a revolving door: admin routes accessible to anyone who knows the URL, APIs that blindly trust whatever the client sends — including an isAdmin: true field that no joke, this exists, it has happened, and is probably happening somewhere in the world right now.
And finally, the timeless classic of not updating dependencies with reported CVEs — sometimes months or years old — because “now’s not the time,” and it always ends up being the time in the worst way possible.
OWASP itself sums it up with the infinite patience of someone who has been saying the same thing for years: most of the risk comes from systematic design and configuration mistakes, not from ultra-complex spy-movie attacks with gadgets and a dramatic soundtrack.
12-Factor Apps, configuration, and secrets: don’t be your own worst enemy
The 12-Factor Apps manifesto became famous mostly for deployment and scalability reasons, but if you read it carefully, two of its factors are directly about security — and most people ignore them because they’re buried between “logs” and “processes” and aren’t exactly a riveting read.
The first is the config factor: store configuration in the environment, not in the code.
Credentials, endpoints, third-party keys — all of it should live in environment variables or a dedicated secrets store, not baked into the repository like a welcome note.
Storing usernames and passwords in source code is the most obvious violation of this principle and, at the same time, the most efficient way to end up in an incident report with your name prominently featured on page one.
The second is the backing services factor: treat databases, queues, caches, and other external services as attached resources, with proper credentials and permissions for each environment.
Combining this philosophy with solid IAM practices and data protection (secret stores, encryption in transit and at rest) is basically the bare minimum for any modern application that wants to stay out of the news for the wrong reasons.
CVE: the public catalog of screw-ups and how to actually use it
The CVE (Common Vulnerabilities and Exposures) system is the standard database for identifying and cataloging known vulnerabilities in software and hardware. In practical terms: each CVE is an identifier (CVE-2025-XXXX) that describes a specific vulnerability — whether it’s a buffer overflow, an SQL injection, or an authentication flaw that shouldn’t exist but does, complete with a name, a description, and an official case number.
MITRE and a network of CNAs maintain and assign those IDs, with the patience of people who have made cataloging other people’s mistakes their life’s work.
The most common mistake with CVEs isn’t ignoring them entirely — that would be too obvious a failure — it’s dismissing them with a “not exploitable in our case” without any real analysis to back it up, or simply having no process to review them on a regular basis.
The second is almost worse, because at least the first one implies someone actually read the description.
The sensible approach is to integrate dependency and container scanners into the pipeline (SCA, container scanning) and maintain a vulnerability management process: prioritize CVEs by severity and actual exposure, patch, document.
Not exactly exciting, but that’s what separates the teams that find out about a problem before an attacker does from the ones that find out by reading a tweet.
Pentesting, reviews, and security as a habit
Pentesting is not the final boss, and it’s not the seal of approval that magically turns an insecure app into a secure one. It’s just one layer in a security by design program, and treating it as the only validation mechanism is exactly like getting a blood panel once every five years and calling yourself in peak shape.
A well-run pentest helps you identify vulnerabilities you missed ( bugs, insecure configurations, real attack vectors you hadn’t considered), validate that your controls actually work the way you think they do, and meet the requirements of frameworks like PCI-DSS, HIPAA, or GDPR.
The key is doing it regularly (not just after an incident has already happened), scoping it properly, and making sure the findings actually make it into the backlog and get closed — instead of collecting dust in a nicely formatted PDF that nobody opens again until the next pentest.
All of this is complemented by static and dynamic analysis integrated into CI/CD and code reviews focused on security patterns.
And by logging and monitoring that detects anomalous behavior before it becomes an incident — not just logs that record the crash after it’s already too late to prevent it.
Security by design in practice: what you should already be doing
If you want to stop patching holes you dug yourself, the bare minimum has four stages and none of them are optional.
In requirements and design: include explicit security requirements from the start (encryption, auditing, permissions, regulatory compliance) and run threat modeling on critical features and systems before anyone has written a single line of code.
In implementation: follow secure coding guidelines , manage configuration and secrets properly, and treat security as an acceptance criterion — not as a footnote that will be revisited “when there’s time.”
In verification: SAST, DAST, dependency and container scanners in CI/CD, code reviews with a security checklist, and periodic pentests well-integrated into the improvement cycle — not as an annual traumatic event.
In operations: monitor security events and anomalous activity, maintain CVE and patch management processes, and run post-incident analyses with real corrective actions — not solemn promises that “this will never happen again.”
Epilogue: you’re already paying the price
If all of this sounds like a lot of work, it’s because it is.
Integrating security into the development cycle requires discipline, tooling, and a willingness to have uncomfortable conversations about risk when everyone would rather be talking about features.
It’s not “cool.” It doesn’t show up in the roadmap. It doesn’t generate impressive demos to show off to management and clients.
But here’s the trap: the cost doesn’t go away if you decide not to pay it now. It compounds.
Every decision made under pressure, every secret hardcoded “just temporarily,” every vulnerability management process postponed because there are more urgent things right now — all of that is a deferred bill that someone is going to have to pay.
Sometimes it’s you, at 3 a.m. Sometimes it’s a customer whose data ends up in a forum they’d rather not be mentioned in.
The real question isn’t whether security by design is expensive — it’s how much you’ve already spent fighting fires you started yourself, and whether that money would have been enough to prevent them.
Quick glossary (so nobody gets lost in the acronyms)
Because “I know what that is” means different things to different people — and in security, that has consequences.
- Security by design : approach in which security is integrated from the very start of design and development, rather than being bolted on when it’s already too late to change anything without crying.
- SDLC (Secure Development Lifecycle) : development lifecycle with security activities baked into every phase — requirements, design, implementation, testing, deployment. Turns security into part of the process instead of an awkward appendix nobody wants to deal with.
- Threat modeling : the process of identifying assets, threats, vulnerabilities, and mitigations before — and during — development. Ideally before someone external does it for you and hands you a report full of red flags.
- OWASP : open project that publishes security guides and standards for web applications, best known for the Top 10 that has been collectively embarrassing the industry with the same mistakes for decades.
- 12-Factor Apps : a set of principles for modern applications that, among other things, insist on separating configuration from code and treating external services as attached resources.
- CVE (Common Vulnerabilities and Exposures) : standard for identifying known vulnerabilities. The historical record of everything that went wrong and already has an official reference number.
- Pentesting : controlled intrusion tests carried out by professionals to evaluate the security of systems and applications. They work great — as long as they’re not the only security mechanism you have.
Sources and references
Because “a coworker mentioned it in standup” is not a valid academic reference, even if it sometimes feels like it should be.
- Threat Modeling and Secure by Design Applications – ISACA - ISACA. Article on how to integrate threat modeling into the secure development cycle.
- OWASP Secure by Design Framework - OWASP. Reference framework for embedding security into architecture, design, code, and operations.
- Understanding the Secure Development Lifecycle (SDLC) for App Security - PointGuard AI. Practical guide to the SDLC and its security phases.
- Secure by Design: The Complete Guide - Check Point. Complete overview of the security by design approach applied to modern development.
- Practice Security by Design – Salesforce Trailhead - Salesforce. Hands-on module on security integrated into the SDLC.
- Software Development Lifecycle Threat Modeling - Versprite. How to apply threat modeling at each phase of the SDLC.
- Threat Modeling – Microsoft Security Engineering - Microsoft. Official Microsoft guide to threat modeling in the SDL.
- OWASP Top 10: Security Misconfiguration Explained - Security Journey. Detailed explanation of the misconfiguration category in the OWASP Top 10.
- The In-Depth Guide to OWASP’s Top 10 Vulnerabilities - Jit.io. In-depth analysis of the 10 most critical vulnerabilities according to OWASP.
- Secure 12-Factor Apps - Think DevOps. How to apply 12-Factor principles with a security focus.
- The Twelve-Factor App: Config - 12factor.net. Factor III of the manifesto: separating configuration from code.
- Common Vulnerabilities and Exposures (CVE) - Rapid7. Explanation of the CVE system and how to use it in vulnerability management.
- CVE – Fortinet Cybersecurity Glossary - Fortinet. Definition and industry context of the CVE system.
- Best Practices for Penetration Testing - Cobalt. Best practices for planning and running effective pentests.
- Pentest Best Practice Checklists - Shubham Sharma (LinkedIn). Practical checklist of pentesting best practices.
