Skip to content

Security: gpazo/Rat-Things

Security

docs/security.md

Security and threat model

For a concise introduction, read the security overview.

Security posture

Treat prompts, webhook fields, repositories, tool results and model output as untrusted. A valid provider signature authenticates the delivery; it does not make its author or content trustworthy. Rat Things owns the API, harness, state and workers in the operator's AWS account.

An AWS managed Session uses a dedicated worker VM. Workspaces and execution identities are isolated by owner and Session. The native sandbox is additional protection; the outer VM is the primary execution boundary. Trusted orchestration runs as root and launches Codex or Pi Durable and repository commands as UID/GID 10001. The worker sandbox defaults to workspace-only writes with agent networking off. The host-side local harness retains its separate read-only/no-network policy.

Managed execution verifies the official Codex process's effective permission profile before exposing tools. Unexpected merged grants, unknown policy files or incomplete policy inspection prevent startup. Agent networking off uses a network namespace and a proxy with no allowed destinations. Local socket metadata and anonymous socketpairs remain available for subprocess I/O; external connections and named Unix socket access remain denied.

The EC2 worker supports connected Session lifetime beyond Lambda MicroVM's maximum lifetime. Both backends must preserve the same ownership, process and credential boundaries. Self-hosted executor connections also require an operator-controlled sandbox; transport encryption does not make a shared or privileged executor safe.

Local workspaces

The local desktop has a different placement boundary: Codex inference and ChatGPT sign-in stay on the host, while managed commands run as UID 10001 in a Session-owned container inside a local Linux VM. The container engine and its VM are trusted host components. The worker mounts only its named workspace volume, receives scoped executor transport credentials, and has no host folder, Docker socket, AWS credential chain or subscription login mounted. Only an authenticated loopback transport is published. Native permissions enforce the admitted workspace and network policy; approval requests fail closed. This first local backend supports Apple silicon Macs and does not claim that a bare container on a Linux host supplies the same outer VM boundary.

The host harness uses a private Rat Things Codex home for sign-in and thread history. It does not inherit the user's personal Codex configuration. Host plugins, apps and hooks are disabled, and unexpected host MCP configuration prevents a Session from starting. Subscription login material stays in that private home.

Session copying locks an idle source while stopping writers and taking a bounded workspace snapshot. Its encrypted local receipt supports retry. The destination principal owns the imported Session and supplies its own model connection. Login files outside the workspace are never part of the transfer. Workspace files and explicit environment values are user content and are copied as reviewed.

Protected assets

  • AWS resources, worker roles and model credentials.
  • Provider signing secrets, clone tokens, delivery tokens and OAuth refresh tokens.
  • Vault credentials and environment variables deliberately installed into a sandbox.
  • Private source, prompts, native journals, workspace files, Items and saved artifacts.
  • Provider destinations, model budget and execution capacity.

Trust boundaries

API caller -> authenticated HTTPS API -> durable Session state and outbox
Provider   -> provider authentication -> owned source binding -> Session input
                                                     |
                                               private dispatch
                                                     |
                                          dedicated worker + harness
                                                     |
                                          durable Turns and Items
                                                     |
                                     delivery adapters -> provider APIs

The authenticated API principal owns its resources. A provider event supplies attribution and source metadata; the preconfigured source binding selects the operator owner and Agent. Generic source selectors are trusted operator configuration, not proof that an arbitrary tenant owns a repository or channel. Destination selection and credential-subject selection remain separate from actor attribution. No caller-provided URL or credential may establish ownership.

Threats and controls

