Skip to content

Commit 2613b8a

Browse files
Initial secure coding examples project
0 parents  commit 2613b8a

27 files changed

Lines changed: 746 additions & 0 deletions

Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
2+
WORKDIR /src
3+
4+
COPY . .
5+
RUN dotnet restore
6+
RUN dotnet publish src/SecureCodingExamples.Api/SecureCodingExamples.Api.csproj -c Release -o /app/publish
7+
8+
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
9+
WORKDIR /app
10+
COPY --from=build /app/publish .
11+
12+
EXPOSE 8080
13+
ENTRYPOINT ["dotnet", "SecureCodingExamples.Api.dll"]

README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# secure-coding-examples-dotnet
2+
3+
A .NET 10 secure coding portfolio project demonstrating common enterprise AppSec mistakes and safer implementation patterns.
4+
5+
## Purpose
6+
7+
This repository supports a cybersecurity transition profile focused on:
8+
9+
- secure engineering
10+
- Application Security
11+
- OWASP Top 10
12+
- OWASP API Top 10
13+
- secure SDLC
14+
- regulated-system thinking
15+
- enterprise .NET security
16+
17+
## Safety Note
18+
19+
The intentionally insecure examples are educational and isolated. They demonstrate anti-patterns so the secure version can be compared clearly. Do not reuse insecure examples in production.
20+
21+
## What This Project Demonstrates
22+
23+
- input validation
24+
- SQL injection prevention
25+
- secure authentication patterns
26+
- secure password hashing
27+
- secure logging
28+
- safe error handling
29+
- mass assignment prevention
30+
- secure file upload validation
31+
- dependency and CI security awareness
32+
33+
## Tech Stack
34+
35+
- .NET 10
36+
- ASP.NET Core 10 Web API
37+
- SQLite
38+
- Dapper
39+
- FluentValidation
40+
- BCrypt.Net
41+
- xUnit
42+
- GitHub Actions
43+
- Docker
44+
45+
## Run Locally
46+
47+
```bash
48+
dotnet restore
49+
dotnet build
50+
dotnet test
51+
dotnet run --project src/SecureCodingExamples.Api
52+
```
53+
54+
Swagger:
55+
56+
```text
57+
https://localhost:5001/swagger
58+
```
59+
60+
## Portfolio Positioning
61+
62+
This project shows security reasoning from a software engineering perspective: identifying risky implementation patterns and applying secure coding practices in enterprise .NET systems.

SecureCodingExamples.sln

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio Version 17
3+
VisualStudioVersion = 17.0.31903.59
4+
MinimumVisualStudioVersion = 10.0.40219.1
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecureCodingExamples.Api", "src\SecureCodingExamples.Api\SecureCodingExamples.Api.csproj", "{11111111-1111-1111-1111-111111111111}"
6+
EndProject
7+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecureCodingExamples.Tests", "tests\SecureCodingExamples.Tests\SecureCodingExamples.Tests.csproj", "{22222222-2222-2222-2222-222222222222}"
8+
EndProject
9+
Global
10+
EndGlobal

docs/OWASP_MAPPING.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# OWASP Mapping
2+
3+
## OWASP Top 10
4+
5+
| Area | Example |
6+
|---|---|
7+
| A01 Broken Access Control | Role and mass-assignment examples |
8+
| A02 Cryptographic Failures | Password hashing examples |
9+
| A03 Injection | SQL injection vulnerable vs secure examples |
10+
| A04 Insecure Design | Threat-aware notes and mitigations |
11+
| A05 Security Misconfiguration | Secure headers and safe defaults |
12+
| A07 Identification and Authentication Failures | Password verification patterns |
13+
| A09 Security Logging and Monitoring Failures | Audit-style logging examples |
14+
15+
## OWASP API Top 10
16+
17+
| Area | Example |
18+
|---|---|
19+
| Broken Object Property Level Authorization | DTO allow-listing |
20+
| Broken Authentication | Password handling examples |
21+
| Unrestricted Resource Consumption | File upload size validation |
22+
| Security Misconfiguration | Secure headers |

docs/SECURE_CODING_NOTES.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Secure Coding Notes
2+
3+
## Core Principles
4+
5+
- validate input at boundaries
6+
- never trust client-supplied identifiers or roles
7+
- use parameterized queries
8+
- avoid leaking stack traces
9+
- do not log secrets, tokens, passwords, or sensitive medical data
10+
- use DTOs instead of binding directly to domain entities
11+
- use least privilege
12+
- make security controls visible in code and documentation
13+
14+
## AppSec Review Questions
15+
16+
- What input can an attacker control?
17+
- What data is sensitive?
18+
- Where are authorization decisions made?
19+
- Can users access another user's data?
20+
- Are secrets exposed in logs or configuration?
21+
- Is error handling leaking implementation details?
22+
- Are dependencies scanned?

