Developer security training: curriculum and resources
Developers write the code that attackers exploit. Every SQL injection, every XSS vulnerability, every authentication bypass exists because a developer wrote code that way. This isn't blame — it's reality. And the solution isn't security teams reviewing every line of code. It's developers who understand security and build it in from the start.
Security-aware developers don't just avoid vulnerabilities. They think like attackers. They question assumptions. They ask "what could go wrong?" before shipping. They build defense in depth, not security as an afterthought.
This article provides a comprehensive security training curriculum for developers: what topics to cover, learning resources for each, and structured learning paths from junior to senior level.
This is Part 1 of the developer security training series:
- Curriculum and resources (this article) — what to teach
- Assessment and competency mapping — how to evaluate skills
- Implementation guide — how to roll out the program
Why developer security training matters
The economics are clear: fixing a vulnerability in development costs 6x less than fixing it in production. Finding it during design costs 15x less than post-release. Developer security knowledge is the most cost-effective security investment you can make.
Most vulnerabilities are preventable. The OWASP Top 10 hasn't changed dramatically in 20 years. SQL injection, XSS, broken access control — we know these vulnerabilities exist. We know how to prevent them. Yet they keep appearing in new code because developers aren't taught to avoid them.
Security teams can't scale. Even if you have security specialists, they can't review every commit. The ratio of developers to security engineers is typically 100:1 or worse. Developers must be the first line of defense.
Shift-left requires developer knowledge. DevSecOps means integrating security into development. But developers can't fix SAST findings they don't understand. They can't threat model features they're building without security knowledge.
It's a career differentiator. Developers with security skills are in high demand. Security knowledge increases earning potential and opens paths to specialized roles (Application Security, Security Engineering).
Security competency framework
Before training developers, define what "security competency" means for your organization. Here's a framework:
Competency levels
| Level | Name | Description | Expected of |
|---|---|---|---|
| L1 | Aware | Understands basic security concepts, recognizes common vulnerabilities | All developers |
| L2 | Practitioner | Writes secure code consistently, can review others' code for security | Senior developers |
| L3 | Expert | Designs secure systems, mentors others, leads security initiatives | Tech leads, architects |
| L4 | Champion | Drives security culture, represents team in security discussions | Security Champions |
Competency areas
| Area | L1: Aware | L2: Practitioner | L3: Expert |
|---|---|---|---|
| Secure coding | Knows OWASP Top 10 | Prevents vulnerabilities in own code | Reviews others' code, creates patterns |
| Authentication & authorization | Understands concepts | Implements correctly | Designs auth systems |
| Data protection | Knows classification | Handles data securely | Designs data protection strategies |
| Threat modeling | Understands purpose | Participates in sessions | Leads threat modeling |
| Security testing | Runs provided tools | Writes security tests | Creates testing strategies |
| Incident response | Reports issues | Investigates and fixes | Leads incident response |
| Dependencies | Updates when told | Monitors and manages | Creates dependency policies |
Role-based requirements
| Role | Minimum level | Focus areas |
|---|---|---|
| Junior Developer | L1 | Secure coding basics, OWASP Top 10 |
| Mid-Level Developer | L1-L2 | Secure coding, basic security testing |
| Senior Developer | L2 | All areas, code review, mentoring |
| Tech Lead | L2-L3 | Architecture, threat modeling, team practices |
| QA Engineer | L1-L2 | Security testing, vulnerability verification |
| DevOps Engineer | L2 | Infrastructure security, CI/CD security |
| Security Champion | L3-L4 | All areas, cultural leadership |
Core curriculum for developers
1: Security fundamentals
Duration: 2-4 hours
Target: All developers (L1)
Topics:
- CIA triad (Confidentiality, Integrity, Availability)
- Defense in depth
- Least privilege principle
- Attack surface concept
- Security vs. convenience tradeoffs
- Threat landscape for web applications
Learning objectives:
- Explain why security matters for developers
- Identify common attack vectors
- Understand basic security terminology
- Recognize when to ask for security help
Resources:
| Resource | Type | Cost | Link |
|---|---|---|---|
| OWASP Web Security Testing Guide | Guide | Free | owasp.org/www-project-web-security-testing-guide |
| PortSwigger Web Security Academy | Interactive course | Free | portswigger.net/web-security |
| Hack The Box Academy | Hands-on labs | Free tier | academy.hackthebox.com |
| TryHackMe | Beginner-friendly labs | Free tier | tryhackme.com |
2: OWASP Top 10 deep dive
Duration: 4-8 hours
Target: All developers (L1-L2)
The OWASP Top 10 represents the most critical web application security risks. Every developer should understand these vulnerabilities intimately.
OWASP Top 10 (2021):
| # | Vulnerability | What it is | Prevention |
|---|---|---|---|
| A01 | Broken Access Control | Users can access unauthorized resources | Check authorization on every request |
| A02 | Cryptographic Failures | Sensitive data exposed via weak crypto | Use strong encryption, proper key management |
| A03 | Injection | Untrusted data executed as code | Parameterized queries, input validation |
| A04 | Insecure Design | Flaws in architecture/design | Threat modeling, secure design patterns |
| A05 | Security Misconfiguration | Default configs, unnecessary features | Hardening, minimal permissions |
| A06 | Vulnerable Components | Using components with known vulnerabilities | SCA scanning, updates |
| A07 | Auth Failures | Broken authentication mechanisms | MFA, secure session management |
| A08 | Software & Data Integrity Failures | Trusting untrusted sources | Verify signatures, integrity checks |
| A09 | Security Logging Failures | Insufficient logging for detection | Comprehensive security logging |
| A10 | SSRF | Server makes requests to attacker-controlled destinations | Validate and sanitize URLs |
Hands-on practice:
| Platform | Description | Link |
|---|---|---|
| OWASP WebGoat | Deliberately insecure app for learning | github.com/WebGoat/WebGoat |
| OWASP Juice Shop | Modern vulnerable app | owasp.org/www-project-juice-shop |
| DVWA | Damn Vulnerable Web Application | github.com/digininja/DVWA |
| HackTheBox | Vulnerable machines | hackthebox.com |
| PentesterLab | Guided exercises | pentesterlab.com |
3: Secure coding by language
Duration: 4-6 hours per language
Target: Developers (L1-L2)
Security practices differ by language and framework. Provide language-specific training for your stack.
JavaScript/TypeScript
Key areas:
- XSS prevention (output encoding, CSP)
- Prototype pollution
- npm dependency security
- Secure authentication with JWTs
- Server-side request validation
- Safe JSON parsing
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP Node.js Security Cheat Sheet | Guide | cheatsheetseries.owasp.org |
| Node.js Security Best Practices | Guide | nodejs.org/en/docs/guides/security |
| Snyk JavaScript Security | Blog/Learning | snyk.io/learn/javascript-security |
| Secure Coding in Node.js | Course | pluralsight.com |
Example: XSS prevention
// BAD: Direct HTML insertion
element.innerHTML = userInput; // XSS vulnerability
// GOOD: Text content (auto-escapes)
element.textContent = userInput;
// GOOD: DOMPurify for rich content
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);
// GOOD: Template literals with encoding
const safe = encodeHTML(userInput);
element.innerHTML = `<div>${safe}</div>`;
Python
Key areas:
- SQL injection with ORMs
- Command injection (subprocess)
- Pickle deserialization
- SSTI (Server-Side Template Injection)
- Path traversal
- Secure password hashing
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP Python Security | Guide | cheatsheetseries.owasp.org |
| Bandit | SAST tool | bandit.readthedocs.io |
| Real Python Security | Tutorials | realpython.com/tutorials/security |
| Python Security Best Practices | Course | pluralsight.com |
Example: SQL injection prevention
# BAD: String formatting (SQL injection)
query = f"SELECT * FROM users WHERE id = {user_id}"
cursor.execute(query)
# GOOD: Parameterized queries
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
# GOOD: ORM usage (SQLAlchemy)
user = session.query(User).filter(User.id == user_id).first()
# GOOD: Django ORM
user = User.objects.get(id=user_id)
Java
Key areas:
- SQL injection (JDBC, JPA)
- XML External Entity (XXE)
- Deserialization vulnerabilities
- Spring Security configuration
- Secure logging
- Cryptography with JCA
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP Java Security | Guide | cheatsheetseries.owasp.org |
| Spring Security Reference | Docs | docs.spring.io/spring-security |
| Find Security Bugs | SAST tool | find-sec-bugs.github.io |
| Secure Coding Guidelines for Java | Oracle Guide | oracle.com |
Go
Key areas:
- Input validation
- SQL injection with database/sql
- Path traversal
- Race conditions
- Secure HTTP client configuration
- Cryptography with crypto package
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP Go Security | Guide | cheatsheetseries.owasp.org |
| Secure Go | Book | github.com/OWASP/Go-SCP |
| gosec | SAST tool | github.com/securego/gosec |
PHP
Key areas:
- SQL injection (PDO, mysqli)
- XSS prevention
- File upload vulnerabilities
- Session security
- include/require vulnerabilities
- Password hashing with password_hash()
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP PHP Security | Guide | cheatsheetseries.owasp.org |
| PHP: The Right Way - Security | Guide | phptherightway.com/#security |
| Psalm | Static analyzer | psalm.dev |
C# / .NET
Key areas:
- SQL injection with Entity Framework
- XSS in Razor views
- Antiforgery tokens (CSRF)
- Secure deserialization
- Cryptography with .NET APIs
- Authentication with ASP.NET Identity
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP .NET Security | Guide | cheatsheetseries.owasp.org |
| ASP.NET Core Security | Docs | docs.microsoft.com/en-us/aspnet/core/security |
| Security Code Scan | SAST tool | security-code-scan.github.io |
4: Authentication and authorization
Duration: 4-6 hours
Target: Developers (L2)
Topics:
- Authentication vs. authorization
- Session management
- JWT best practices and pitfalls
- OAuth 2.0 and OpenID Connect
- Password storage (bcrypt, Argon2)
- MFA implementation
- API authentication patterns
- RBAC and ABAC
Common mistakes to teach:
// BAD: JWT in localStorage (XSS can steal it)
localStorage.setItem('token', jwt);
// BETTER: HttpOnly cookie (not accessible via JavaScript)
// Set via response header:
// Set-Cookie: token=jwt; HttpOnly; Secure; SameSite=Strict
// BAD: Checking JWT signature but not expiration
const decoded = jwt.verify(token, secret);
// Token could be expired!
// GOOD: Verify all claims
const decoded = jwt.verify(token, secret, {
algorithms: ['HS256'],
maxAge: '1h',
issuer: 'your-app'
});
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP Authentication Cheat Sheet | Guide | cheatsheetseries.owasp.org |
| OAuth 2.0 Simplified | Book | oauth.com |
| Auth0 Blog | Articles | auth0.com/blog |
| JWT.io | Learning | jwt.io/introduction |
5: Security testing for developers
Duration: 4-6 hours
Target: Developers and QA (L2)
Developers should write security tests, not just rely on security teams.
Types of security testing:
| Type | What it tests | When to use | Tools |
|---|---|---|---|
| Unit tests for security | Individual security functions | Every commit | Jest, pytest, JUnit |
| Integration security tests | Auth flows, access control | Every PR | Supertest, requests |
| SAST | Source code patterns | CI/CD | Semgrep, CodeQL, Bandit |
| DAST | Running application | Staging | OWASP ZAP, Nuclei |
| Dependency scanning | Known CVEs in libraries | Every build | Snyk, Dependabot |
| Fuzz testing | Edge cases, crashes | Periodic | AFL, libFuzzer |
Writing security tests:
// Authentication tests
describe('Authentication', () => {
test('should reject invalid credentials', async () => {
const res = await request(app)
.post('/api/login')
.send({ username: 'user', password: 'wrong' });
expect(res.status).toBe(401);
});
test('should not leak user existence via timing', async () => {
const start1 = Date.now();
await request(app).post('/api/login').send({ username: 'exists', password: 'wrong' });
const time1 = Date.now() - start1;
const start2 = Date.now();
await request(app).post('/api/login').send({ username: 'nonexistent', password: 'wrong' });
const time2 = Date.now() - start2;
// Response times should be similar
expect(Math.abs(time1 - time2)).toBeLessThan(50);
});
});
// Authorization tests
describe('Authorization', () => {
test('should deny access to other users resources', async () => {
const user1Token = await login('user1', 'password1');
const res = await request(app)
.get('/api/users/user2/data')
.set('Authorization', `Bearer ${user1Token}`);
expect(res.status).toBe(403);
});
});
// Input validation tests
describe('Input Validation', () => {
test('should reject SQL injection attempts', async () => {
const res = await request(app)
.get('/api/users')
.query({ id: "1' OR '1'='1" });
expect(res.status).toBe(400);
});
test('should reject XSS in user input', async () => {
const res = await request(app)
.post('/api/comments')
.send({ text: '<script>alert("xss")</script>' });
// Either reject or sanitize
expect(res.body.text).not.toContain('<script>');
});
});
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP Testing Guide | Comprehensive guide | owasp.org/www-project-web-security-testing-guide |
| BDD Security | Framework | github.com/iriusrisk/bdd-security |
| OWASP ZAP | DAST tool | zaproxy.org |
| Nuclei | Template-based scanner | nuclei.projectdiscovery.io |
6: Threat modeling
Duration: 2-4 hours
Target: Senior developers, Tech leads (L2-L3)
Threat modeling identifies security issues during design, before code is written.
STRIDE model:
| Threat | Description | Example | Mitigation |
|---|---|---|---|
| Spoofing | Pretending to be someone else | Stolen credentials | Strong authentication, MFA |
| Tampering | Modifying data | Changing prices in cart | Integrity checks, signatures |
| Repudiation | Denying actions | "I didn't make that purchase" | Audit logging |
| Information Disclosure | Data exposure | Database dump | Encryption, access control |
| Denial of Service | Making system unavailable | DDoS attack | Rate limiting, scaling |
| Elevation of Privilege | Gaining unauthorized access | Admin access without being admin | Least privilege, RBAC |
Simple threat modeling process:
- What are we building? Draw a data flow diagram. Identify components, data stores, and trust boundaries.
- What can go wrong? Apply STRIDE to each component. Brainstorm attack scenarios.
- What are we going to do about it? Prioritize threats (likelihood × impact). Define mitigations. Create security requirements.
- Did we do a good job? Review model completeness. Verify mitigations are implemented. Update the model as the design changes.
Resources:
| Resource | Type | Link |
|---|---|---|
| OWASP Threat Modeling | Guide | owasp.org/www-community/Threat_Modeling |
| Microsoft Threat Modeling Tool | Tool | microsoft.com/en-us/securityengineering/sdl/threatmodeling |
| Threat Modeling: Designing for Security | Book | Adam Shostack |
| OWASP Threat Dragon | Open source tool | owasp.org/www-project-threat-dragon |
Security training for QA engineers
QA engineers are force multipliers for security. They already think about edge cases and breaking things — security testing is a natural extension.
Security testing curriculum for QA
| Module | Topics | Duration |
|---|---|---|
| Security testing basics | Vulnerability types, OWASP Top 10, testing mindset | 4 hours |
| Manual security testing | Burp Suite basics, Intercepting requests, testing auth | 8 hours |
| Automated security testing | OWASP ZAP, Nuclei, CI integration | 4 hours |
| API security testing | API vulnerabilities, Postman security tests, fuzzing | 4 hours |
| Reporting vulnerabilities | Writing good bug reports, severity assessment | 2 hours |
Tools for QA security testing
| Tool | Purpose | Learning curve | Link |
|---|---|---|---|
| Burp Suite Community | Web proxy, manual testing | Medium | portswigger.net/burp |
| OWASP ZAP | Web scanner, free alternative to Burp | Medium | zaproxy.org |
| Postman | API testing with security tests | Low | postman.com |
| Nuclei | Template-based scanning | Low | nuclei.projectdiscovery.io |
| Browser DevTools | Request inspection, cookie analysis | Low | Built-in |
QA security testing checklist
## QA Security Testing Checklist
### Authentication
- [ ] Test with invalid credentials
- [ ] Test account lockout after failed attempts
- [ ] Test password reset flow for account enumeration
- [ ] Test session timeout
- [ ] Test concurrent session handling
- [ ] Test remember me functionality
### Authorization
- [ ] Test accessing other users' data (IDOR)
- [ ] Test role-based access (can user access admin?)
- [ ] Test function-level access control
- [ ] Test after logout (can cached pages be accessed?)
### Input validation
- [ ] Test with SQL injection payloads
- [ ] Test with XSS payloads
- [ ] Test with special characters
- [ ] Test with very long inputs
- [ ] Test with empty/null inputs
- [ ] Test with unexpected data types
### Business logic
- [ ] Test race conditions (submit twice quickly)
- [ ] Test workflow bypass (skip steps)
- [ ] Test negative values (negative quantity, negative price)
- [ ] Test integer overflow
### Files
- [ ] Test uploading executable files
- [ ] Test uploading oversized files
- [ ] Test path traversal in filenames
- [ ] Test accessing files without authorization
### API specific
- [ ] Test with missing authentication
- [ ] Test with tampered tokens
- [ ] Test rate limiting
- [ ] Test for mass assignment
- [ ] Test for excessive data exposure
Burp Suite basics for QA
Setup: Configure proxy (127.0.0.1:8080), install Burp CA certificate in browser, browse the application — Burp captures all traffic.
Key tabs:
- Proxy → HTTP history — see all requests
- Repeater — modify and resend individual requests
- Intruder — automated payload testing
- Scanner — automated vulnerability scanning (Pro only)
Common tests: change user ID in URL (IDOR) · modify JSON body (authorization) · remove auth headers (auth requirements) · inject payloads (input validation)
Comprehensive learning paths
Junior developer path (0-2 years)
Months 1-3: Foundations
- Security fundamentals course
- OWASP Top 10 training
- Language-specific secure coding basics
- Assessment: Security quiz (pass 80%)
Months 4-6: Practical skills
- Complete PortSwigger Web Security Academy (basics)
- Practice on WebGoat
- Write first security unit tests
- Assessment: Find 3 vulnerabilities in test app
Months 7-12: Integration
- Apply secure coding in daily work
- Participate in security code reviews
- Join CTF event
- Assessment: Secure code review exercise
Target by end of year: L1 competency in all areas
Mid-level developer path (2-5 years)
Quarter 1:
- Advanced OWASP training
- Authentication and authorization deep dive
- Assessment: Intermediate security quiz
Quarter 2:
- Security testing with Burp Suite
- API security
- Assessment: Find vulnerabilities using Burp
Quarter 3:
- Threat modeling introduction
- Participate in threat model session
- Assessment: Lead threat model for small feature
Quarter 4:
- Mentor junior developer
- Contribute to security documentation
- Assessment: Code review with security focus
Target by end of year: L2 competency, ready for security champion role
Senior developer / Tech lead path
Focus areas:
- Architecture security
- Leading threat modeling sessions
- Security requirements for new projects
- Mentoring others
- Security incident response
Activities:
- Complete threat modeling course
- Lead 3+ threat modeling sessions
- Review security architecture for new projects
- Present at internal tech talk on security topic
- Participate in incident response exercise
Target: L3 competency, security champion or working with security team
Self-check questions
- What are the four levels in the security competency framework?
- Which OWASP Top 10 vulnerability involves executing untrusted data as code?
- Why is parameterized query safer than string interpolation for SQL?
- What's the difference between SAST and DAST?
- What does STRIDE stand for?
- Why should QA engineers learn security testing?
Links and resources
Courses and training
| Resource | Type | Cost | Link |
|---|---|---|---|
| PortSwigger Web Security Academy | Interactive | Free | portswigger.net/web-security |
| OWASP WebGoat | Hands-on | Free | owasp.org/www-project-webgoat |
| Hack The Box Academy | Labs | Free tier | academy.hackthebox.com |
| TryHackMe | Beginner labs | Free tier | tryhackme.com |
| PentesterLab | Exercises | $20/month | pentesterlab.com |
| SANS Secure Coding | Certification | Paid | sans.org |
Cheat sheets and guides
- OWASP Cheat Sheet Series — Comprehensive secure coding guides
- OWASP Testing Guide — Security testing methodology
- CWE Top 25 — Most dangerous software weaknesses
SAST tools by language
| Language | Tool | Link |
|---|---|---|
| Multi-language | Semgrep | semgrep.dev |
| Multi-language | CodeQL | codeql.github.com |
| Python | Bandit | bandit.readthedocs.io |
| JavaScript | ESLint security plugins | github.com/eslint-community/eslint-plugin-security |
| Java | Find Security Bugs | find-sec-bugs.github.io |
| Go | gosec | github.com/securego/gosec |
| C# | Security Code Scan | security-code-scan.github.io |
Vulnerable applications for practice
CTF platforms
Conclusion
A curriculum that doesn't map to what your developers actually build is wasted effort. Start with what you know — your stack, your vulnerabilities, your incidents — and build from there.
The goal isn't to turn every developer into a security expert. It's to make them fluent enough that they don't introduce the same categories of bugs twice.
What's next
Next: assessment and competency mapping — how to evaluate where your developers are before you start training.