Skip to content

Security Best Practices

Eric Fitzgerald edited this page Apr 8, 2026 · 7 revisions

Security Best Practices

This page consolidates security guidance for deploying and operating TMI securely.

Authentication & Authorization

OAuth 2.0 Configuration

TMI integrates with OAuth providers for secure authentication:

  • Supported Providers: GitHub, Google, Microsoft (Azure AD), SAML, and any generic OAuth 2.0 / OIDC provider
  • Token Type: JWT tokens with configurable expiration and signing method (HS256, RS256, ES256)
  • Flow: OAuth 2.0 authorization code flow with PKCE (S256) support

Key Settings:

  • Change TMI_JWT_SECRET from default in production (default is "your-secret-key")
  • Set appropriate JWT expiration time via TMI_JWT_EXPIRATION_SECONDS (default: 3600 seconds / 1 hour)
  • Use HTTPS for all OAuth callback URLs (TMI_OAUTH_CALLBACK_URL)

See Setting-Up-Authentication for configuration details.

Session Management

TMI uses HttpOnly cookies for browser-based session management, providing XSS protection by preventing JavaScript access to tokens:

  • Access token cookie (tmi_access_token): HttpOnly, SameSite=Lax, Path=/
  • Refresh token cookie (tmi_refresh_token): HttpOnly, SameSite=Strict, Path=/oauth2
  • Bearer token fallback: API clients can also authenticate via Authorization: Bearer <token> header
  • Cookie configuration: TMI_COOKIE_ENABLED (default: true), TMI_COOKIE_DOMAIN, TMI_COOKIE_SECURE (auto-derived from TLS)

Role-Based Access Control

TMI implements three permission levels per object:

  • Owner - Full read/write/delete permissions
  • Writer - Read and write permissions (cannot delete or change authorization)
  • Reader - Read-only access

Authorization Rules:

  1. The owner field takes absolute precedence
  2. Highest role wins when user appears multiple times
  3. Use the "everyone" pseudo-group to grant access to all authenticated users
  4. Regular users cannot change authorization or ownership (only owner can)

For detailed rules, see the Architecture-and-Design wiki page (RBAC section).

Pseudo-Groups

The special "everyone" group grants access to all authenticated users:

{
  "owner": "admin@example.com",
  "authorization": [
    {
      "subject": "everyone",
      "subject_type": "group",
      "role": "reader"
    }
  ]
}

Container Security

Grype Integration

TMI includes automated container vulnerability scanning using Grype (Anchore):

  • Scans container images for CVEs
  • Reports vulnerabilities by severity level (SARIF and table formats)
  • Generates SBOMs using Syft (companion tool)

Quick Start:

# Check Grype is installed
make check-grype

# Scan containers for vulnerabilities
make scan-containers

# Build containers (uses Chainguard base images)
make build-containers

# Build individual containers for faster iteration
make build-container-db      # PostgreSQL only
make build-container-redis   # Redis only
make build-container-tmi     # TMI server only

# Generate security report
make report-containers

Vulnerability Scanning

Container images are scanned for vulnerabilities using Grype. Scan results are reported in SARIF and table formats. Review scan output after each build to identify and remediate vulnerabilities.

Chainguard Base Images

TMI uses Chainguard images for enhanced container security:

  • Builder: cgr.dev/chainguard/go:latest - Secure Go build environment
  • Runtime: cgr.dev/chainguard/static:latest - Minimal static runtime
  • PostgreSQL: cgr.dev/chainguard/postgres:latest - Secure database
  • Redis: cgr.dev/chainguard/redis:latest - Secure cache/session store

Container Hardening

  • Chainguard base images with minimal CVEs and daily updates
  • Static binaries built with CGO_ENABLED=0
  • TMI server container runs as nonroot:nonroot; Redis container runs as redis; PostgreSQL uses the Chainguard entrypoint default
  • No shell, package manager, or unnecessary tools in runtime (Chainguard static base)
  • Security labels and logging enabled
  • Resource limits implemented

See Container Security Guide for detailed procedures.

Network Security

HTTPS/TLS Configuration

Enable TLS to encrypt all traffic:

TMI_SERVER_TLS_ENABLED=true
TMI_SERVER_TLS_CERT_FILE=/path/to/cert.pem
TMI_SERVER_TLS_KEY_FILE=/path/to/key.pem
TMI_SERVER_TLS_SUBJECT_NAME=your-domain.com
TMI_SERVER_HTTP_TO_HTTPS_REDIRECT=true  # Redirect HTTP to HTTPS

The server enforces TLS 1.2 as the minimum version when TLS is enabled.

