Skip to content

Security Best Practices

Eric Fitzgerald edited this page Jan 26, 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, custom providers
  • Token Type: JWT tokens with configurable expiration
  • Flow: OAuth 2.0 authorization code flow

Key Settings:

  • Change JWT_SECRET from default in production
  • Set appropriate JWT expiration time (default: 24 hours)
  • Use HTTPS for all OAuth callback URLs

See Setting-Up-Authentication for configuration details.

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

Docker Scout Integration

TMI includes automated container vulnerability scanning using Docker Scout:

  • Scans container images for CVEs
  • Reports vulnerabilities by severity level
  • Enforces security thresholds in build process
  • Patches known vulnerabilities in base images

Quick Start:

# 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

Security Thresholds

Default vulnerability limits (configurable):

  • Critical CVEs: 0 allowed (build fails)
  • High CVEs: 3 allowed (warning)
  • Medium CVEs: 10 allowed (informational)

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 (~57MB)
  • PostgreSQL: cgr.dev/chainguard/postgres:latest - Secure database

Container Hardening

  • Chainguard base images with minimal CVEs and daily updates
  • Static binaries built with CGO_ENABLED=0
  • All containers run as nonroot:nonroot by default
  • No shell, package manager, or unnecessary tools in runtime
  • 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:

TLS_ENABLED=true
TLS_CERT_FILE=/path/to/cert.pem
TLS_KEY_FILE=/path/to/key.pem
TLS_HTTP_REDIRECT=true  # Redirect HTTP to HTTPS

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 JWT_SECRET from default "secret"
  • Length: Use strong, randomly generated secrets (256+ bits)
  • Storage: Store in secure secrets vault (HashiCorp Vault, AWS Secrets Manager, etc.)
  • 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

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

Security Monitoring

# Monitor security logs
tail -f logs/security.log

# Check for failed authentication attempts
grep "auth_failed" logs/security.log

# Monitor authorization changes
grep "authorization_changed" logs/audit.log

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 JWT_SECRET from default
  • Enable TLS/HTTPS
  • Configure OAuth providers with HTTPS callback URLs
  • Set appropriate JWT expiration time
  • 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

ENV=production
TLS_ENABLED=true
LOG_LEVEL=info
JWT_SECRET=<strong-random-secret>
OAUTH_CALLBACK_URL=https://your-domain.com/oauth2/callback

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. Email details to security@tmi.dev
  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 (Client-Side)

TMI-UX implements comprehensive HTTP security headers to protect against common web vulnerabilities.

Dynamic Content Security Policy

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
  • Prevents clickjacking via frame-ancestors
  • Includes WebSocket support for real-time collaboration
  • Supports Google Fonts and OAuth callbacks

Example CSP Generated:

default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com data:;
img-src 'self' data: https: blob:;
connect-src 'self' https://api.example.com wss: ws: https:;
object-src 'none';

Required Deployment Headers

These headers must be configured at the server/proxy level (not via meta tags):

Header Value Purpose
X-Frame-Options DENY Prevents clickjacking (CSP frame-ancestors ignored in meta tags)
X-Content-Type-Options nosniff Prevents MIME type sniffing
Strict-Transport-Security max-age=31536000; includeSubDomains Forces HTTPS
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
    location /ws {
        proxy_pass http://backend:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Testing Security Headers

# Check headers
curl -I https://tmi.example.com

# Online validation
# - https://securityheaders.com
# - https://observatory.mozilla.org
# - https://csp-evaluator.withgoogle.com

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

Home

Releases


Getting Started

Deployment

Operation

Troubleshooting

Development

Integrations

Tools

API Reference

Reference

Clone this wiki locally