Threat Present control Boundary or remaining concern
Forged webhook Authenticate before parsing; verify exact raw-body signatures where supported Legacy GitLab token auth does not sign the body or enforce freshness; see channels
Duplicate ingress Owner/binding-scoped input receipts and conditional commits Retention bounds deduplication; do not treat a trigger mention as authorization
Cross-owner access Owner-scoped resources, hashed storage prefixes and authenticated lookups Review authorizer/tenant mapping and deployment IAM independently
Malicious repository Dedicated VM, argument-array commands, HTTPS host allowlist and unprivileged checkout commands Native tools can exercise all admitted authority; same-UID model/environment credentials are readable by repository code
Guest reaches control plane Root-owned listener/configuration, guest UID split and cgroup eBPF local-port denial A root/kernel escape compromises the worker boundary
Guest steals AWS role Sanitized child environment and metadata denial on EC2 Keep the explicit AWS credential-chain escape hatch disabled
MCP or function abuse Explicit tool declarations, credential selection, transport policy and fail-closed approval handling Sandbox code can read inline environment secrets and exercise admitted Vault placeholders
Credential confused deputy Distinct owner, actor, source, destination and credential subject; broker checks before secret reads Trusted adapters and the service role remain authoritative
OAuth replay or account swap Hashed one-use state, PKCE, owner binding, verified provider identity and serialized refresh Reconnection must preserve the expected tenant/subject; provider consent is an external boundary
Browser SSRF Browser tools run within the admitted execution environment and its network policy Provider origin filters are not an isolation boundary; redirects, private destinations and DNS rebinding require enforced deployment egress controls
Duplicate external write Durable delivery fences and explicit unknown-outcome state Reconcile ambiguous provider acceptance; never automatically replay it merely because an acknowledgement was lost
Lost Session event Durable journal/event commits and an outbox separate from delivery effects Outbox failures and expired retries need operator reconciliation
Superseded worker write Immutable execution generation, backend identity and conditional state changes Lost process memory cannot be recreated from public Items alone
Artifact disclosure Private encrypted objects, owner checks, saved Turn/path identity and explicit publication grants Publication URLs are bearer credentials; provider copies have independent retention
Resource exhaustion Bounded requests, pagination, queues and deployment concurrency controls Configure tenant budgets, API throttles and provider-event abuse limits
Supply-chain compromise Locked packages, pinned source/base image, official package integrity and complete artifact digests Review build provenance and scan/sign release artifacts

Fixed capability-envelope security model

The Session retains its resolved Agent configuration. Tools and environments are admitted before execution and cannot be widened through a native approval request. Codex uses approvalPolicy: "never"; approval-shaped requests fail closed. Missing tools, IAM denials, broker rejection and blocked network destinations remain failures, not pending authorization.

Connection installation, OAuth initiation, identity replacement, grants and source-binding management are owner-authenticated operator actions. They are not automatically exposed as model tools. Notification connection sets do not imply Agent tool access. A host can explicitly provide a function or MCP service backed by an appropriate broker, with a separately reviewed capability envelope. See the capability envelope.

IAM separation

Keep these roles distinct:

  1. Token issuance authenticates callers without provider-administration authority.
  2. The HTTPS API reads/writes canonical resources and dispatches through durable state. Its policy is separate from provider control and the outbox.
  3. Ingress validates provider credentials and records normalized inputs under source bindings.
  4. The outbox performs admitted execution, scheduling, webhook and terminal-delivery effects.
  5. Dispatch launches the selected worker backend under constrained launch/pass-role permissions.
  6. The trusted worker reads its runtime inputs and selected secrets, updates fenced execution state and writes Session files/journals. The guest receives only explicitly admitted model and environment credentials.
  7. Delivery reads the saved terminal Turn and credentials for its destination. It does not execute model-generated commands or clone repositories.

The EC2 backend has no inbound worker security-group rules. A private durable command mailbox carries control requests, and each claim precedes its effect. An uncertain acknowledgement does not authorize replay. Commands are fenced to their intended public Turn and execution generation.

Lambda MicroVM control uses AWS-issued port-scoped proxy tokens. Keep those tokens inside trusted orchestration. Its root listener permits the service proxy while the guest-local cgroup policy denies UID 10001 access to port 8080. Neither transport exposes an authority-widening guest route.

Scope Secrets Manager ARNs, storage prefixes, launch templates, image inputs and iam:PassRole. Worker role permissions are broader than one Session's object prefix, so the root boundary is material. The agent must not inherit that role's full credential chain.

Secret handling

Store values in Secrets Manager; public configuration uses resource IDs or approved references. Never place tokens in prompts, clone URLs, DynamoDB records, task overrides or logs. Keep webhook, clone, model, Vault and delivery identities distinct. A Workflow URL is a credential.

Service-side MCP credentials stay in the service process. A Vault environment_variable credential supplies a placeholder to a hosted sandbox. The trusted host substitutes its secret in HTTPS headers only for the credential's exact allowed hosts on port 443 or 8443, within the environment's network policy. TLS verification and public-address checks precede each outbound request. Raw values and certificate private keys remain outside the guest UID. A Session keeps its credential snapshot across Vault rotation; new Sessions use the replacement value.

