RookeryOS — Security Model
Zero-trust, encrypted, isolated — every layer has its own security boundary
Security Layers
┌─────────────────────────────────────────────┐
│ Layer 5: Application Security │
│ JWT auth, RBAC, API key scoping │
├─────────────────────────────────────────────┤
│ Layer 4: Data Security │
│ AES-256-GCM, per-tenant DEK, Secret Mgr │
├─────────────────────────────────────────────┤
│ Layer 3: Network Security │
│ K8s NetworkPolicy, namespace isolation │
├─────────────────────────────────────────────┤
│ Layer 2: Container Security │
│ Hardened images, non-root, ASLR, no SUID │
├─────────────────────────────────────────────┤
│ Layer 1: Transport Security │
│ TLS 1.3, GKE Gateway termination │
└─────────────────────────────────────────────┘
Layer 1: Transport Security
| Aspect | Implementation |
|---|---|
| TLS | TLS 1.3 terminated at GKE Gateway |
| Certificates | Google-managed SSL certificates |
| HTTPS Redirect | All HTTP → HTTPS redirect via HTTPRoute |
| Internal Traffic | Unencrypted within pod (shared network namespace) |
| Service-to-Service | INTERNAL_KEY header for API authentication |
HTTP-to-HTTPS Redirect
Every hostname in the platform has an HTTP→HTTPS redirect route:
# aw2-system/http-to-https-redirect
hostnames:
- agentworksstudio.com
- www.agentworksstudio.com
- app.agentworksstudio.com
- api.agentworksstudio.com
- gateway.agentworksstudio.com
Layer 2: Container Security
RookeryOS Base Image
The hardened base image applies kernel-level security:
# Kernel hardening
RUN sysctl -w kernel.randomize_va_space=2 # ASLR enabled
RUN echo "kernel.core_pattern=/dev/null" >> /etc/sysctl.conf # No core dumps
# Remove SUID binaries
RUN find / -perm /4000 -type f -exec chmod -s {} \; 2>/dev/null || true
# Strip non-essential packages
RUN apt-get purge -y ...
# Games, sound, printing, perl, docs, editors, etc.
# Non-root user
USER agent:agent
| Hardening | Purpose |
|---|---|
| ASLR | Address Space Layout Randomization — prevents buffer overflow exploits |
| No core dumps | Prevents memory extraction via crash dumps |
| No SUID | Prevents privilege escalation via setuid binaries |
| Non-root | All processes run as agent (UID 1001) |
| tini | Proper signal handling, prevents zombie processes |
| Minimal packages | Reduced attack surface |
Layer 3: Network Security
Namespace Isolation
Each production agent pod runs in its own namespace:
agent-blue-heron-3cb587f4/ ← Ava pod
agent-blue-heron-4fddfb76/ ← Dr. Mitchell pod
agent-blue-heron-f0b49f04/ ← Tom pod
platform/ ← Platform services (API, Console, Gateway)
voice/ ← STT/TTS service
aw2-system/ ← Gateway, KEDA, system resources
navigator/ ← Free-tier pods (isolated)
Navigator Network Policy
Navigator pods are restricted to platform API + internet only:
# infrastructure/k8s/navigator/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: navigator-network-policy
namespace: navigator
spec:
podSelector: {} # Apply to ALL pods in namespace
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: aw2-system # Only from Gateway
egress:
- to:
- namespaceSelector:
matchLabels:
name: platform # Platform API only
- to:
- ipBlock:
cidr: 0.0.0.0/0 # Internet (for LLM calls)
Production Pod Network
| From | To | Allowed |
|---|---|---|
| Kernel | Sidecar | Yes (shared pod network) |
| Kernel | Platform API | Yes |
| Kernel | Internet (LLM) | Yes |
| Sidecar | Internet (websites) | Yes |
| External | Kernel :8080 | Via Gateway only |
| External | Sidecar :6080 | Via noVNC proxy only |
| Navigator | Other pods | No |
Layer 4: Data Security
Cookie Vault
Browser cookies are encrypted with per-tenant keys:
┌──────────────────────────────────────────┐
│ Cookie Encryption Flow │
│ │
│ 1. Human authenticates via noVNC │
│ 2. HITL Controller captures cookies │
│ 3. Request DEK from GCP Secret Manager │
│ 4. Encrypt cookies with AES-256-GCM │
│ 5. Store encrypted blob in PostgreSQL │
│ │
│ cookie_vault table: │
│ ├── tenant_id (UUID) │
│ ├── agent_id (UUID) │
│ ├── domain (TEXT) │
│ ├── encrypted_cookies (BYTEA) │
│ ├── iv (BYTEA) │
│ ├── auth_tag (BYTEA) │
│ └── expires_at (TIMESTAMPTZ) │
└──────────────────────────────────────────┘
| Aspect | Implementation |
|---|---|
| Algorithm | AES-256-GCM (authenticated encryption) |
| Key Management | Per-tenant DEK in GCP Secret Manager |
| Key Access | Workload Identity binding (production pods only) |
| IV Handling | Random IV per encryption operation |
| Auth Tag | GCM provides integrity verification |
| Storage | PostgreSQL cookie_vault table |
| Navigator | No access — Cookie Vault disabled for free tier |
Database Security
| Aspect | Implementation |
|---|---|
| Connection | SSL required, Cloud SQL proxy in GKE |
| Authentication | Service account + password |
| Row-Level Security | Tenant isolation via tenant_id column |
| System Core | is_system_core flag prevents modification by tenants |
| Migrations | Sequential numbered SQL files, applied in order |
Layer 5: Application Security
Authentication
Login Flow:
POST /auth/login → bcrypt verify → JWT (RS256) → { accessToken, refreshToken }
Token Types:
├── GATEWAY_TOKEN — WebSocket relay authentication
├── PLATFORM_API_TOKEN — REST API authentication (JWT)
└── INTERNAL_SERVICE_KEY — Pod-to-API service authentication
Role-Based Access Control (RBAC)
| Role | Access |
|---|---|
platform_admin | All endpoints, all tenants, system config |
tenant_admin | Own tenant's agents, settings, billing |
user | Own workspace, assigned agents |
navigator | Assessment only, no persistent data |
Credential Safety
Rookery rule: Agents must NEVER display credential values.
- Credentials are use-only: retrieve → authenticate → report outcome
- API keys stored in K8s secrets (
aw2-api-secrets) - Agent pods receive keys via environment variables
- No credential values in logs, responses, or LLM context
Feature Flags (Security Controls)
| Flag | Default | Security Impact |
|---|---|---|
ENABLE_SIDECAR | false | Enables browser container (attack surface increase) |
USE_BROWSER_INTERFACE | false | Per-connector browser vs API toggle |
ENABLE_COOKIE_VAULT | false | Enables encrypted cookie storage |
ENABLE_HITL | false | Enables human-in-the-loop authentication |
NAVIGATOR_MODE | false | Restricted mode — no PVC, no cookies, 24h TTL |
All security-sensitive features are off by default and must be explicitly enabled per deployment.
Incident Response
Compromised Agent Pod
kubectl delete pod <pod-name> -n <namespace>— immediate kill- Rotate DEK in GCP Secret Manager — invalidate cookie vault
- Audit
cookie_vaulttable for the affected agent - Review audit logs for unauthorized access patterns
- Reprovision pod with fresh credentials
Compromised Cookie Vault
- Rotate per-tenant DEK in Secret Manager
DELETE FROM cookie_vault WHERE tenant_id = $1— clear all cookies- Human re-authentication required on next session
- Audit access logs for the affected tenant
Navigator Abuse
- Navigator pods auto-delete after 24 hours
- Resource quotas prevent crypto mining or DoS
- Network policies prevent lateral movement
- No persistent storage — all data is ephemeral