global.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"sdk": {
3+
"version": "10.0.100",
4+
"rollForward": "latestFeature"
5+
}
6+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using SecureCodingExamples.Api.Services;
3+
4+
namespace SecureCodingExamples.Api.Controllers;
5+
6+
[ApiController]
7+
[Route("api/examples/file-upload")]
8+
public class FileUploadExamplesController : ControllerBase
9+
{
10+
private readonly FileUploadSecurityService _service;
11+
12+
public FileUploadExamplesController(FileUploadSecurityService service)
13+
{
14+
_service = service;
15+
}
16+
17+
[HttpPost("validate")]
18+
public IActionResult ValidateUpload(IFormFile file)
19+
{
20+
if (!_service.IsAllowedFile(file))
21+
{
22+
return BadRequest(new
23+
{
24+
error = "File type or size not allowed."
25+
});
26+
}
27+
28+
return Ok(new
29+
{
30+
accepted = true,
31+
safeStorageName = _service.CreateSafeStorageName(file)
32+
});
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using SecureCodingExamples.Api.Services;
3+
4+
namespace SecureCodingExamples.Api.Controllers;
5+
6+
[ApiController]
7+
[Route("api/examples/injection")]
8+
public class InjectionExamplesController : ControllerBase
9+
{
10+
private readonly SqlInjectionExampleService _service;
11+
12+
public InjectionExamplesController(SqlInjectionExampleService service)
13+
{
14+
_service = service;
15+
}
16+
17+
[HttpGet("insecure-search")]
18+
public async Task<IActionResult> InsecureSearch([FromQuery] string email)
19+
{
20+
var users = await _service.InsecureSearchByEmailAsync(email);
21+
return Ok(new
22+
{
23+
warning = "Educational anti-pattern: vulnerable query construction.",
24+
users
25+
});
26+
}
27+
28+
[HttpGet("secure-search")]
29+
public async Task<IActionResult> SecureSearch([FromQuery] string email)
30+
{
31+
var users = await _service.SecureSearchByEmailAsync(email);
32+
return Ok(users);
33+
}
34+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using SecureCodingExamples.Api.Dtos;
3+
using SecureCodingExamples.Api.Services;
4+
5+
namespace SecureCodingExamples.Api.Controllers;
6+
7+
[ApiController]
8+
[Route("api/examples/mass-assignment")]
9+
public class MassAssignmentExamplesController : ControllerBase
10+
{
11+
private readonly MassAssignmentService _service;
12+
13+
public MassAssignmentExamplesController(MassAssignmentService service)
14+
{
15+
_service = service;
16+
}
17+
18+
[HttpPost("insecure-create-user")]
19+
public async Task<IActionResult> InsecureCreateUser(InsecureCreateUserRequest request)
20+
{
21+
var id = await _service.InsecureCreateUserAsync(request);
22+
23+
return Ok(new
24+
{
25+
warning = "Educational anti-pattern: client can control Role.",
26+
id
27+
});
28+
}
29+
30+
[HttpPost("secure-create-user")]
31+
public async Task<IActionResult> SecureCreateUser(CreateUserRequest request)
32+
{
33+
var id = await _service.SecureCreateUserAsync(request);
34+
35+
return Ok(new
36+
{
37+
id,
38+
roleAssignedByServer = "User"
39+
});
40+
}
41+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using SecureCodingExamples.Api.Dtos;
3+
using SecureCodingExamples.Api.Services;
4+
5+
namespace SecureCodingExamples.Api.Controllers;
6+
7+
[ApiController]
8+
[Route("api/examples/passwords")]
9+
public class PasswordExamplesController : ControllerBase
10+
{
11+
private readonly PasswordSecurityService _service;
12+
13+
public PasswordExamplesController(PasswordSecurityService service)
14+
{
15+
_service = service;
16+
}
17+
18+
[HttpPost("secure-login-check")]
19+
public async Task<IActionResult> SecureLoginCheck(LoginRequest request)
20+
{
21+
var isValid = await _service.SecureVerifyPasswordAsync(request);
22+
23+
return Ok(new
24+
{
25+
authenticated = isValid,
26+
note = "Uses BCrypt verification and does not expose password hashes."
27+
});
28+
}
29+
}

0 commit comments

Comments
 (0)