Skip to content
Rookery OS

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

AspectImplementation
TLSTLS 1.3 terminated at GKE Gateway
CertificatesGoogle-managed SSL certificates
HTTPS RedirectAll HTTP → HTTPS redirect via HTTPRoute
Internal TrafficUnencrypted within pod (shared network namespace)
Service-to-ServiceINTERNAL_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
HardeningPurpose
ASLRAddress Space Layout Randomization — prevents buffer overflow exploits
No core dumpsPrevents memory extraction via crash dumps
No SUIDPrevents privilege escalation via setuid binaries
Non-rootAll processes run as agent (UID 1001)
tiniProper signal handling, prevents zombie processes
Minimal packagesReduced 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 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

FromToAllowed
KernelSidecarYes (shared pod network)
KernelPlatform APIYes
KernelInternet (LLM)Yes
SidecarInternet (websites)Yes
ExternalKernel :8080Via Gateway only
ExternalSidecar :6080Via noVNC proxy only
NavigatorOther podsNo

Layer 4: Data Security

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)             │
└──────────────────────────────────────────┘
AspectImplementation
AlgorithmAES-256-GCM (authenticated encryption)
Key ManagementPer-tenant DEK in GCP Secret Manager
Key AccessWorkload Identity binding (production pods only)
IV HandlingRandom IV per encryption operation
Auth TagGCM provides integrity verification
StoragePostgreSQL cookie_vault table
NavigatorNo access — Cookie Vault disabled for free tier

Database Security

AspectImplementation
ConnectionSSL required, Cloud SQL proxy in GKE
AuthenticationService account + password
Row-Level SecurityTenant isolation via tenant_id column
System Coreis_system_core flag prevents modification by tenants
MigrationsSequential 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)

RoleAccess
platform_adminAll endpoints, all tenants, system config
tenant_adminOwn tenant's agents, settings, billing
userOwn workspace, assigned agents
navigatorAssessment 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)

FlagDefaultSecurity Impact
ENABLE_SIDECARfalseEnables browser container (attack surface increase)
USE_BROWSER_INTERFACEfalsePer-connector browser vs API toggle
ENABLE_COOKIE_VAULTfalseEnables encrypted cookie storage
ENABLE_HITLfalseEnables human-in-the-loop authentication
NAVIGATOR_MODEfalseRestricted 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

  1. kubectl delete pod <pod-name> -n <namespace> — immediate kill
  2. Rotate DEK in GCP Secret Manager — invalidate cookie vault
  3. Audit cookie_vault table for the affected agent
  4. Review audit logs for unauthorized access patterns
  5. Reprovision pod with fresh credentials
  1. Rotate per-tenant DEK in Secret Manager
  2. DELETE FROM cookie_vault WHERE tenant_id = $1 — clear all cookies
  3. Human re-authentication required on next session
  4. Audit access logs for the affected tenant
  1. Navigator pods auto-delete after 24 hours
  2. Resource quotas prevent crypto mining or DoS
  3. Network policies prevent lateral movement
  4. No persistent storage — all data is ephemeral