Skip to content

Documentation

Enterprise Security Architecture

Comprehensive security system with runtime threat detection, automated response, and nonce-based CSP for enterprise-grade protection.

3/27/2026
11 min read Edit on GitHub

SveltyCMS implements a multi-layered, enterprise-grade security system that combines build-time validation, runtime threat detection, and automated security response. The architecture provides comprehensive protection against XSS, CSRF, injection attacks, and sophisticated threat patterns.


Security Architecture Overview

Core Security Components

  1. Build-Time Security Validation - Static analysis and dependency security scanning
  2. Runtime Threat Detection - Real-time security event monitoring and correlation
  3. Nonce-Based Content Security Policy - Cryptographically secure XSS prevention
  4. Automated Security Response - Dynamic threat mitigation and blocking
  5. Security Metrics & Analytics - Comprehensive security monitoring dashboard

Runtime Security Services

SecurityResponseService - Automated Threat Detection

Purpose: Real-time threat analysis with automated response capabilities File: src/services/security-response-service.ts

export class SecurityResponseService {
  // Centralized security analysis
  public async analyzeRequest(request: Request, clientIp: string): Promise<SecurityStatus> {
    // 1. IP Block check (Persistent Redis state)
    if (await securityStore.isBlocked(clientIp)) return { level: "critical", action: "block" };

    // 2. Rate Limit check (Per-endpoint + Global)
    const rateLimit = await this.checkRateLimit(clientIp, new URL(request.url).pathname);
    if (rateLimit.action !== "allow") return rateLimit;

    // 3. Payload pattern analysis (XSS, SQLi, ReDoS-safe)
    const threatLevel = await this.analyzePayload(request);

    // 4. Automated Decision Engine
    return this.mapThreatToResponse(threatLevel, clientIp);
  }
}

Key Features:

  • Distributed Rate Limiting: Redis-backed limits for high-availability clusters.
  • ReDoS-Safe Patterns: Bounded regex quantifiers and length-capped payload scanning.
  • Structured Analysis: Recursive JSON scanning and multipart value inspection.
  • Multi-Tenant Isolation: Automated security response scoped by tenantId.

MetricsService - Security Analytics

Purpose: Unified security and performance metrics with real-time analysis File: src/services/metrics-service.ts

export class MetricsService {
  // Security-specific metrics
  incrementSecurityEvent(type: SecurityEventType): void {
    this.counters.set(`security.${type}`, (this.counters.get(`security.${type}`) || 0) + 1);
  }

  getSecurityReport(): SecurityMetrics {
    return {
      totalThreats: this.counters.get("security.threats_detected") || 0,
      blockedIPs: this.counters.get("security.ips_blocked") || 0,
      cspViolations: this.counters.get("security.csp_violations") || 0,
      authFailures: this.counters.get("security.auth_failures") || 0,
      threatsByType: this.getThreatsBreakdown(),
      securityTrends: this.calculateSecurityTrends(),
    };
  }
}

Content Security Policy (CSP) Implementation

Nonce-Based CSP Architecture

Purpose: Cryptographically secure XSS prevention with dynamic nonce generation File: src/hooks/addSecurityHeaders.ts

export function generateNonce(): string {
  return crypto.randomUUID().replace(/-/g, "");
}

export function buildCSP(nonce: string): string {
  return [
    "default-src 'self'",
    `script-src 'self' 'nonce-${nonce}' 'strict-dynamic'`,
    `style-src 'self' 'nonce-${nonce}' 'unsafe-inline'`,
    "object-src 'none'",
    "base-uri 'self'",
    "form-action 'self'",
    "frame-ancestors 'none'",
    "block-all-mixed-content",
    `report-uri /api/security/csp-violations`,
  ].join("; ");
}

