Security & permissions
Nexus runs autonomous agents that touch real repos and clusters. Security is defense in depth across four layers.
Layers
| Layer | Enforces |
|---|---|
| Nexus Core | Whether an agent may be dispatched with a given tool/permission set; raises approvals for gated actions. |
| Runner | Refuses any action the run config didn't grant. |
| Kubernetes RBAC | The run's service account can only touch what its role allows. |
nexus-auth crate | Admin users, API keys, agent tokens, tool/project permissions. |
A permission must be granted at every layer for an action to succeed.
Identity & tokens
- Admin users — JWT (
jsonwebtoken), passwords hashed withargon2. - API keys — for machine clients.
- Agent tokens — short-lived tokens minted per run so a pod can report back to Core, scoped to that run only.
- Telegram allowlist — only known user IDs may issue commands.
Permission model
agent.can_create_branch · agent.can_commit · agent.can_open_pr · agent.can_merge
agent.can_delete_files · agent.can_use_kubectl · agent.can_apply_k8s
agent.can_write_memory · agent.can_create_board_task
Approval gates
Agents declare actions that always need a human:
requires_human_approval_for:
- production_deploy
- dependency_upgrade
- database_migration
Gated attempts raise an approval request.
Kubernetes isolation
- Each run is an isolated Job in a dedicated agent namespace (
nexus-agents). - Core/worker service accounts can manage Jobs only there:
verbs: [create, get, list, watch, delete]
resources: [jobs, pods, pods/log]
Runner pod hardening
Every agent Job is created with a locked-down pod (see nexus-k8s):
| Control | Setting |
|---|---|
| Run as non-root | runAsNonRoot: true, runAsUser/Group: 1000, fsGroup: 1000 |
| No privilege escalation | allowPrivilegeEscalation: false, privileged: false |
| Drop capabilities | capabilities.drop: ["ALL"] |
| Immutable root FS | readOnlyRootFilesystem: true (+ writable emptyDir at /tmp and /workspace) |
| Seccomp | seccompProfile: RuntimeDefault |
| No cluster access | automountServiceAccountToken: false |
| Auto-cleanup | ttlSecondsAfterFinished: 3600 |
Secret injection
LLM keys are not baked into images. They live in the nexus-agent Secret in
the agent namespace and are injected via envFrom (referenced as optional, so a
missing secret fails the run fast rather than blocking scheduling):
OPENAI_API_KEY · ANTHROPIC_API_KEY · GIT_TOKEN
GIT_TOKEN (falling back to GITHUB_TOKEN / GITLAB_TOKEN) authenticates clones
of private https repositories in the agent's repository list.
The runner injects it into the clone URL at run time and never logs it; clone
errors are credential-redacted before they reach logs or run results. Repos marked
read_only are a convention the prompt conveys to the agent — enforce non-push
hard limits via permissions and review gates. Prefer https clones: the runner
NetworkPolicy allows egress on 443, so SSH (git@…, port 22) needs the egress
rule widened.
Agents using a subscription CLI backend (claude-code-cli / codex-cli) need
no API key. Instead a credentials PVC is mounted read-write at /creds
(CLAUDE_CONFIG_DIR=/creds/claude, CODEX_HOME=/creds/codex), populated once via
an interactive login pod. See LLM backends.
NetworkPolicy
Runner pods are confined by a NetworkPolicy (app=nexus-agent-runner):
- Ingress: denied entirely — nothing reaches a runner.
- Egress: DNS, the NATS event bus (port 4222), and outbound HTTPS (443) for LLM provider APIs only.
Enforcement requires a NetworkPolicy-capable CNI (Calico/Cilium); otherwise it is a safe no-op.
Memory safety
Agents cannot write permanent shared memory unattended at first — proposals go to a review queue and a human approves them. See Memory.
Secrets
.envnever committed.- Production secrets from a secrets manager; LLM keys, Taiga credentials, Telegram token, and JWT signing key rotated on a schedule.
Planned hardening
Nexus's container isolation is already at or beyond parity with comparable agents, but several runner-side safety layers are planned (see the Hermes gap analysis): a command firewall (pattern + smart-classifier + always-on hardline blocklist), application-layer egress/SSRF policy, input-trust scanning of SOUL/skill/memory/context before prompting, and per-skill credential scoping with secret redaction of tool output.