Security Architecture

Transparent security documentation for this portfolio

Security-First Approach

I built this site with the same security standards I apply to every project. This page documents what I've implemented and why — not to impress, but because I believe security decisions should be visible and reviewable.

A+ SecurityHeaders.io A+ SSL Labs

Philosophy: Transparency over obscurity. Every measure documented here stands on its own merits.

All Checks Passing
cargo deny

Advisories & Licenses

cargo audit

Vulnerability Scan

cargo clippy

Lint Checks

cargo test

Test Suite

Content-Security-Policy (CSP)

default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests; report-uri /api/csp-report; report-to csp-endpoint

Purpose: Controls which resources the browser is allowed to load

Prevents: Cross-Site Scripting (XSS), Data Injection, Clickjacking

X-Frame-Options

DENY

Purpose: Prevents the page from being embedded in frames/iframes

Prevents: Clickjacking attacks

X-Content-Type-Options

nosniff

Purpose: Prevents browsers from MIME-sniffing responses

Prevents: MIME confusion attacks, malicious file execution

Strict-Transport-Security (HSTS)

max-age=31536000; includeSubDomains; preload

Purpose: Forces all connections to use HTTPS for 1 year

Prevents: Man-in-the-Middle (MitM) attacks, SSL stripping

Additional Headers

  • Referrer-Policy: Controls referrer information leakage
  • Permissions-Policy: Disables 8 browser features (geolocation, camera, microphone, payment, USB, magnetometer, gyroscope, accelerometer)
  • X-XSS-Protection: Legacy auditor disabled (CSP provides XSS protection)
  • Cross-Origin-Opener-Policy: Isolates browsing context (Spectre protection)
  • Cross-Origin-Resource-Policy: Prevents cross-origin resource embedding
  • X-Permitted-Cross-Domain-Policies: Blocks Flash/Acrobat policy loading
  • X-Request-ID: Unique UUID for audit trails

General Endpoints

Limit: 100 requests per 60 seconds per IP

Applies to: All public endpoints

Authentication Endpoints

Limit: 5 requests per 60 seconds per IP

Purpose: Prevents brute force attacks

Implementation: actix-governor with RealIpKeyExtractor for accurate client identification

Password Security

  • Algorithm: Argon2id (OWASP recommended)
  • Why Argon2id: Memory-hard, resistant to GPU/ASIC attacks
  • Policy: NIST 800-63B (length-based, common password blocklist)

Session Management

  • Access Tokens: JWT with 15-minute expiry
  • Refresh Tokens: 7-day expiry with rotation
  • Storage: JSON response body, Authorization header
  • CSRF: Immune (Authorization header, not cookies)
  • Token Blacklist: Redis-backed JWT revocation on logout
0 Critical 0 High 0 Medium 3 Low — remediated or accepted

Conducted February 2026 covering 8 phases: reconnaissance, TLS/SSL analysis, web application scanning, authentication testing, injection testing, configuration review, infrastructure scanning, and exploitation attempts.

Full report available on request via contact form.

  • Active PostgreSQL 17: Strong typing and ACID compliance
  • Active Connection Pooling: Prevents connection exhaustion
  • Active Prepared Statements: SQL injection prevention via SQLx
  • Defined Row-Level Security: Policies defined in migrations, not yet enforced at application level
cargo audit passing No known vulnerabilities

Security Policy

  • Dependabot: Automated dependency update alerts via GitHub
  • Security Patches: Applied immediately upon discovery
  • CI Integration: cargo audit + cargo deny + clippy on every build
  • Minimal Dependencies: Only essential, well-maintained crates

Server Infrastructure (Active)

  • Host: Hetzner Cloud Helsinki (Debian 13)
  • Service: systemd unit with automatic restart
  • Proxy: nginx reverse proxy with TLS termination
  • Firewall: UFW — ports 22, 80, 443 only

Operations (Active)

  • HTTPS: Let's Encrypt with auto-renewal
  • Backups: Daily PostgreSQL backups with rotation
  • Monitoring: Health checks every 5 minutes (ntfy.sh alerts)
  • Access: Dedicated deploy user with locked permissions
  • Active Input Sanitisation: Submissions sanitised before database storage (stored-XSS prevention)
  • Active PGP-Encrypted Notifications: Messages encrypted to admin's PGP public key before email delivery — content never transmitted in plaintext
  • Active Fail-Open Design: Email or notification failures never block the visitor's form submission

Security Contact & Responsible Disclosure

Responsible disclosure is appreciated. Security issues will be addressed within 48 hours.

Initial response within 24 hours, patches within 48–72 hours depending on severity.