export async function addSecurityHeaders({ event, resolve }) {
  const response = await resolve(event);
  const nonce = event.locals.nonce;

  // Apply nonce-based CSP
  response.headers.set("Content-Security-Policy", buildCSP(nonce));

  // Additional security headers
  response.headers.set("X-Frame-Options", "DENY");
  response.headers.set("X-Content-Type-Options", "nosniff");
  response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
  response.headers.set("Permissions-Policy", "camera=(), microphone=(), geolocation=()");

  // HSTS for production
  if (event.url.protocol === "https:") {
    response.headers.set(
      "Strict-Transport-Security",
      "max-age=31536000; includeSubDomains; preload",
    );
  }

  return response;
}

Key Features:

  • Crypto-Secure Nonces: Unpredictable nonces prevent XSS injection
  • Violation Reporting: CSP violations automatically reported to security service
  • Defense in Depth: Multiple security headers for comprehensive protection
  • Production Hardening: HSTS enforcement for HTTPS-only environments

CSP Violation Handling

Purpose: Real-time CSP violation monitoring and threat response File: src/routes/api/security/csp-violations/+server.ts

export async function POST({ request, getClientAddress }) {
  const violation = await request.json();
  const clientIP = getClientAddress();

  // Analyze violation severity
  const threatLevel = await securityResponseService.analyzeCSPViolation({
    violatedDirective: violation["violated-directive"],
    blockedURI: violation["blocked-uri"],
    sourceFile: violation["source-file"],
    clientIP,
  });

  // Execute automated response
  await securityResponseService.executeResponse(threatLevel, clientIP);

  // Update security metrics
  metricsService.incrementSecurityEvent("csp_violation");

  return new Response(null, { status: 204 });
}

Build-Time Security Plugin

Overview

The Vite Security Check Plugin provides build-time protection against accidental exposure of private settings in client-side code. Unlike static environment variables (e.g., PRIVATE_* in SvelteKit), our dynamic settings loaded from the database don’t have built-in Vite protection. This plugin fills that gap.

The Problem

Static Environment Variables (Built-in Protection βœ…)

// .env file
PRIVATE_DB_PASSWORD=secret123  // βœ… Vite warns if used in client code
PUBLIC_API_URL=https://api.com  // βœ… Safe for client

SvelteKit’s PRIVATE_ prefix triggers build-time warnings if accidentally imported in .svelte files.

Dynamic Settings (No Built-in Protection ❌)

// Loaded from database at runtime
const settings = {
  DB_PASSWORD: "secret123", // ❌ No compile-time protection!
  JWT_SECRET_KEY: "abc...", // ❌ Could leak to browser
  ENCRYPTION_KEY: "xyz...", // ❌ Dangerous if imported in .svelte
};

Our database-driven settings lack this protection because they’re loaded at runtime, not compile-time.

The Solution

The src/utils/vitePluginSecurityCheck.ts scans all code during build and fails the build if it detects dangerous patterns:

🚨 Blocked Patterns

  1. Direct privateEnv imports in client code

    // ❌ BLOCKED - Exposes ALL private settings to browser!
    import { privateEnv } from "@src/stores/global-settings";
    console.log(privateEnv.DB_PASSWORD); // Would be visible in browser
  2. getPrivateSetting() calls in .svelte files

    // ❌ BLOCKED - Attempts to access private data on client!
    import { getPrivateSetting } from "@src/stores/global-settings";
    const secret = getPrivateSetting("JWT_SECRET_KEY");

3. **`getAllSettings()` in client code**
   ```typescript
   // ❌ BLOCKED - Returns both public AND private settings!
   import { getAllSettings } from "@src/stores/global-settings";
   const all = await getAllSettings(); // Includes passwords!
   ```

### βœ… Safe Patterns

1. **Public settings in any file**

   ```typescript
   // βœ… SAFE - Public settings can be used anywhere
   import { publicEnv, getPublicSetting } from "@src/stores/global-settings";
   console.log(publicEnv.SITE_NAME); // Safe for browser
   ```

2. **Private settings in server-side files**

   ```typescript
   // βœ… SAFE - Server-only files can use private settings
   // Files: +page.server.ts, +layout.server.ts, +server.ts, /hooks/, /auth/, /databases/
   import { privateEnv, getPrivateSetting } from "@src/stores/global-settings";
   const dbPass = privateEnv.DB_PASSWORD; // Never sent to client
   ```