Plain environment values and inline environment MCP variables can be read by sandbox code. Use Vault placeholders for outbound API authentication when the sandbox should not read the secret or use it for local computation.

With CODEX_AUTH_MODE=chatgpt, trusted orchestration reads the selected encrypted file-based login, materializes a private auth.json, persists validated refresh rotation and removes the runtime copy during cleanup. Only the approved secret reference crosses orchestration. A persistent Session may retain the credential while its harness is active.

Codex must read that file, so malicious same-UID code can steal its bearer and renewable refresh tokens. Possession can permit account impersonation and Codex usage. Validation preserves unknown fields, so protect the whole bundle rather than assuming other sensitive fields are absent. Use the bridge only for trusted owner-operated workloads, and use account-session revocation plus secret removal when a credential is compromised. Encrypted backing storage does not remove the active-process risk.

Codex can also use Bedrock. Trusted orchestration mints a bounded bearer token from its AWS identity or reads the configured token secret. Keep ALLOW_AGENT_AWS_CREDENTIAL_CHAIN false unless exposing the entire role is intentional. The requested model identifier must retain its meaning; a substitute provider/model is not a compatibility repair.

Pi Durable uses Bedrock Converse with the deployment's exact model and inference resource allowlists. The host mints short-term model tokens and keeps AWS role credentials out of the Pi process. Native commit writes require the active Run and ownership version, so a replaced worker cannot continue writing Session state.

Keep model credentials out of image builds, test logs and diagnostic output. See Codex subscription setup for the file bridge and its lifecycle.

Storage and retention

Prompts, journals and artifacts live in encrypted S3. DynamoDB stores resource state, references and bounded summaries. Owner checks remain required even when an object outlives its database record. Saved artifacts are immutable per Turn/path; publishing creates a separate explicit grant. Artifact deletion and workspace-file deletion are distinct operations.

DynamoDB TTL is asynchronous. S3 lifecycle, event retry windows, CloudWatch retention and provider copies have separate lifetimes. Align them with the operator's retention policy.

S3 Files resources hold active Session journals. Their conversation_state Terraform addresses and /conversations filesystem root identify Session storage. Preserve these resources when maintaining worker infrastructure.

Repository and process isolation

Accept only allowlisted credential-free HTTPS repository URLs. Commands use argument arrays; trusted orchestration never interpolates a prompt, URL, ref or path into a shell command. Repository-controlled Git configuration and commands execute as UID 10001.

Workspace paths are anchored beneath the configured root. A replacement worker may reuse only the same owner/Session storage under its fenced execution identity. Native checkpoints preserve harness history; public-item recovery preserves historical facts without replaying tool effects. Neither recovery path promises survival of a process whose VM has been destroyed.

Codex checkpoint publication requires a successful cold resume of copied native history after all writers stop and storage is synchronized. A separate verifier runs without credentials or network access; it cannot modify the saved candidate. Evidence covers root and child identities, public native history, and the flushed host journal. It does not inspect hidden Codex mailbox state or preserve running commands. Unsupported startup integrations or unverifiable state prevent handoff.

The EC2 supervisor requires the outer dedicated VM for its privileged mount/network setup. The agent does not receive the Docker socket or host control configuration. Metadata and the local control listener are denied to the guest while trusted root orchestration remains able to operate.

MicroVM-specific review

Lambda MicroVM snapshots must contain only generic initialization. Supply Session identity, credentials and runtime clients during launch, not image build. Keep launch hooks within the service payload limit and keep worker proxy tokens in trusted orchestration.

S3 Files mounting and the local control-port guard require privileged in-VM setup. The agent still runs as UID 10001. Suspended memory and disk are sensitive Session state and remain subject to configured expiry and explicit teardown. Lambda MicroVM lifetime is bounded; select the EC2 backend for connected-process requirements beyond that bound.

Deployment responsibilities

Deployment review must cover IAM/pass-role scope, authorizer ownership, guest credential and metadata isolation, outbound network policy, replay/unknown-outcome handling, budget limits and artifact access. Keep release provenance and secret rotation procedures current.

There aren't any published security advisories