- JWT-based authentication
- Password hashing (ASP.NET Core Identity)
- Role-based authorization
- Token expiration (configurable)
-
Strong JWT Secret: Min 32 bytes, random
{ "Jwt": { "Key": "CHANGE_THIS_TO_A_STRONG_RANDOM_SECRET_MIN_32_CHARS_LONG" } } -
Token Lifetime: Reduce to 15-60 minutes
{ "Jwt": { "ExpiryMinutes": 30 } } -
Refresh Tokens: Implement for long-lived sessions
-
Multi-Factor Authentication (MFA): Optional but recommended
-
Account Lockout: After N failed attempts
-
Password Policy:
- Min 12 characters
- Require uppercase, lowercase, number, symbol
- Password history (no reuse of last 5)
Add security headers to all responses:
// Program.cs
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Add("X-XSS-Protection", "1; mode=block");
context.Response.Headers.Add("Referrer-Policy", "no-referrer");
context.Response.Headers.Add("Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'");
context.Response.Headers.Add("Permissions-Policy",
"geolocation=(), microphone=(), camera=()");
// Remove server header
context.Response.Headers.Remove("Server");
await next();
});Restrict origins in production:
builder.Services.AddCors(options =>
{
options.AddPolicy("Production", policy =>
{
policy.WithOrigins(
"https://nexuscad.yourdomain.com",
"https://app.nexuscad.com")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});// Add AspNetCoreRateLimit package
builder.Services.AddMemoryCache();
builder.Services.Configure<IpRateLimitOptions>(options =>
{
options.GeneralRules = new List<RateLimitRule>
{
new RateLimitRule
{
Endpoint = "*",
Limit = 100,
Period = "1m"
},
new RateLimitRule
{
Endpoint = "*/api/auth/login",
Limit = 5,
Period = "1m"
}
};
});For service-to-service communication:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ApiKeyAttribute : Attribute, IAsyncAuthorizationFilter
{
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (!context.HttpContext.Request.Headers.TryGetValue("X-API-Key", out var apiKey))
{
context.Result = new UnauthorizedResult();
return;
}
var configuration = context.HttpContext.RequestServices
.GetRequiredService<IConfiguration>();
var validApiKey = configuration["ApiKeys:Worker"];
if (apiKey != validApiKey)
{
context.Result = new UnauthorizedResult();
}
}
}- Never commit connection strings with passwords
- Use environment variables or Azure Key Vault
- Encrypt connection strings in config files
- Least privilege: Database user should only have necessary permissions
{
"ConnectionStrings": {
"DefaultConnection": "Host=${DB_HOST};Database=${DB_NAME};Username=${DB_USER};Password=${DB_PASSWORD}"
}
}- Parameterized queries (EF Core does this automatically)
- Input validation on all user inputs
- Stored procedures for sensitive operations (optional)
PostgreSQL encryption:
-- Enable SSL
ALTER SYSTEM SET ssl = 'on';
-- Transparent Data Encryption (PostgreSQL 15+)
-- Or use disk-level encryption (LUKS, BitLocker)// Track sensitive operations
public class AuditEntry
{
public int Id { get; set; }
public string UserId { get; set; }
public string Action { get; set; }
public string Entity { get; set; }
public DateTime Timestamp { get; set; }
public string IpAddress { get; set; }
public string Changes { get; set; }
}# Use specific versions, not :latest
FROM mcr.microsoft.com/dotnet/aspnet:8.0.4-alpine AS runtime
# Run as non-root user
RUN addgroup -S nexuscad && adduser -S nexuscad -G nexuscad
USER nexuscad
# Read-only root filesystem
RUN chmod -R 755 /app && \
chown -R nexuscad:nexuscad /app
# Drop capabilities
# (Configured in docker-compose or Kubernetes)services:
api:
# ... existing config
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
tmpfs:
- /tmp
- /var/tmp# Use Docker secrets instead of environment variables
secrets:
db_password:
file: ./secrets/db_password.txt
jwt_key:
file: ./secrets/jwt_key.txt
services:
api:
secrets:
- db_password
- jwt_key
environment:
ConnectionStrings__Password: /run/secrets/db_password
Jwt__Key: /run/secrets/jwt_key# Scan for vulnerabilities
docker scan nexuscad-api:latest
# Or use Trivy
trivy image nexuscad-api:latest-
Content Security Policy (CSP)
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self' https://api.nexuscad.com; frame-ancestors 'none';";
-
Subresource Integrity (SRI) for CDN resources
<script src="https://cdn.example.com/library.js" integrity="sha384-..." crossorigin="anonymous"></script>
-
XSS Protection
- Sanitize all user inputs
- Use React's built-in escaping
- DOMPurify for rich text
-
CSRF Protection
- SameSite cookies
- Anti-forgery tokens
axios.defaults.xsrfCookieName = 'XSRF-TOKEN'; axios.defaults.xsrfHeaderName = 'X-XSRF-TOKEN';
-
Secure Storage
- Never store tokens in localStorage (use httpOnly cookies)
- Or use sessionStorage with auto-logout
// If using localStorage, clear on window close window.addEventListener('beforeunload', () => { sessionStorage.clear(); });
-
Force HTTPS redirect
server { listen 80; return 301 https://$host$request_uri; }
-
HSTS header
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
-
Secure cookies
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.SameSite = SameSiteMode.Strict;
-
Validate file types
var allowedExtensions = new[] { ".pdf", ".docx", ".xlsx" }; if (!allowedExtensions.Contains(Path.GetExtension(fileName))) throw new BadRequestException("Invalid file type");
-
Limit file size
builder.Services.Configure<FormOptions>(options => { options.MultipartBodyLengthLimit = 10 * 1024 * 1024; // 10 MB });
-
Scan for malware (ClamAV or Windows Defender)
var scanner = new ClamScanner(); var result = await scanner.ScanFileAsync(filePath); if (!result.IsClean) throw new SecurityException("Malware detected");
-
Store outside webroot
var uploadPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "NexusCad", "Generated");
-
Serve with X-Content-Type-Options: nosniff
- β Authentication attempts (success/failure)
- β Authorization failures
- β API errors and exceptions
- β Sensitive operations (create/delete)
- β Configuration changes
- β Performance metrics
- β Passwords (plaintext or hashed)
- β JWT tokens
- β API keys
- β Credit card numbers
- β Personal identifiable information (PII)
// Seq queries for security events
// Failed login attempts
RequestPath = '/api/auth/login' AND StatusCode >= 400
// Unauthorized access
StatusCode = 401 OR StatusCode = 403
// SQL injection attempts
Exception LIKE '%SQL%' OR RequestPath LIKE '%SELECT%'# Allow only necessary ports
ufw allow 443/tcp # HTTPS
ufw allow 5432/tcp # PostgreSQL (internal only)
ufw deny 5140/tcp # API should be behind reverse proxy
ufw enable# Hide backend details
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
# Limit request size
client_max_body_size 10M;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffer overflow protection
client_body_buffer_size 1K;
client_header_buffer_size 1k;
large_client_header_buffers 2 1k;# TLS 1.2 and 1.3 only
ssl_protocols TLSv1.2 TLSv1.3;
# Strong ciphers
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# Certificate
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;-
Regular updates
dotnet list package --outdated dotnet add package <PackageName>
-
Vulnerability scanning
dotnet list package --vulnerable
-
Audit dependencies
# Use GitHub Dependabot or Snyk
# Audit
npm audit
# Fix
npm audit fix
# Check outdated
npm outdated-
Detect
- Monitor logs for anomalies
- Alert on suspicious patterns
- User reports
-
Contain
- Isolate affected systems
- Block malicious IPs
- Revoke compromised tokens
-
Investigate
- Review logs
- Identify attack vector
- Assess impact
-
Remediate
- Patch vulnerabilities
- Reset compromised credentials
- Update security rules
-
Document
- Post-mortem report
- Lessons learned
- Update procedures
- Security team: security@nexuscad.com
- On-call engineer: +1-XXX-XXX-XXXX
- Incident response: [Internal wiki link]
- Data minimization: Only collect necessary data
- Right to access: API endpoint for user data export
- Right to deletion: User account deletion
- Data portability: Export in standard format
- Consent management: Explicit opt-in
- Privacy policy: Published and accessible
- Encrypt sensitive data at rest
- Encrypt data in transit (TLS)
- Regular backups (encrypted)
- Secure backup storage
- Retention policies
# OWASP ZAP
zap-cli quick-scan http://localhost:5140
# SQLMap (SQL injection)
sqlmap -u "http://localhost:5140/api/projects?id=1" --batch
# Nikto (web server)
nikto -h http://localhost:5140- Authentication bypass attempts
- Authorization escalation
- Input validation (XSS, SQL injection)
- Session management
- File upload vulnerabilities
- CSRF attacks
- Security audit completed
- All secrets rotated
- Dependency vulnerabilities fixed
- Penetration testing done
- SSL/TLS certificates valid
- Backup strategy tested
- Incident response plan ready
- Monitor logs for anomalies
- Verify security headers
- Test authentication
- Verify HTTPS redirect
- Check firewall rules
- Review access logs
- OWASP Top 10
- OWASP Cheat Sheets
- Microsoft Security Best Practices
- Docker Security
- CIS Docker Benchmark
Last Updated: 15 Mayo 2026
Review Schedule: Quarterly