3. **Passing data via page.data**

   ```typescript
   // βœ… SAFE - Controlled data flow from server to client

   // +page.server.ts (server-only)
   export async function load() {
     const dbStatus = await checkDatabase(privateEnv.DB_HOST);
     return {
       isConnected: dbStatus.connected, // Only pass safe data
       // Never return privateEnv directly!
     };
   }

   // +page.svelte (client)
   export let data;
   console.log(data.isConnected); // βœ… Safe
   ```

## Configuration

The plugin is configured in `vite.config.ts`:

```typescript
import { securityCheckPlugin } from "./src/utils/vitePluginSecurityCheck";

export default defineConfig({
  plugins: [
    securityCheckPlugin({
      failOnError: true, // Fail build on violations (recommended)
      showWarnings: true, // Show suspicious patterns
      extensions: [".svelte", ".ts", ".js"], // Files to check
    }),
    // ... other plugins
  ],
});
```

## How It Works

### 1. File Scanning

The plugin runs during Vite's `transform` phase and scans every file that matches the configured extensions.

### 2. Smart Filtering

Not all `.ts` files are client-side! The plugin intelligently skips:

- **Server-only route files**: `+page.server.ts`, `+layout.server.ts`, `+server.ts`
- **Server-only hooks**: All files in `/hooks/`
- **API routes**: All files in `/routes/api/`
- **Auth modules**: All files in `/auth/`
- **Database code**: All files in `/databases/`
- **Widget utilities**: `.ts` files in `/widgets/` (typically server-only)
- **The store itself**: `/stores/global-settings.ts` (defines the functions)

### 3. Pattern Detection

For client-side files (primarily `.svelte` and client-facing `.ts`), the plugin uses regex patterns to detect:

```
const DANGEROUS_PATTERNS = [
  {
    pattern: /import\s+{[^}]*privateEnv[^}]*}\s+from\s+['"]@src\/stores\/global-settings['"]/g,
    message: "SECURITY: Importing privateEnv exposes passwords and secrets!",
  },
  {
    pattern: /getPrivateSetting\s*\(/g,
    message: "SECURITY: getPrivateSetting() in client code!",
  },
  {
    pattern: /getAllSettings\s*\(/g,
    message: "SECURITY: getAllSettings() exposes private data!",
  },
];
```

### 4. Build Failure

If violations are detected, the build fails with a detailed error report:

```
🚨 SECURITY VIOLATIONS DETECTED!

Found 2 critical security issue(s):

  βœ— src/components/Settings.svelte:5
    SECURITY: Importing privateEnv exposes passwords and secrets!
    β†’ import { privateEnv } from '@src/stores/global-settings';

  βœ— src/routes/(app)/admin/+page.svelte:12
    SECURITY: getPrivateSetting() in client code!
    β†’ const secret = getPrivateSetting('JWT_SECRET');

These violations expose sensitive data to the client!
Fix these issues before deploying to production.

How to fix:
  1. Remove privateEnv imports from .svelte files
  2. Use page.data from +page.server.ts load functions instead
  3. Only access private settings in +page.server.ts, +layout.server.ts, or +server.ts files
```

## Real-World Example

### ❌ Vulnerable Code

```
<!-- src/routes/(app)/settings/+page.svelte -->
<script lang="ts">
  import { privateEnv } from '@src/stores/global-settings';

  // 🚨 CRITICAL VULNERABILITY: ALL private settings exposed!
  // Browser DevTools can access:
  // - privateEnv.DB_PASSWORD
  // - privateEnv.JWT_SECRET_KEY
  // - privateEnv.ENCRYPTION_KEY
  // - privateEnv.SMTP_PASSWORD
  // - privateEnv.GOOGLE_CLIENT_SECRET
  // etc.

  const dbInfo = {
    host: privateEnv.DB_HOST,
    password: privateEnv.DB_PASSWORD // Visible in browser source!
  };
</script>

<div>Database: {dbInfo.host}</div>
```

