DevSec Station

The Most Common Secure Coding Mistakes Good Devs Make

Tanya Janca | SheHacksPurple Season 1 Episode 9

Use Left/Right to seek, Home/End to jump to start or end. Hold shift to jump forward or backward.

0:00 | 8:24

Security bugs aren't usually caused by 'bad developers'. More often, they're the result of good developers making rational decisions under deadlines, competing priorities, and imperfect systems.

This episode is sponsored by Maze.

In this episode of DevSec Station, Tanya Janca explores why common secure coding mistakes are often incentive problems rather than knowledge problems. You'll learn why insecure patterns emerge, why simply telling developers to "be more careful" doesn't work, and how changing your development environment can make secure coding the easiest path forward. 

You'll learn:

  •  why good developers still introduce security vulnerabilities 
  •  how deadlines, delivery pressure, and operational complexity influence coding decisions 
  •  why 'shame and blame' doesn't improve software security 
  •  several practical examples of how to replace insecure patterns with more secure ones 
  •  how to identify recurring shortcuts and improve them instead of fighting them 

Tanya shares several real-world examples of secure coding shortcuts that teams make every day (from copy-pasted authentication checks to inconsistent secret handling) and explains why these decisions are understandable in the moment, even though they create security problems over time (also known as 'security drift'). She also demonstrates how small changes to defaults, shared libraries, and team patterns can eliminate entire classes of recurring mistakes. 

If you do just one thing after listening to this episode:

Identify one insecure pattern that keeps showing up in your team's code base and ask why it exists before trying to eliminate it. If you don't know the why, you can't fix it. Then replace that shortcut with an easier, more secure path.

DevSec Station is a podcast by Tanya Janca (SheHacksPurple), focused on short, practical lessons that help software developers build more secure software.

Follow Tanya:

This episode is sponsored by Maze.

One of the biggest problems in security right now is that every vulnerability scanner says everything is critical, and honestly, no one has time for that.

Maze uses AI agents to investigate vulnerabilities in context, so you can focus on the issues that are actually exploitable in your environment, not just theoretically scary.

Their AI agents also generate and prioritize fixes that knock out multiple vulnerabilities at once, which is honestly the kind of scaling that security teams need right now.

Learn more about Maze https://mazehq.com/devsec

SPEAKER_00

I'd like to clear something up right now. Most security bugs are not caused by bad developers. They're caused by good developers doing exactly what the system rewards them for doing. They aren't stupid mistakes. They're rational ones. Hi, I'm Tanya Jenka, also known as SheHacksPurple. Welcome to DevSecStation, a podcast for software developers who want to build more secure software. In each episode, I'll share a short practical lesson about secure coding, software security, and how to build safer systems without slowing development down. You can jump in at any episode, at any time. No homework required. This episode is sponsored by Maze. One of the biggest problems in security right now is that every vulnerability or cloud scanner says everything is critical. And honestly, no one has time for that. MAZES uses AI agents to investigate vulnerabilities in context, so you can focus on the issues that are actually exploitable in your environment and not just theoretically scary. Their AI agents also generate and prioritize fixes that knock out multiple vulnerabilities at once, which is honestly the kind of scaling that security teams really need right now. Learn more about maze at mazehq.com slash devsec. If you've ever looked at a security issue and thought, I knew better, why did I do that? Oh this episode's for you. There is a very persistent myth in security that insecure code comes from ignorance, that if developers just knew more, these issues would magically go away. But in practice, most insecure patterns come from incentives, from deadlines, performance reviews, feature pressure, operational complexity. When the system rewards speed, availability, and delivery, developers optimize for those things and not for security. That's not negligence, that's professionalism. I'd like us to look at a few very common examples of how this happens. You skip input validation because the data is internal, and you're trying to hit a deadline and you know that it's safe. You reuse old authorization code because it mostly works, and rewriting it feels pretty risky. You log less than you know you should because verbose logs they cost too much. You copy a known pattern because it worked last time, even though you know that maybe it's not ideal. In isolation, each of these decisions totally makes sense. They made sense in that moment. But over time, these shortcuts can really stack up. And eventually, they can turn into vulnerabilities. This isn't about bad judgment. That's not what I'm talking about. It's about local optimization in a very complex system. So, how do we fix this? A bad approach would be assuming insecure code means someone messed up and then blaming them and shaming them. That leads to discussions, lectures, more rules, more shame, and shame does not produce better software. A slightly better approach is reminding developers to slow down and be more careful. This could help in the short term, but it still asks people to fight incentives using willpower. And willpower is an extremely fragile security control. The best approach isn't telling developers try harder. It's changing the environment so that the secure choices are the easiest and best choices. Let me give you some concrete examples of what that actually looks like. Example number one: authentication checks. So instead of copying and pasting authentication checks everywhere, teams either use a trusted product or they create a shared helper or middleware and they use it repeatedly every single time. Now the incentives have shifted. Using the secure pattern is faster than rolling your own. Example two, authorization logic. Instead of sprinkling role checks all throughout your code base, teams centralize authorization decisions in one single function. Developers don't have to remember all the edge cases. They can just call that helper that already enforces it for them. When. Example three, input validation. Instead of ad hoc validation in every endpoint, teams adopt a standard validation library or schema. Skipping validation or writing your own stops being the shortcut because the safe version is already there and it's easy to use and everyone else on your team is doing it. Example four, error handling. So instead of catching exceptions inconsistently, teams define a standard error handling library. Then you do it the same safe way every single time. Example five, secrets and configuration. So instead of letting developers decide where secrets live, team make secret management the only supported path. You scan every check-in for secrets, and if it's not in the secret manager, it just doesn't work and does not run and does not let you check it in. When? In all of these examples, we didn't fix security by giving a developer a big lecture. We fixed it by making the secure option easier, faster, and less risky than some shortcut that they usually did before. That's how we can eliminate insecure patterns without blaming people. If you do just one thing this week after this episode, please do this. Identify one insecure pattern your team uses for good reasons and then make it safer. How do we do that, right? Step one, find a security shortcut that has been happening for some time. Perhaps a security tool has been chirping about that same thing forever and you have been suppressing that result. Perhaps there's a comment that keeps showing up over and over in your PR reviews. A security incident was caused by this shortcut, or perhaps there was like a near miss as a result. Something that is copied and pasted all the time, but no one maintains that thing. Code that has a note on it that says fix later, but has never been fixed. Developers don't discover insecure patterns by knowing security better and being an expert on vulnerabilities. They discover them when the same problem shows up repeatedly. Okay, step two, ask why does this exist? Is it saving time? Is it reducing risk? Is it avoiding outages? Because if you change it and you don't also fix why it exists, it's definitely going to come back and we don't want that. Okay, so you need to understand the why. Step three, improve the pattern. So for example, replace that copy paste auth check with a shared helper. Add a safe default wrapper instead of raw access. Introduce a lightweight validation library instead of ad hoc checks that are inconsistent. You are not asking people to stop doing their jobs, you are giving them a safer way to succeed. Good developers don't write insecure code because they don't care. They rate it because they care about shipping, stability, and users. When we acknowledge that, security stops being adversarial and it starts becoming collaborative. And that is what we want. Thanks for listening to DevSecStation. If you enjoyed this episode, please subscribe, share it with a friend, or leave a review. It helps more people discover the show. If you'd like to learn more, I'm Tanya Jenka, also known as SheHacksPurple. And I teach secure coding training for software developers. You can find me online at shehackspurple.ca. Thank you for being here.