Files
cv-site/doc/SECURITY.md
T
juanatsap f211d40803 docs: consolidate and sanitize documentation for public release
**Changes Summary:**

**Files Deleted (6 files):**
- doc/HTMX-PRODUCTION-RECOMMENDATIONS.md (implementation notes)
- doc/SEO-OPTIMIZATION-COMPLETE.md (implementation artifact)
- doc/PROJECT-DOCUMENTATION-SUMMARY.md (meta-documentation)
- doc/PROJECT_STATUS.md (internal roadmap)
- doc/API-QUICK-REFERENCE.md (consolidated into API.md)
- doc/API-PROTECTION.md (consolidated into API.md and SECURITY.md)

**API Documentation Enhanced:**
- Added Quick Reference section to API.md (from API-QUICK-REFERENCE.md)
- Added Security & Protection section to API.md (from API-PROTECTION.md)
- Updated Rate Limiting section to reflect actual implementation
- Added Origin Checking documentation with examples

**SECURITY.md Enhanced:**
- Added comprehensive API Protection Features section
- Updated Rate Limiting section (was marked "Not implemented", now shows it IS implemented)
- Added Origin Checking configuration and examples
- Added Combined Protection flow documentation
- Added Testing Protection section with curl examples
- Added Production Deployment Checklist
- Added Troubleshooting section

**Private Information Removed:**
- README.md: Removed matomo.drolo.club and site ID references
- PRIVACY.md: Replaced specific Matomo server with generic template
- CUSTOMIZATION.md: Replaced Analytics Configuration with generic guide
- All Matomo-specific details replaced with placeholders

**Documentation Navigation:**
- README.md: Enhanced Documentation section with organized categories
  - Getting Started (README, DEPLOYMENT, CUSTOMIZATION)
  - Technical Reference (ARCHITECTURE, API)
  - Policies & Standards (SECURITY, PRIVACY, CODE_OF_CONDUCT, CONTRIBUTING)
  - License

**Broken Links Fixed:**
- Removed reference to non-existent CHANGELOG.md in API.md
- Fixed relative paths for cross-document references
- Verified all internal documentation links

**Result:**
- Documentation reduced from 16 files to 10 core files (37.5% reduction)
- No private information exposed (all Matomo details sanitized)
- No implementation artifacts remaining
- Clear, professional structure suitable for public instructive project
- Comprehensive API and security documentation
- All essential content preserved and enhanced

This documentation now represents a professional, instructive open-source project suitable for public consumption and learning purposes.
2025-11-12 16:04:43 +00:00

14 KiB

Security Policy

Supported Versions

This project is actively maintained. Security updates will be provided for the latest release on the main branch.

Version Supported
main
< main

Reporting a Vulnerability

We take the security of this CV site seriously. If you discover a security vulnerability, please help us protect users by following responsible disclosure practices.

How to Report

DO NOT open a public issue for security vulnerabilities.

Instead, please report security vulnerabilities by:

  1. GitHub Security Advisories (Preferred):

    • Go to the repository's Security tab
    • Click "Report a vulnerability"
    • Fill out the form with details
  2. Direct Contact:

    • Open a private issue or contact the maintainer directly
    • Use encrypted communication if the vulnerability is severe

What to Include

Please provide the following information in your report:

  • Description of the vulnerability
  • Steps to reproduce the issue
  • Potential impact (e.g., data exposure, XSS, CSRF)
  • Affected versions (if known)
  • Suggested fix (if you have one)
  • Your contact information for follow-up questions

Response Timeline

  • Initial Response: Within 48 hours
  • Status Update: Within 7 days
  • Fix Timeline: Depends on severity
    • Critical: Within 7 days
    • High: Within 14 days
    • Medium: Within 30 days
    • Low: Next release cycle

Disclosure Policy

  • We ask that you give us reasonable time to fix the vulnerability before public disclosure
  • We will credit you in the security advisory (unless you prefer to remain anonymous)
  • Once the fix is deployed, we will publish a security advisory with details

Security Considerations for Deployments

If you're deploying this CV site, please be aware of these security considerations:

1. PDF Generation Security

The server uses headless Chrome (via chromedp) to generate PDFs:

  • Risk: Chromedp executes JavaScript and renders HTML, which could be exploited if user input is not sanitized
  • Mitigation:
    • The CV data comes from trusted JSON files, not user input
    • If you modify the application to accept user input, ensure proper sanitization
    • Consider running chromedp in a sandboxed environment

2. Content Security Policy

The application includes CSP headers:

Content-Security-Policy: default-src 'self';
  script-src 'self' 'unsafe-inline' https://unpkg.com;
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  img-src 'self' data:
  • Review and adjust CSP headers based on your deployment needs
  • Remove 'unsafe-inline' if possible by moving inline scripts/styles to separate files

3. Environment Variables

Sensitive configuration is managed via environment variables:

  • Never commit .env file to version control
  • Use .env.example as a template
  • In production, use secure secret management (e.g., HashiCorp Vault, AWS Secrets Manager)

