Skip to main content

Security & permissions

Nexus runs autonomous agents that touch real repos and clusters. Security is defense in depth across four layers.

Layers

LayerEnforces
Nexus CoreWhether an agent may be dispatched with a given tool/permission set; raises approvals for gated actions.
RunnerRefuses any action the run config didn't grant.
Kubernetes RBACThe run's service account can only touch what its role allows.
nexus-auth crateAdmin 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 with argon2.
  • 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):

ControlSetting
Run as non-rootrunAsNonRoot: true, runAsUser/Group: 1000, fsGroup: 1000
No privilege escalationallowPrivilegeEscalation: false, privileged: false
Drop capabilitiescapabilities.drop: ["ALL"]
Immutable root FSreadOnlyRootFilesystem: true (+ writable emptyDir at /tmp and /workspace)
SeccompseccompProfile: RuntimeDefault
No cluster accessautomountServiceAccountToken: false
Auto-cleanupttlSecondsAfterFinished: 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

  • .env never 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.