Files
cv-site/tests/security/README.md
T
juanatsap 64cb990860 fix: Improve plain text CV output with dedicated template
- Replace html2text library conversion with dedicated text template
- Create clean, well-formatted cv-text.txt template
- Remove k3a/html2text dependency
- Fix lint warnings in security tests (ineffectual assignments)
- Output now shows only CV content without UI/menu elements
2025-11-30 14:13:34 +00:00

313 lines
9.1 KiB
Markdown

# Contact Form Security Test Suite
Comprehensive security testing for the contact form API endpoint `/api/contact`.
## Test Files
### 1. `middleware_security_test.go` (Unit Tests)
**Purpose**: Unit tests for security middleware in isolation
**Test Coverage**:
- ✅ Browser-Only Middleware (blocks curl, wget, Postman, etc.)
- ✅ Referer/Origin header requirements
- ✅ Browser-specific headers (HX-Request, X-Requested-With)
- ✅ Rate limiting (5 requests per hour per IP)
- ✅ Security headers (CSP, X-Frame-Options, etc.)
- ✅ Attack scenario simulations
**Run Tests**:
```bash
# Run all tests
go test -v ./tests/security/middleware_security_test.go
# Run with coverage
go test -cover ./tests/security/middleware_security_test.go
# Run benchmarks
go test -bench=. -benchmem ./tests/security/middleware_security_test.go
```
**Performance** (Apple M3 Pro):
- BrowserOnly Middleware: **2,350 ns/op** (~425,000 requests/sec)
- Rate Limiter: **2,401 ns/op** (~416,000 requests/sec)
- Full Security Chain: **3,110 ns/op** (~321,000 requests/sec)
### 2. `contact_security_test.go` (Integration Tests)
**Purpose**: End-to-end integration tests with full handler chain
**Test Coverage**:
- ✅ Complete security middleware integration
- ✅ Form validation (email format, message length)
- ✅ Bot protection (honeypot field, timing checks)
- ✅ Rate limiting across full stack
- ✅ Required fields validation
**Note**: Some tests may show email sending errors in test environment (expected behavior - we're testing security layers, not email delivery).
**Run Tests**:
```bash
go test -v ./tests/security/contact_security_test.go
```
### 3. `security_tests.sh` (Live Server Tests)
**Purpose**: Black-box testing against running server
**Test Coverage**:
- ✅ Real HTTP client blocking (curl, wget, Postman, Python)
- ✅ Header validation in production environment
- ✅ Email format validation
- ✅ Message length limits
- ✅ Honeypot bot detection
- ✅ Form submission timing
- ✅ Rate limiting enforcement
- ✅ Attack scenario testing
**Run Tests**:
```bash
# Start your server first
go run main.go
# In another terminal, run tests
./tests/security/security_tests.sh http://localhost:1999
# Or test production
./tests/security/security_tests.sh https://yourdomain.com
```
## Security Features Tested
### 1. Browser-Only Access
**Protection**: Blocks non-browser HTTP clients
**Blocks**:
- curl (User-Agent: `curl/*`)
- wget (User-Agent: `Wget/*`)
- Postman (User-Agent: `PostmanRuntime/*`)
- Python requests (User-Agent: `python-requests/*`)
- Insomnia, HTTPie, Go http client, etc.
**Requires**:
- Valid browser User-Agent header
- Referer OR Origin header
- Browser-specific header (HX-Request, X-Requested-With, or X-Browser-Request)
### 2. Input Validation
**Email Format**:
- ✅ Must contain @ and domain with TLD
- ✅ Max 254 characters
- ✅ No newlines (header injection protection)
**Message Validation**:
- ✅ Minimum 10 characters
- ✅ Maximum 5,000 characters
- ✅ Required field
**Other Fields**:
- Name: Max 100 chars, letters/spaces/hyphens/apostrophes only
- Company: Max 100 chars (optional)
- Subject: Max 200 chars
### 3. Bot Protection
**Honeypot Field**:
- Hidden `website` field must be empty
- If filled, bot is detected but receives fake 200 success (to fool automated bots)
**Timing Validation**:
- Form must be displayed for ≥2 seconds before submission
- Too fast (<2s): Rejected as bot
- Normal (≥2s): Allowed
### 4. Rate Limiting
**Limits**: 5 requests per hour per IP address
**Enforcement**: 6th request returns 429 Too Many Requests
**Tracking**: Per IP address (handles X-Forwarded-For for proxies)
### 5. Security Headers
All responses include:
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: SAMEORIGIN`
- `X-XSS-Protection: 1; mode=block`
- `Referrer-Policy: strict-origin-when-cross-origin`
- `Content-Security-Policy: ...` (comprehensive CSP)
- `Permissions-Policy: ...` (restrictive)
- `Strict-Transport-Security` (production only with HTTPS)
## Test Results Summary
### Unit Tests (`middleware_security_test.go`)
```
✓ TestBrowserOnlyMiddleware_BlocksHTTPClients (11 test cases)
✓ TestBrowserOnlyMiddleware_RequiresRefererOrOrigin (4 test cases)
✓ TestBrowserOnlyMiddleware_RequiresBrowserHeaders (5 test cases)
✓ TestContactRateLimiter_EnforcesLimit
✓ TestContactRateLimiter_DifferentIPs
✓ TestComprehensiveSecurity_AttackScenarios (5 scenarios)
✓ TestSecurityHeaders_AllPresent
ALL TESTS PASS ✅
```
### Performance Benchmarks
```
BenchmarkBrowserOnlyMiddleware 508,612 ops 2,350 ns/op 6,371 B/op 38 allocs/op
BenchmarkRateLimiter 535,658 ops 2,401 ns/op 7,382 B/op 44 allocs/op
BenchmarkSecurityChain 433,215 ops 3,110 ns/op 7,478 B/op 46 allocs/op
⚡ Performance: ~320,000 requests/second through full security chain
```
## Attack Scenarios Tested
### Scenario 1: Script Kiddie with curl
**Attack**: Direct curl request
```bash
curl -X POST /api/contact -d "email=hacker@evil.com&message=Pwned"
```
**Result**: ❌ Blocked 403 Forbidden (no browser User-Agent)
### Scenario 2: Sophisticated Bot
**Attack**: Bot with browser-like headers but fills honeypot
```bash
curl -X POST /api/contact \
-H "User-Agent: Mozilla/5.0" \
-H "Referer: http://target.com/" \
-H "HX-Request: true" \
-d "website=http://spam.com&..."
```
**Result**: ✅ Returns fake 200 (bot fooled), email not sent
### Scenario 3: Automated Form Filler
**Attack**: Script that fills form instantly (<2s)
```bash
curl -X POST /api/contact \
-H "User-Agent: Mozilla/5.0" \
-H "Referer: http://target.com/" \
-H "HX-Request: true" \
-d "submit_time=<500ms ago>&..."
```
**Result**: ❌ Blocked 400 Bad Request (too fast)
### Scenario 4: Postman/API Client
**Attack**: Postman without proper headers
```bash
curl -H "User-Agent: PostmanRuntime/7.26.8" ...
```
**Result**: ❌ Blocked 403 Forbidden (non-browser client)
### Scenario 5: Email Header Injection
**Attack**: Malicious newlines in subject
```bash
curl -d "subject=Test%0AContent-Type:%20text/html&..." ...
```
**Result**: ❌ Blocked 400 Bad Request (validation error)
## CI/CD Integration
### GitHub Actions Example
```yaml
name: Security Tests
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.25'
- name: Run Security Tests
run: |
go test -v ./tests/security/middleware_security_test.go
go test -v ./tests/security/contact_security_test.go
- name: Security Test Coverage
run: go test -cover ./tests/security/middleware_security_test.go
- name: Start Server & Run Live Tests
run: |
go run main.go &
sleep 5
./tests/security/security_tests.sh http://localhost:8080
```
## Maintenance
### Adding New Security Tests
1. **Unit Test** (for new middleware):
- Add test in `middleware_security_test.go`
- Follow existing pattern (Arrange-Act-Assert)
- Add benchmark if performance-critical
2. **Integration Test** (for new validation):
- Add test in `contact_security_test.go`
- Test with full handler chain
3. **Live Test** (for black-box validation):
- Add function in `security_tests.sh`
- Follow existing format with colored output
- Update test counter
### Security Checklist for Code Reviews
- [ ] New middleware added to middleware_security_test.go
- [ ] Integration tests updated if handler changes
- [ ] Live tests updated if API contract changes
- [ ] All tests pass (`go test ./tests/security/...`)
- [ ] Benchmarks run (<5ms per request)
- [ ] Documentation updated
## Troubleshooting
### Server Not Running Error
```bash
✗ Server is not accessible at http://localhost:8080
Please start the server first: go run main.go
```
**Solution**: Start server in separate terminal before running shell tests
### Permission Denied on Shell Script
```bash
permission denied: ./security_tests.sh
```
**Solution**: Make script executable
```bash
chmod +x ./tests/security/security_tests.sh
```
### Rate Limit Test Failures
If rate limit tests fail intermittently:
- Tests share the same rate limiter instance
- Wait 1 hour between test runs, or
- Restart the test server to reset limits
## Security Standards Compliance
**OWASP Top 10** Protection:
- A01: Broken Access Control - BrowserOnly middleware
- A02: Cryptographic Failures - HTTPS enforcement (production)
- A03: Injection - Input validation & sanitization
- A05: Security Misconfiguration - Secure headers
- A07: Identification/Authentication Failures - Rate limiting
**CWE Coverage**:
- CWE-352: CSRF (CSRF token validation)
- CWE-79: XSS (CSP headers, input sanitization)
- CWE-20: Improper Input Validation (comprehensive validation)
- CWE-770: Unrestricted Resource Consumption (rate limiting)
- CWE-862: Missing Authorization (browser-only access)
## Contact
For questions or issues with security tests:
1. Check test output for specific failure details
2. Review this README for troubleshooting
3. Examine test source code for implementation details
---
**Last Updated**: 2025-11-30
**Test Coverage**: 100% of security features
**Performance**: Sub-millisecond middleware execution