Podcast Summary: The Pragmatic Engineer
Episode: Code Security for Software Engineers
Date: November 26, 2025
Host: Gergely Orosz
Guest: Johannes Das (VP of Code Security, Sonar)
Overview
This episode dives deep into practical code security for software engineers, from fundamental principles to evolving threats introduced by AI and the modern tooling landscape. Guest Johannes Das, a 20-year veteran in code security and penetration testing, shares hands-on advice, industry anecdotes, and data-driven insights based on his work at Sonar, where billions of lines of code are analyzed daily. The discussion covers the changing landscape of code security ownership, the realities and limitations of security tools, handling dependencies and supply chain risk, the rise of AI in both coding and security, and hard truths about the ongoing battle between attackers and defenders.
Key Discussion Points and Insights
1. Path to Code Security—Johannes’s Journey
- Early Inspiration: Johannes’s journey started two decades ago when his computer was hacked—prompting a fascination with security that led him to university competitions and penetration testing. (01:32–02:30)
- “I remember I got hacked... I was super frustrated, right? And then also super intrigued.” — Johannes Das [01:34]
- Practical Learning: Capture the Flag (CTF) competitions provided the best hands-on experience, eventually leading to a career in professional penetration testing and startups, culminating at Sonar.
2. Penetration Testing: How Attackers Think
- Types of Testing: Explained black-box testing (no internal access, simulating real attackers) and white-box testing (with code or system access). (04:01–04:59)
- “You treat it as a real attacker, like, with no knowledge… and then trying to figure out what could be vulnerabilities.” — Johannes Das [04:08]
- Tools and Approach: Reliance on both standard automated discovery tools and manual probing for nuanced vulnerabilities. Manual exploration is still the “exciting part.” (05:23–05:57)
3. Who Owns Code Security? Shifting Left
- Developers’ Responsibility: Modern software orgs expect developers to own code security. Security issues begin in code, so only developers can fix them. Security teams shouldn’t have to process each vulnerability discovered during development. (06:27–07:29)
- “Every software vulnerability basically manifests in code and developers are the only ones writing the code...they should own all those code security issues.” — Johannes Das [06:36]
- Role of Security Teams: They oversee broader application security, compliance, and larger org-wide initiatives, focusing their expertise on complex areas like cryptography or auth logic. (08:02–09:31)
- “I just think that when you write software...security team shouldn’t waste their time in looking into every single security issue that happens during development.” — Johannes Das [08:29]
- Platform Team Analogy: Security teams should serve as specialized experts and tool builders for engineers, not gatekeepers for every code issue. (09:31–10:17)
4. How the Landscape Has Changed
- From Siloed to Iterative: Historically, security was the domain of compliance-focused security teams, with slow dev cycles allowing time for audits. Modern rapid release cycles (multiple per day) and AI-assisted coding require security to be integrated into developer workflow. (11:10–11:44)
- “We are moving a lot faster now.” — Johannes Das [11:43]
- Noise vs. Signal: Old-school security tools were built for auditors and created high “noise” (false positives); developers need actionable, not overwhelming, notifications. (13:15–14:36)
- “If you drive a car and you have a security guy in your passenger seat and he would scream... that’s maybe interesting, the first 50 meters, but then gets super painful and annoying.” — Johannes Das [14:00]
5. Defining “Code Security” and Common Vulnerabilities
- Definition: Code free of exploitable issues—which could be logic errors, memory safety bugs, or classic vulnerabilities (SQL injection, XSS, etc.). As systems evolve, so do the forms of “security issues.” (15:06–16:49)
- Core Developer Security Hygiene:
- Understanding Code Behavior: “Really know and understand what your code is doing.” (17:18–18:39)
- Never Trust Input: Timeless mantra—a simple parameter or file upload can be attack vectors. (18:41)
- Don’t Leak Secrets: Avoid hardcoding passwords, tokens, or sensitive config—attackers scan public repos for these. (19:53–20:28)
- “They crawl the public GitHub repositories, right, and steal those secrets and try to see if they're still valid even if you delete your code.” — Johannes Das [20:09]
6. Advanced Security Challenges
- Complex Features: Cryptography, authentication logic, privileges, password resets—don’t reinvent, use vetted libraries and frameworks. Lean on security teams for these areas. (21:42)
- Supply Chain Risks: Dependency poisoning—malicious updates in npm, pip, etc.—is increasingly common and hard to defend without tooling. (23:19)
- “You cannot not use dependencies… the only thing what you can do here is to have tools in place.” — Johannes Das [23:30]
7. Security Tools & Automation
- Software Composition Analysis (SCA): Monitors dependency manifests against CVE (Common Vulnerabilities and Exposures) databases. Tools, not humans, should keep up—there are too many new CVEs daily. (24:31–27:59)
- “There are over 200,000 CVEs and every day… like 50 new CVEs coming out… not a good use of your time… use a tool for this.” — Johannes Das [26:58]
- Static Application Security Testing (SAST): Analyzes code structure and data flows to find issues without execution (symbolic execution, taint analysis, etc.). Best when tuned for developer usage (low noise). (37:29–40:28)
- “Your code is transformed into a big graph model... then you try to figure out what are all the combinations where variable assignments… passed on with data assignments through functions…” — Johannes Das [39:09]
- Linters, Secret Detection, Infrastructure as Code (IaC) Analysis: Essential layers for security hygiene. (40:38)
- Dynamic Tools (DAST, Fuzzing): Useful for pen testing and finding runtime issues, but less developer-friendly due to feedback latency. (42:53–44:42)
8. Impact of AI in Coding and Security
- AI as Code Generator: AI increases the pace of code creation, but verification—not code writing—is now the bottleneck. (54:28–55:08)
- “You produce just code much more faster and writing code is not the challenge anymore. The new bottleneck is how are you verifying all that code?” — Johannes Das [54:33]
- AI as Reviewer: AI-powered security review tools are promising for security teams but are not yet systematic or deterministic enough for team-wide adoption as developer tools—too much variance between runs. (44:42–47:27)
- “AI is non-deterministic… as a development organization, you need to have a quality gate that’s consistent across your team.” — Johannes Das [46:21]
- AI-generated Code Issues: AI tends toward verbose, low-quality output, which increases maintainability and (eventually) security risks. Training models on high-quality, secure code reduces “bad” output. (48:02–49:11; 55:36–56:22)
- New Threats—Prompt Injection: In LLM-based systems, manipulating natural language inputs (“prompt injection”) is a modern version of code injection. (53:43–54:19)
- “Prompt injection is kind of like the new code injection. The human language is the new code.” — Johannes Das [54:04]
- AI and Dependency Confusion: LLMs may hallucinate dependencies—“AI proposes to use a library that doesn’t exist,” possibly leading to malicious package usage. (56:40–58:20)
9. Code Quality = Security
- Direct Relationship: Poor code structure (spaghetti code, unreadable blocks, lack of tests) makes it harder to spot and fix vulnerabilities, extending the “attacker window.” (32:03–33:23)
- “Quality suddenly becomes a security issue in the sense that the attacker window stays open longer.” — Johannes Das [33:07]
- Lines of Code as Risk Factor: Every ~1,000 lines of code contains one security issue, per Sonar’s data from 8B lines scanned. More code = more liability. (30:54–31:15; 49:11)
- “Only 3% of developers said they trust their AI generated code. And I think that's very reasonable.” — Johannes Das [50:53]
10. Misconceptions and Industry Fallacies
- “Buying” Security Doesn’t Work: Security isn’t just a product you can buy; integrating security into dev practice and culture is essential. (58:20–60:45)
- “Often... a mistake here is to look at security as a product and not as something that you are building into the process of development.” — Johannes Das [59:17]
- No Perfect Security: Even the best, most widely-used open-source projects have vulnerabilities; software complexity means “something” is always exploitable if you look hard enough. (61:48)
11. What Makes “Good Enough” Security?
- Foundational Steps:
- Use automated tools (static/dynamic analysis, SCA).
- Regular initial assessments by professionals or tools.
- Ongoing diligence: fix the most critical, don’t add more, avoid technical debt. (63:21–65:03)
- “With software the challenge is... you're adding new windows and doors every day... you need some automation for that.” — Johannes Das [63:37]
- Continuous Process: Security is “never-ending.” Keeping up with top vulnerability lists (OWASP Top 10) and new attack types (e.g., LLM prompt injection) is essential.
12. Programming Language Security
- Best Choices Today: Newer languages learn from the past (Go highly recommended, Java is solid for enterprises). Language evolution matters. (65:48–66:18)
- “I think the newer languages are more secure, like Go is a good example... also other languages are evolving... Java... quite secure to use.” — Johannes Das [65:48]
Notable Quotes & Memorable Moments
-
On Security Ownership:
“Developers are the only ones who can fix security issues. And so I think they should own all those code security issues.” — Johannes Das [06:36] -
On Overwhelming Security Noise:
“If you drive a car and you have a security guy...yell at you at every single thing that could go wrong...that gets super painful and annoying.” — Johannes Das [14:00] -
On Secrets and Supply Chain:
“They crawl public GitHub repositories, right, and steal those secrets and try to see if they're still valid even if you delete your code.” — Johannes Das [20:09] -
On Security Tools:
“There are over 200,000 CVEs...like 50 new CVEs coming out...not a good use of your time...use a tool for this.” — Johannes Das [26:58] -
On AI’s Double-Edged Sword:
“You produce code much more faster...the new bottleneck is how are you verifying all that code?” — Johannes Das [54:33] -
On AI and Prompt Injection:
“Prompt injection is kind of like the new code injection. The human language is the new code.” — Johannes Das [54:04]
Highlighted Timestamps
| Segment | Timestamps | |-----------------------------------------------|------------------| | Johannes’s security background & CTFs | 01:32–02:30 | | Penetration testing explained | 02:32–05:23 | | Developers VS security teams | 06:27–07:29 | | Security team role analogy | 09:31–10:17 | | How code security ownership shifted | 11:10–11:44 | | Defining code security / vulnerabilities | 15:06–16:49 | | Core security basics for devs | 17:18–20:28 | | Security automation and SCA tools | 23:19–27:59 | | Types of security tooling and trade-offs | 37:29–44:42 | | AI in code generation and reviews | 44:42–47:27 | | Prompt injection & AI-specific issues | 53:43–54:19 | | Good enough security advice | 63:21–65:03 | | Most secure programming languages | 65:48–66:18 |
Conclusion
Code security is no longer just a specialized responsibility—it’s a shared cultural and practical imperative for software engineers. Leveraging modern automated tools is a must, but human understanding and diligence are irreplaceable. As code is written (by humans or AI) at an ever-faster cadence, practical security means not aiming for perfection, but for continuous improvement, built into the workflow—just as essential as writing features or running tests. The attack landscape is dynamic, so security thinking must evolve, too.
For further reading and resources, see the Pragmatic Engineer Deep Dives.