**Impact**: Complete credential exposure, allows full system compromise.

### βœ… Secure Code

```
<!-- src/routes/(app)/settings/+page.server.ts -->
import { privateEnv } from '@src/stores/global-settings';
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async () => {
  // βœ… Server-only: privateEnv never sent to client
  const isConnected = await testConnection(
    privateEnv.DB_HOST,
    privateEnv.DB_PASSWORD // Safe - stays on server
  );

  return {
    // Only return safe, non-sensitive data
    dbStatus: isConnected ? 'connected' : 'disconnected',
    dbHost: privateEnv.DB_HOST // Host is not sensitive
    // Never return: DB_PASSWORD, JWT_SECRET, etc.
  };
};
```

```
<!-- src/routes/(app)/settings/+page.svelte -->
<script lang="ts">
  import type { PageData } from './$types';
  export let data: PageData;
</script>

<div>Database Status: {data.dbStatus}</div>
<div>Host: {data.dbHost}</div>
```

## Best Practices

### 1. Server-Side Data Loading

Always load private settings in `+page.server.ts` and pass only necessary, safe data to the client via `page.data`.

### 2. Minimal Data Exposure

Only return the absolute minimum data needed. Never pass entire settings objects.

```
// ❌ BAD
export const load = async () => {
  return { settings: privateEnv }; // ALL secrets exposed!
};

// βœ… GOOD
export const load = async () => {
  return {
    siteName: publicEnv.SITE_NAME,
    cacheEnabled: privateEnv.CACHE_ENABLED === "true",
  };
};
```

### 3. Type Safety

Use TypeScript to enforce safe data contracts:

```
// src/routes/(app)/admin/types.ts
export interface SafeAdminData {
  dbConnected: boolean;
  cacheStatus: "enabled" | "disabled";
  // No password fields allowed!
}

// +page.server.ts
export const load = async (): Promise<SafeAdminData> => {
  return {
    dbConnected: await isDbConnected(),
    cacheStatus: privateEnv.CACHE_ENABLED === "true" ? "enabled" : "disabled",
  };
};
```

### 4. Code Review Checklist

Before committing, verify:

- βœ… No `privateEnv` imports in `.svelte` files
- βœ… No `getPrivateSetting()` calls in client code
- βœ… All sensitive operations in `+page.server.ts` or `+server.ts`
- βœ… `page.data` only contains safe, non-sensitive information
- βœ… Build passes without security violations

## Integration with CI/CD

The plugin automatically runs during your build process:

```
# Development
bun run dev      # No check during dev (for speed)

# Production build
bun run build    # βœ… Security check runs and fails on violations

# CI/CD (GitHub Actions, etc.)
- run: bun run build
  # Build will fail if security violations detected
```

## Disabling (Not Recommended)

If you need to temporarily disable for debugging:

```
// vite.config.ts
securityCheckPlugin({
  failOnError: false, // Show warnings but don't fail build
  showWarnings: true,
});
```

**⚠️ Warning**: Never deploy to production with `failOnError: false`!

## Related Documentation

- [Authentication System](/docs/reference/security/authentication-system) - 3-Layer Security Architecture
- [Settings System](/docs/reference/architecture/admin-user-management) - Managing system settings
- [Environment Variables](/docs/reference/architecture/configuration-management) - Static vs dynamic settings
- [Server Hooks Architecture](/docs/reference/architecture/server-hooks) - Enterprise middleware pipeline

---

## Security Dashboard Integration

### Real-Time Security Monitoring

**security-widget.svelte** - Enterprise security dashboard component
**File**: `src/components/dashboard/security-widget.svelte`