WebSocket Security

  • Use wss:// (secure WebSocket) in production
  • Use ws:// (standard WebSocket) only in development
  • Client connections are authenticated with JWT tokens

Network Isolation

  • Run database behind firewall
  • Use VPC/private networks for database access
  • Restrict Redis access to application server
  • Implement network policies in Kubernetes

Database Security

PostgreSQL

  • Connection: Use SSL/TLS for database connections
  • Credentials: Store in secure vaults (not config files)
  • Access Control: Use least-privilege database users
  • Backups: Encrypt backups at rest
  • Updates: Keep PostgreSQL patched for security updates

Redis

  • Authentication: Set strong password if exposed
  • Network: Keep Redis private; don't expose to internet
  • Persistence: Use RDB/AOF with encryption at rest
  • Memory: Monitor and limit memory usage

Secrets Management

JWT Secret

  • Critical: Change TMI_JWT_SECRET from the default "your-secret-key" (validation rejects the default)
  • Signing methods: HS256 (shared secret), RS256 (RSA keys), or ES256 (ECDSA keys) via TMI_JWT_SIGNING_METHOD
  • Length: For HS256, use strong, randomly generated secrets (256+ bits)
  • Storage: Store in secure secrets vault. TMI supports AWS Secrets Manager (TMI_SECRETS_PROVIDER=aws) and OCI Vault (TMI_SECRETS_PROVIDER=oci) natively.
  • Rotation: Rotate periodically and implement key versioning

OAuth Credentials

  • Store OAuth client secrets in secure vault
  • Never commit secrets to version control
  • Use environment variables, not config files
  • Implement secret rotation policies