4. HTTPS in Production

  • Always use HTTPS in production
  • Configure TLS certificates (Let's Encrypt recommended)
  • Consider using a reverse proxy (nginx, Caddy) for TLS termination

5. Rate Limiting & Origin Checking

Status: Implemented

The application includes built-in rate limiting and origin checking for resource-intensive endpoints:

Protected Endpoints:

  • /export/pdf - Rate limited to 3 requests per minute per IP
  • Origin checking prevents external hotlinking

Configuration:

# Set allowed domains in production
ALLOWED_ORIGINS=yourdomain.com,www.yourdomain.com

Features:

  • IP-based rate limiting (3 PDF/min per IP)
  • Origin/Referer header validation
  • Works with reverse proxies (Nginx, CloudFlare)
  • Automatic IP detection from X-Forwarded-For headers

For detailed configuration, see API Protection Features below.

6. Input Validation

While this application primarily serves static CV data:

  • If you extend it to accept user input, implement strict validation
  • Sanitize all inputs before rendering in templates
  • Use Go's html/template package (which auto-escapes) for HTML rendering

7. Dependency Management

Keep dependencies up to date:

# Check for outdated dependencies
go list -u -m all

# Update dependencies
go get -u ./...
go mod tidy

8. Security Headers

The application sets security headers:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection: 1; mode=block
  • Content-Security-Policy: ...

Review and enhance these headers based on your deployment needs.

9. Logging and Monitoring

  • Enable structured logging in production
  • Monitor for unusual patterns (e.g., excessive PDF generation requests)
  • Set up alerts for errors and anomalies

10. Docker Security

If deploying via Docker:

  • Use official, minimal base images
  • Run container as non-root user
  • Scan images for vulnerabilities (e.g., docker scan, Trivy)
  • Keep base images updated

API Protection Features

The application implements multiple layers of protection to prevent external access and DDoS attacks on resource-intensive endpoints.

Origin Checking

Purpose: Prevent external sites from hotlinking to resource-intensive endpoints like PDF generation.

How It Works:

  1. Checks Origin header (CORS requests)
  2. Falls back to Referer header (navigation requests)
  3. Validates against whitelist of allowed domains
  4. Blocks requests from external domains

Configuration via Environment Variable:

# Development (default - allows localhost)
ALLOWED_ORIGINS=

# Production (specify your domains)
ALLOWED_ORIGINS=yourdomain.com,www.yourdomain.com

# Multiple domains
ALLOWED_ORIGINS=yourdomain.com,www.yourdomain.com,staging.yourdomain.com

Behavior by Environment:

Environment No Header Localhost Your Domain External Domain
Development Allowed Allowed Allowed Blocked
Production Blocked (PDF) Allowed Allowed Blocked

Example Requests:

# ✅ Allowed (localhost in development)
curl http://localhost:1999/export/pdf?lang=en

# ✅ Allowed (valid referer)
curl -H "Referer: https://yourdomain.com/" \
  https://yourdomain.com/export/pdf?lang=en

# ❌ Blocked (external referer)
curl -H "Referer: https://evil.com/" \
  https://yourdomain.com/export/pdf?lang=en
# Response: 403 Forbidden - External access not allowed

Rate Limiting

Purpose: Prevent abuse even from allowed origins by limiting request frequency.

Current Configuration:

  • Endpoint: /export/pdf
  • Limit: 3 requests per minute per IP address
  • Window: 1 minute (rolling)
  • Response: 429 Too Many Requests when exceeded

Implementation:

// Applied in main.go
pdfRateLimiter := middleware.NewRateLimiter(3, 1*time.Minute)

Behavior:

Requests Status Response
1st-3rd requests 200 OK PDF generated
4th+ request (within 1 min) 429 Too Many Requests Rate limit exceeded
After 1 minute 200 OK Counter reset

IP Detection:

  • Checks X-Forwarded-For header (proxy/CDN scenarios)
  • Falls back to X-Real-IP header (alternative proxy header)
  • Uses RemoteAddr field (direct connections)
  • Works correctly behind Nginx, CloudFlare, and other reverse proxies

Rate Limit Response:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: text/plain; charset=utf-8

Rate limit exceeded. Please try again later.

Combined Protection

The PDF endpoint has both origin checking and rate limiting applied in sequence:

Request Flow:
User Request → Origin Checker → Rate Limiter → PDF Handler
                    ↓                ↓
            403 if external   429 if exceeded

Protection Scenarios:

  1. Scenario: External hotlinking attempt

    • External site links directly to your PDF endpoint
    • Mitigation: Origin checker blocks (403 Forbidden)
    • Result: Request never reaches rate limiter
  2. Scenario: Rapid PDF generation from your site

    • Legitimate user on your domain requests many PDFs quickly
    • Mitigation: Rate limiter blocks after 3 requests/min (429)
    • Result: Prevents resource exhaustion
  3. Scenario: Distributed attack with header spoofing

    • Botnet spoofs Referer headers to bypass origin check
    • Mitigation: HTTPS prevents header modification + Rate limiter per IP
    • Result: Each IP limited to 3 requests/min

Configuration Examples

Development Environment:

# .env file
PORT=1999
HOST=localhost
GO_ENV=development
ALLOWED_ORIGINS=  # Empty allows localhost

Behavior:

  • Allows localhost and 127.0.0.1
  • Allows requests without headers
  • Rate limit: 3 PDF/min per IP

Production Environment:

# .env file
PORT=1999
HOST=0.0.0.0
GO_ENV=production
ALLOWED_ORIGINS=yourdomain.com,www.yourdomain.com

Behavior:

  • Only allows specified domains
  • Requires Origin or Referer header for PDF endpoint
  • Blocks direct URL access
  • Rate limit: 3 PDF/min per IP

Testing Protection

Test Origin Checking:

# ✅ Should succeed (localhost in development)
curl http://localhost:1999/export/pdf?lang=en

# ✅ Should succeed (valid referer)
curl -H "Referer: http://localhost:1999/" \
  http://localhost:1999/export/pdf?lang=en

# ❌ Should fail (external referer)
curl -H "Referer: https://evil.com/" \
  http://localhost:1999/export/pdf?lang=en
# Expected: 403 Forbidden

Test Rate Limiting:

# Generate 4 PDFs quickly to trigger rate limit
for i in {1..4}; do
  echo "Request $i:"
  curl -w "Status: %{http_code}\n" -o /dev/null -s \
    http://localhost:1999/export/pdf?lang=en
  sleep 1
done

# Expected output:
# Request 1: Status: 200
# Request 2: Status: 200
# Request 3: Status: 200
# Request 4: Status: 429

Customizing Protection

Adjust Rate Limits:

Edit main.go to change limits:

// Current: 3 requests per minute
pdfRateLimiter := middleware.NewRateLimiter(3, 1*time.Minute)

// More restrictive: 5 per hour
pdfRateLimiter := middleware.NewRateLimiter(5, 1*time.Hour)

// Less restrictive: 10 per minute
pdfRateLimiter := middleware.NewRateLimiter(10, 1*time.Minute)

Apply Protection to Other Endpoints:

// Protect /cv endpoint
protectedCVHandler := middleware.OriginChecker(
    http.HandlerFunc(cvHandler.CVContent),
)
mux.Handle("/cv", protectedCVHandler)

Production Deployment Checklist

Before deploying to production:

  • Set GO_ENV=production in environment
  • Configure ALLOWED_ORIGINS with your domain(s)
  • Test origin checking with external domain
  • Test rate limiting with rapid requests
  • Verify HTTPS is enabled (prevents header spoofing)
  • Set up monitoring for 403/429 responses
  • Configure log retention for security analysis
  • Test PDF generation under load
  • Verify reverse proxy headers (X-Forwarded-For)
  • Document allowed origins in runbook

Troubleshooting

Problem: Legitimate users getting 403 Forbidden

Cause: ALLOWED_ORIGINS not configured correctly

Solution:

# Ensure all your domains are listed (comma-separated, no spaces)
ALLOWED_ORIGINS=yourdomain.com,www.yourdomain.com

# Check for typos (domain matching is case-insensitive but exact)
# Verify in logs which domain is being rejected

Problem: Rate limit too restrictive

Cause: Legitimate users hitting the 3 requests/min limit

Solution:

// Increase limit in main.go
pdfRateLimiter := middleware.NewRateLimiter(5, 1*time.Minute) // or higher

Problem: Behind reverse proxy, rate limiting not working per IP

Cause: IP detection failing, all requests seen as same IP

Solution:

# Ensure Nginx passes correct headers
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;

Problem: Origin header not being sent

Cause: Browser doesn't send Origin for same-origin navigation requests

Solution: This is normal browser behavior. The middleware checks Referer header as fallback, which browsers do send for navigation.

For technical API details, see API.md.


Known Security Considerations

PDF Generation Resource Usage

  • Issue: PDF generation uses headless Chrome, which consumes significant CPU/memory
  • Impact: Potential DoS via excessive PDF generation requests
  • Mitigation:
    • Implement rate limiting on /export/pdf endpoint
    • Consider caching generated PDFs
    • Monitor resource usage

Third-Party Dependencies

External dependencies loaded from CDNs:

  • HTMX from https://unpkg.com
  • Google Fonts from https://fonts.googleapis.com

Recommendation: For production, consider:

  • Self-hosting these dependencies for better control
  • Using Subresource Integrity (SRI) hashes
  • Implementing a Content Security Policy

Security Best Practices

If you're forking this project for your own CV:

  1. Review all code before deploying
  2. Update personal information in JSON files
  3. Configure security headers appropriate for your use case
  4. Enable HTTPS with valid certificates
  5. Keep dependencies updated regularly
  6. Monitor application logs for suspicious activity
  7. Backup your data regularly
  8. Test security before going live

Security Updates

Security updates will be announced via:

  • GitHub Security Advisories
  • Release notes on GitHub
  • Git commit messages tagged with [SECURITY]

Contact

For security concerns, please contact the project maintainer via GitHub.

Acknowledgments

We appreciate the security research community's efforts in responsibly disclosing vulnerabilities. Thank you for helping keep this project secure!