```
<script>
	import { onMount } from 'svelte';
	import { securityMetrics } from '$stores/security';

	let securityData = {
		totalThreats: 0,
		blockedIPs: 0,
		cspViolations: 0,
		recentEvents: []
	};

	onMount(async () => {
		// Real-time security metrics
		const response = await fetch('/api/security/metrics');
		securityData = await response.json();

		// Live updates
		const eventSource = new EventSource('/api/security/events');
		eventSource.onmessage = (event) => {
			const securityEvent = JSON.parse(event.data);
			securityData.recentEvents.unshift(securityEvent);
			securityData = securityData; // Trigger reactivity
		};
	});
</script>

<div class="security-dashboard">
	<div class="threat-overview">
		<div class="metric-card critical">
			<h3>Active Threats</h3>
			<span class="count">{securityData.totalThreats}</span>
		</div>

		<div class="metric-card warning">
			<h3>Blocked IPs</h3>
			<span class="count">{securityData.blockedIPs}</span>
		</div>

		<div class="metric-card info">
			<h3>CSP Violations</h3>
			<span class="count">{securityData.cspViolations}</span>
		</div>
	</div>

	<div class="security-events">
		<h3>Recent Security Events</h3>
		{#each securityData.recentEvents as event}
			<div class="event {event.severity}">
				<span class="timestamp">{new Date(event.timestamp).toLocaleTimeString()}</span>
				<span class="type">{event.type}</span>
				<span class="details">{event.details.ip}</span>
			</div>
		{/each}
	</div>
</div>
```

---

## Security API Endpoints

### Comprehensive Security Management API

**Security Metrics Endpoint**

```
// GET /api/security/metrics
export async function GET() {
  const metrics = metricsService.getSecurityReport();
  return json(metrics);
}
```

**Threat Management Endpoint**

```
// POST /api/security/threats/block
export async function POST({ request }) {
  const { ip, duration, reason } = await request.json();

  await securityResponseService.blockIP(ip, duration);
  metricsService.incrementSecurityEvent("manual_block");

  return json({ success: true, message: `IP ${ip} blocked for ${duration}` });
}
```

**Security Events Stream**

```
// GET /api/security/events (Server-Sent Events)
export async function GET() {
  const stream = new ReadableStream({
    start(controller) {
      securityResponseService.onSecurityEvent((event) => {
        controller.enqueue(`data: ${JSON.stringify(event)}\n\n`);
      });
    },
  });

  return new Response(stream, {
    headers: {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache",
      Connection: "keep-alive",
    },
  });
}
```

---

## Enterprise Security Features

### Advanced Threat Detection

- **Behavioral Analysis**: Pattern recognition across user sessions
- **Anomaly Detection**: Statistical analysis of request patterns
- **Geographic Filtering**: IP geolocation-based threat assessment
- **Device Fingerprinting**: Hardware-based threat correlation

### Automated Response Capabilities

- **Dynamic Rate Limiting**: Adaptive throttling based on threat levels
- **IP Blocking**: Temporary and permanent IP blacklisting
- **Session Termination**: Automatic logout for compromised accounts
- **Alert Escalation**: Real-time notifications to security teams

### Compliance & Audit

- **Security Event Logging**: Comprehensive audit trail
- **Compliance Reporting**: GDPR, SOC2, ISO 27001 compliance support
- **Forensic Analysis**: Detailed attack pattern analysis
- **Performance Impact**: Minimal overhead security operations

---

## Summary

The enterprise security architecture provides **comprehensive protection** through:

1. βœ… **Build-Time Validation**: Static analysis prevents vulnerabilities before deployment
2. βœ… **Runtime Threat Detection**: Real-time analysis with automated response
3. βœ… **Nonce-Based CSP**: Cryptographically secure XSS prevention
4. βœ… **Automated Response**: Dynamic threat mitigation without manual intervention
5. βœ… **Enterprise Monitoring**: Real-time security dashboard with detailed analytics
6. βœ… **Credentials Protection**: Build-time enforcement prevents sensitive data exposure

This multi-layered approach ensures enterprise-grade security while maintaining optimal performance and user experience.
securitycspthreat-detectionxss-preventionenterpriseautomated-responsereal-time-monitoring
Was this page helpful?