TLS Certificates

  • Use certificates from trusted CAs
  • Implement certificate monitoring and renewal
  • Store private keys securely with restricted permissions
  • Use automated certificate management (Let's Encrypt, etc.)

Logging & Monitoring

Audit Logging

TMI uses structured JSON logging via Go's slog package. All log entries include request context for traceability.

  • Log all authentication attempts (successes and failures)
  • Log authorization changes and ownership transfers
  • Log data access by role and user
  • Implement centralized log collection

Log output is configured via:

  • logging.level in config YAML (or TMI_LOG_LEVEL env var): debug, info, warn, error
  • logging.log_dir: directory for log files (default: logs)
  • logging.also_log_to_console: dual output to stdout and files

Security Monitoring

Since TMI uses structured JSON logging, use jq or a log aggregation tool to query security events:

# Monitor security logs in real time
tail -f logs/tmi.log | jq 'select(.msg | test("auth|login|token"))'

# Check for failed authentication attempts
cat logs/tmi.log | jq 'select(.msg | test("Failed|failed|error")) | select(.msg | test("auth|token|login"))'

# Monitor authorization changes
cat logs/tmi.log | jq 'select(.msg | test("authorization|ownership|transfer"))'

Alerting

Implement alerts for:

  • Failed authentication attempts (repeated failures = potential attack)
  • Unauthorized access attempts
  • High/critical CVEs discovered
  • Certificate expiration warnings
  • Database connection failures

Deployment Security

Pre-deployment Checklist

  • Change TMI_JWT_SECRET from default (or configure RS256/ES256 keys)
  • Enable TLS/HTTPS (TMI_SERVER_TLS_ENABLED=true)
  • Configure OAuth providers with HTTPS callback URLs
  • Set appropriate JWT expiration time (TMI_JWT_EXPIRATION_SECONDS)
  • Configure CORS allowed origins (TMI_CORS_ALLOWED_ORIGINS)
  • Run security scan on all container images
  • Implement database access controls
  • Set up backup and recovery procedures
  • Configure logging and monitoring
  • Review and test disaster recovery plan

Production Configuration

TMI_BUILD_MODE=production
TMI_SERVER_TLS_ENABLED=true
TMI_SERVER_TLS_CERT_FILE=/path/to/cert.pem
TMI_SERVER_TLS_KEY_FILE=/path/to/key.pem
TMI_JWT_SECRET=<strong-random-secret>
TMI_OAUTH_CALLBACK_URL=https://your-domain.com/oauth2/callback
TMI_CORS_ALLOWED_ORIGINS=https://your-frontend-domain.com
TMI_COOKIE_SECURE=true

Kubernetes Deployment

  • Use network policies to restrict traffic
  • Implement pod security policies
  • Use RBAC for access control
  • Enable audit logging
  • Scan images before deployment
  • Use resource limits and quotas

Vulnerability Disclosure

If you discover a security vulnerability:

  1. Do not publicly disclose the vulnerability
  2. Report vulnerabilities by creating an issue in the repository
  3. Include proof of concept if possible
  4. Allow 90 days for patching before public disclosure

Security Updates

  • Subscribe to security notifications
  • Apply security patches promptly
  • Test patches in staging before production
  • Maintain an upgrade schedule (monthly recommended)

HTTP Security Headers

TMI-UX implements a multi-layered security approach for HTTP headers:

  1. Dynamic CSP: Content Security Policy is dynamically generated based on environment configuration
  2. Additional Headers: Configured at the deployment level (proxy/load balancer)
  3. Adaptive HSTS: Enabled only when TLS is available

Backend Security Headers

The TMI backend API server automatically sets the following security headers on all responses via middleware:

Header Value Notes
X-Content-Type-Options nosniff Always set
X-Frame-Options DENY Always set
X-XSS-Protection 0 Disabled per modern guidance
Content-Security-Policy default-src 'self'; ... Dev/production variants
Referrer-Policy strict-origin-when-cross-origin Always set
Cache-Control no-store, no-cache, must-revalidate Prevents caching of API responses
Permissions-Policy geolocation=(), microphone=(), camera=() Always set
Strict-Transport-Security max-age=31536000; includeSubDomains Only when TLS is enabled

CORS is handled via middleware with configurable allowed origins (TMI_CORS_ALLOWED_ORIGINS). In development mode (logging.is_dev=true), any origin is reflected. In production, only explicitly configured origins are allowed. Credentials are supported (Access-Control-Allow-Credentials: true).

Dynamic Content Security Policy (Frontend)

The Angular application dynamically generates and injects a CSP meta tag that:

  • Automatically includes your API URL from environment configuration
  • Supports both HTTP and HTTPS API endpoints
  • Provides XSS protection by restricting script sources
  • Includes mixed content protection with upgrade-insecure-requests (production/HTTPS only)
  • Supports WebSocket protocols (ws: and wss:) for real-time collaboration
  • Supports Google Fonts and FontAwesome CDN integration

Important CSP Limitations with Meta Tags:

  • frame-ancestors directive is ignored in meta tags (use X-Frame-Options header instead)
  • report-uri and report-to directives are ignored in meta tags
  • sandbox directive is ignored in meta tags
  • These directives must be set via HTTP headers at the server/proxy level

Example CSP Generated (frontend meta tag):

default-src 'self';
script-src 'self';
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdnjs.cloudflare.com;
font-src 'self' https://fonts.gstatic.com https://cdnjs.cloudflare.com data:;
img-src 'self' data: https: blob:;
connect-src 'self' https://api.example.com wss: ws: https:;
base-uri 'self';
form-action 'self';
object-src 'none';
media-src 'self';
worker-src 'self' blob:;
manifest-src 'self';
upgrade-insecure-requests

Note: The backend API server also sets its own CSP via HTTP headers with a more permissive script-src 'self' 'unsafe-inline' 'unsafe-eval' policy. The frontend and backend CSPs serve different purposes and apply to different responses.

Required Deployment Headers (Frontend Proxy)

When deploying the TMI-UX frontend behind a reverse proxy (nginx, etc.), these headers must be configured at the proxy level. The TMI backend API already sets these headers automatically via middleware.

Header Value Purpose
X-Frame-Options DENY or SAMEORIGIN Prevents clickjacking (CSP frame-ancestors ignored in meta tags)
X-Content-Type-Options nosniff Prevents MIME type sniffing
X-XSS-Protection 0 Disable legacy XSS auditor (use CSP instead)
Strict-Transport-Security max-age=31536000; includeSubDomains Forces HTTPS (TLS only)
Referrer-Policy strict-origin-when-cross-origin Controls referrer information
Permissions-Policy camera=(), microphone=(), geolocation=() Disables unused browser APIs

Nginx Configuration Example

server {
    listen 443 ssl http2;
    server_name tmi.example.com;

    # Security headers
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "0" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    server_tokens off;

    location / {
        root /var/www/tmi-ux;
        try_files $uri $uri/ /index.html;
    }

    # WebSocket support for diagram collaboration
    location ~ /threat_models/.*/diagrams/.*/ws$ {
        proxy_pass http://backend:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # WebSocket support for notifications
    location /ws/notifications {
        proxy_pass http://backend:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Testing Security Headers

Use the provided security check script:

pnpm run check:security

Or test online with:

For detailed configuration across all deployment scenarios (standalone, proxy, load balancer, Docker, AWS ALB), see the Security Headers Configuration Guide.

Related Documentation

Additional Resources

  • NIST Cybersecurity Framework
  • OWASP Application Security Top 10
  • Docker Security Best Practices
  • Kubernetes Security Documentation
  • OAuth 2.0 Security Best Current Practices

Clone this wiki locally