Secure Coding Labs in 2026
53 secure coding labs in various language
In this article we make a collection of 53 secure coding labs covering the most common vulnerability classes developers run into today. Each lab walks through a real vulnerable code pattern, explains what went wrong at the source level, and shows the fix with working code.
The labs span SQL injection, XSS, SSRF, broken authentication, insecure deserialization, vulnerable dependencies, API misconfigurations, mobile security issues, and memory safety bugs in C++. Languages covered include C#, Java, Python, PHP, Go, JavaScript, TypeScript, Ruby, Kotlin, Swift, and C++.
This is not theory. Every example comes from an actual lab environment with exploitable code. We break down the root cause, show the vulnerable snippet, and provide the corrected version. Use it as a training reference, onboarding material, or just a quick lookup when you need to remind yourself why string concatenation in SQL queries is still a terrible idea.
SQL Injection - .NET (Parameterize All The Things)
Lab Reference
Repository: securec0ding/dotnet-injection-parameterize-all-the-things
Language: C#
OWASP Category: A03:2021 - Injection
Writeup
This lab presents a .NET web application with an employee search feature. The search endpoint takes user input and passes it directly into a raw SQL query without any sanitization or parameterization. An attacker can inject SQL statements through the search field to extract, modify, or delete database records.
Root Cause Analysis
The controller builds a SQL query using string concatenation with user-supplied input. The search parameter from the HTTP request is embedded directly into the SQL string. No input validation, escaping, or parameterized queries are used.
Vulnerable Code
[HttpPost]
public IActionResult Search(string search)
{
var employees = new List<Employee>();
using (var connection = new SqliteConnection("DataSource=database.sqlite"))
{
connection.Open();
var command = connection.CreateCommand();
// User input directly concatenated into SQL query
command.CommandText = "SELECT * FROM employee WHERE name LIKE '%" + search + "%'";
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
employees.Add(new Employee
{
Name = reader.GetString(1),
Email = reader.GetString(2),
Phone = reader.GetString(3),
Salary = reader.GetString(4)
});
}
}
}
return View("Index", employees);
}
Solution
Use parameterized queries. Bind user input as a parameter instead of concatenating it into the SQL string.
Fixed Code
[HttpPost]
public IActionResult Search(string search)
{
var employees = new List<Employee>();
using (var connection = new SqliteConnection("DataSource=database.sqlite"))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "SELECT * FROM employee WHERE name LIKE @search";
command.Parameters.AddWithValue("@search", "%" + search + "%");
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
employees.Add(new Employee
{
Name = reader.GetString(1),
Email = reader.GetString(2),
Phone = reader.GetString(3),
Salary = reader.GetString(4)
});
}
}
}
return View("Index", employees);
}
The @search parameter ensures the database engine treats the input as a literal value, not as part of the SQL syntax.
SQL Injection - Java Spring (Parameterize All The Things)
Lab Reference
Repository: securec0ding/java-injection-parameterize-all-the-things
Language: Java
OWASP Category: A03:2021 - Injection
Writeup
This lab features a Java Spring Boot application with an employee search function. The repository layer uses a native SQL query built through string concatenation. User input from the search form is inserted directly into the query, allowing an attacker to manipulate the SQL logic. Standard injection techniques apply -- extracting data from other tables, bypassing filters, or modifying records.
Root Cause Analysis
The Spring Data JPA repository defines a native query using string concatenation. The name parameter from the HTTP request is lowercased and concatenated directly into the SQL string inside the @Query annotation. This bypasses all of Spring’s built-in parameterization.
Vulnerable Code
@Query(value = "SELECT * FROM employee WHERE LOWER(name) LIKE '%" + name.toLowerCase() + "%'", nativeQuery = true)
List<Employee> getEmployeesByName(String name, Sort sort);
Solution
Use parameterized JPQL or named parameters with the @Param annotation. Let the ORM handle escaping. There is no need for raw SQL here.
Fixed Code
@Query(value = "SELECT e FROM Employee e WHERE LOWER(e.name) LIKE %:keyword%")
List<Employee> getEmployeesByName(@Param("keyword") String keyword, Sort sort);
The :keyword named parameter is bound safely by the JPA provider. The input is treated as a literal value, and the ORM generates the correct parameterized SQL underneath.
SQL Injection - PHP Laravel (Parameterize All The Things)
Lab Reference
Repository: securec0ding/php-injection-parameterize-all-the-things
Language: PHP
OWASP Category: A03:2021 - Injection



