Security Model¶
Container Execution in Backend.AI GO is designed with a defense-in-depth security model. Multiple independent layers work together to ensure containers operate within well-defined boundaries.
Security Layers¶
flowchart TD
REQ[Container Execution Request]
L1["Layer 1: Input Validation\n(ID/name/tag sanitization)"]
L2["Layer 2: Mount Allowlist\n(path canonicalization + allowlist check)"]
L3["Layer 3: Environment Sanitization\n(only approved env vars pass through)"]
L4["Layer 4: Credential Proxy\n(real API keys never enter containers)"]
L5["Layer 5: IPC Permissions\n(group-scoped send/task permissions)"]
L6["Layer 6: Security Audit\n(periodic audit of running containers)"]
CONT[Container Runs]
REQ --> L1 --> L2 --> L3 --> L4 --> L5 --> CONT --> L6 Layer 1: Input Validation¶
All container identifiers, image tags, and build contexts are validated before use to prevent argument injection attacks.
Container IDs and Names¶
Container names must:
- Not be empty
- Not start with
-(would be interpreted as a flag) - Contain only: alphanumeric characters,
_,.,-,:,/
Image Tags¶
Image tags must:
- Not be empty
- Not start with
- - Follow the format:
[registry/]name[:tag][@digest]
Extra Arguments Denylist¶
The following dangerous Docker flags cannot be passed through extra_args:
| Blocked Flag | Reason |
|---|---|
--privileged | Grants root-equivalent access to host |
--cap-add | Adds Linux capabilities |
--security-opt | Modifies seccomp/AppArmor profiles |
--device, --device-cgroup-rule, --gpus | Exposes host devices outside the typed GPU policy |
--pid, --network, --userns, --ipc, --cgroupns, --uts | Selects or shares host namespaces outside typed networking and IPC fields |
-v, --volume, --mount, --volumes-from | Bypasses mount canonicalization and the host-path allowlist |
-e, --env, --env-file | Bypasses typed environment handling and secret masking |
-p, -P, --publish, --publish-all | Bypasses loopback-only typed port publication |
Both --flag=value and split --flag value forms are rejected. Docker's attached and compact short forms, such as -v/:/host and -itv/:/host, are rejected as well.
Layer 2: Mount Security¶
The mount allowlist enforces a deny-by-default policy for filesystem access.
Validation Steps¶
-
Symlink resolution: Host paths are canonicalized (all symlinks resolved) to prevent traversal via symbolic links.
-
Blocked pattern check: Every path component is checked against the blocked pattern list (case-insensitive):
Pattern What it protects .sshSSH private keys .gnupgGPG private keys .envEnvironment files with secrets .awsAWS credentials .azureAzure service principal credentials .gcloudGoogle Cloud credentials .dockerDocker registry credentials .kubeKubernetes cluster credentials -
Allowlist root check: The canonical path must be a descendant of at least one explicitly allowed root. No path is permitted unless an administrator has added a root that covers it.
-
Container path sanitization: Container-side mount paths are restricted to
/workspace/extra/{name}. Paths containing..are rejected. -
Non-main groups forced read-only: Agents in non-main groups always receive read-only mounts, regardless of the requested mode.
Validate a Mount Before Running¶
curl -X POST http://localhost:8001/api/v1/container/mount/validate \
-H "Content-Type: application/json" \
-d '{
"hostPath": "/Users/alice/projects/myapp",
"containerPath": "/workspace/extra/myapp",
"readOnly": true
}'
Response on success:
{
"allowed": true,
"canonicalHostPath": "/Users/alice/projects/myapp",
"message": "Mount validated successfully"
}
Response when blocked:
{
"allowed": false,
"canonicalHostPath": "/Users/alice/.ssh",
"message": "Path contains blocked pattern: .ssh"
}
Layer 3: Environment Sanitization¶
Containers receive a strictly controlled environment. All host environment variables are stripped, and only an approved subset is passed through or overridden:
| Variable | Behavior |
|---|---|
ANTHROPIC_BASE_URL | Passed through from host (points to credential proxy) |
ANTHROPIC_API_KEY | Always overridden with placeholder (CREDENTIAL_PROXY_PLACEHOLDER) |
TZ | Passed through from host for correct timezone |
All other environment variables are not available inside the container. This prevents accidental or malicious leakage of host secrets.
Layer 4: Credential Proxy¶
The credential proxy is the primary mechanism for preventing API key exposure.
How It Works¶
sequenceDiagram
participant A as Container Agent
participant P as Credential Proxy (localhost:3001)
participant U as Upstream API (api.anthropic.com)
A->>P: POST /v1/messages\nAuthorization: Bearer CREDENTIAL_PROXY_PLACEHOLDER
P->>P: Validate placeholder
P->>P: Replace with real API key
P->>U: POST /v1/messages\nAuthorization: Bearer sk-ant-...
U-->>P: Response
P-->>A: Response (forwarded) Proxy Modes¶
| Mode | Header Replaced |
|---|---|
| API Key | x-api-key: CREDENTIAL_PROXY_PLACEHOLDER → x-api-key: {real_key} |
| OAuth Bearer | Authorization: Bearer CREDENTIAL_PROXY_PLACEHOLDER → Authorization: Bearer {real_token} |
Upstream URL Validation¶
Upstream URLs are validated at registration time:
- Must use HTTPS (or HTTP for
localhost/127.0.0.1development only) - Cannot target the blocked cloud metadata endpoints
169.254.169.254andmetadata.google.internal
The current validator does not block every RFC1918 address or resolve hostnames before registration. Treat Management API access as privileged, and do not register an upstream URL you do not trust.
Proxy Status¶
Layer 5: IPC Permissions¶
Containers communicate with the host via a file-based IPC channel. The IPC system enforces group-level permissions to prevent cross-group interference.
Permission Model¶
| Action | Main Group | Normal Group |
|---|---|---|
| Send message to any chat JID | Allowed | Blocked — own chat JID only |
| Create task for any group | Allowed | Blocked — own group only |
| Receive follow-up messages | Allowed | Allowed |
| Read global instructions | Allowed | Allowed |
When a normal-group container attempts a cross-group action, the attempt is logged as a security violation and the IPC command is rejected.
Security Events¶
Every IPC permission check generates a security event:
{
"id": "evt-abc123",
"severity": "violation",
"category": "ipc_permission",
"message": "Container 'aigo-squad-grp1-session42' attempted cross-group send to 'tg:9876'. Blocked.",
"containerId": "aigo-squad-grp1-session42",
"groupName": "grp1",
"timestamp": "2026-03-15T10:30:00Z"
}
Layer 6: Security Audit¶
A periodic security audit (every 120 seconds) verifies that running containers match their expected configuration.
Audit Checks¶
- Environment variables: Verifies
ANTHROPIC_API_KEYis the placeholder, not a real key - Mount points: Verifies mounts match the approved list
- No-new-privileges: Verifies the
no-new-privilegessecurity option is set (Docker only)
Audit Log¶
Security Event Log¶
The security event log retains the last 500 security events:
Security Recommendations¶
Minimum Permissions Principle
- Only add the smallest set of host directories to the mount allowlist that agents actually need.
- Use read-only mounts whenever the agent does not need to write.
- Never add home directory roots (e.g.,
/Users/alice) to the allowlist — be specific.
Protect the Management API
The Management API exposes all container configuration including credential mappings. Always: * Enable API key authentication in API > Access keys. * Bind the Management API to localhost only (default) unless you have a specific need for remote access. * Use TLS if remote access is required.
Audit Log Retention
Security events are retained in an in-memory ring buffer of 500 events. For compliance purposes, export events regularly using the audit log endpoint and store them in a persistent log management system.