Skip to content

Security

root edited this page Dec 4, 2025 · 1 revision

Security

Luna includes comprehensive security measures to protect your data and system.


Overview

Area Protection
Secrets Docker secrets, encrypted storage
Authentication JWT tokens, bcrypt passwords
Authorization Per-user isolation
Network Rate limiting, SSRF protection
Code Sandboxed execution
Data Encryption at rest

Secrets Management

Docker Secrets

Sensitive credentials are stored as Docker secrets, never in code or environment variables:

# Create secrets directory
mkdir -p secrets

# Store secrets (not in version control)
echo "password" > secrets/postgres_password.txt
echo "jwt-key" > secrets/jwt_secret.txt

Secret Files

Secret Purpose
postgres_password.txt Database password
jwt_secret.txt JWT signing key
redis_password.txt Redis password
encryption_key.txt Token encryption
openai_api_key.txt OpenAI API
anthropic_api_key.txt Anthropic API
groq_api_key.txt Groq API
google_api_key.txt Google AI API
xai_api_key.txt xAI API
openrouter_api_key.txt OpenRouter API
elevenlabs_api_key.txt ElevenLabs TTS

Never Commit Secrets

# .gitignore
secrets/
*.txt
!secrets/.gitkeep

Authentication

JWT Tokens

Luna uses JSON Web Tokens for authentication:

Token Lifetime Purpose
Access 7 days API authentication
Refresh 7 days Token refresh

Password Security

  • Hashed with bcrypt
  • Salt rounds: 12
  • Never stored in plaintext

Token Flow

1. User logs in with email/password
2. Server validates credentials
3. Access + refresh tokens issued
4. Client includes access token in requests
5. Refresh token used to get new access token

Encryption

OAuth Token Encryption

OAuth tokens (Google, Microsoft) are encrypted at rest:

  • Algorithm: AES-256-GCM
  • Key: From encryption_key.txt
  • IV: Randomly generated per token

Database Encryption

PostgreSQL supports:

  • Connection encryption (SSL)
  • Data-at-rest encryption (OS-level)

Rate Limiting

Redis-backed rate limiting protects against abuse:

Endpoint Limit Window
/api/auth/login 10 1 min
/api/auth/register 5 1 min
/api/chat/send 60 1 min
/api/chat/tts 10 1 min
/api/abilities/* 100 1 min

Rate Limit Headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640000000

Input Validation

All API inputs validated with Zod schemas:

const messageSchema = z.object({
  message: z.string().min(1).max(100000),
});

const sessionSchema = z.object({
  mode: z.enum(['assistant', 'companion', 'voice']),
});

Validation Features

  • Type checking
  • Length limits
  • Format validation
  • Enum constraints
  • Custom rules

SSRF Protection

URL validation on external requests:

Blocked

  • Private IP ranges (10.x, 192.168.x, etc.)
  • Localhost (127.0.0.1)
  • Internal DNS names
  • Non-HTTP protocols

Implementation

const isAllowedUrl = (url: string) => {
  const parsed = new URL(url);
  // Block private IPs
  // Block localhost
  // Only allow http/https
  return isPublicUrl(parsed);
};

Code Sandbox

Code execution runs in isolated Docker containers:

Isolation Features

  • Separate container per execution
  • No network access
  • Limited filesystem
  • Resource limits (CPU, memory, time)
  • User namespace isolation

Limits

Resource Limit
CPU 1 core
Memory 512MB
Time 30 seconds
Disk 100MB

Security Headers

Helmet.js provides security headers:

Header Value
Content-Security-Policy Strict CSP
X-Frame-Options DENY
X-Content-Type-Options nosniff
Strict-Transport-Security max-age=31536000
X-XSS-Protection 1; mode=block

Fail2Ban Integration

Login attempt tracking for IP blocking:

Tracked Events

  • Failed logins
  • Invalid tokens
  • Rate limit violations

Configuration

// After 5 failed attempts in 15 minutes
// IP blocked for 1 hour

Container Hardening

Docker containers are hardened:

Security Options

security_opt:
  - no-new-privileges:true
cap_drop:
  - ALL
read_only: true

User Isolation

  • Non-root users
  • Minimal permissions
  • Isolated networks

SQL Injection Prevention

All database queries use parameterized statements:

// Safe
await db.query(
  'SELECT * FROM users WHERE id = $1',
  [userId]
);

// Never
// await db.query(`SELECT * FROM users WHERE id = ${userId}`);

Command Injection Prevention

External commands use spawn, not exec:

// Safe - no shell interpretation
spawn('python', ['script.py', arg]);

// Dangerous - shell injection possible
// exec(`python script.py ${arg}`);

File Upload Security

Document uploads are validated:

Checks

  • MIME type verification
  • Extension whitelist
  • Size limit (10MB)
  • Content scanning

Allowed Types

Type Extensions
Text .txt, .md, .json, .csv
Documents .pdf
Images .png, .jpg, .jpeg, .gif, .webp

API Security

Per-User Isolation

  • Users can only access their own data
  • Session ownership verified
  • Resource access controlled

Request Validation

  • All inputs sanitized
  • Response filtering
  • Error message sanitization

Best Practices

For Deployment

  1. Use Docker secrets

    • Never hardcode credentials
    • Rotate keys periodically
  2. Enable HTTPS

    • Use reverse proxy (nginx)
    • Valid SSL certificates
  3. Network isolation

    • Internal services not exposed
    • Firewall rules
  4. Regular updates

    • Keep dependencies updated
    • Monitor security advisories

For Users

  1. Strong passwords

    • 12+ characters
    • Mix of character types
  2. Secure API keys

    • Don't share keys
    • Use key rotation
  3. Local mode for sensitive data

    • Use Ollama for privacy
    • Disable external APIs

Reporting Security Issues

Report security vulnerabilities to:

Please:

  • Don't disclose publicly
  • Provide reproduction steps
  • Allow time for fix

Clone this wiki locally