Skip to content

Add credential profiles with socket-per-profile isolation#7

Merged
calebfaruki merged 4 commits intomainfrom
credential-profiles
Mar 19, 2026
Merged

Add credential profiles with socket-per-profile isolation#7
calebfaruki merged 4 commits intomainfrom
credential-profiles

Conversation

@calebfaruki
Copy link
Owner

@calebfaruki calebfaruki commented Mar 18, 2026

Fixes #6

Summary

Credential profiles scope credentials and commands to individual containers. Each profile gets its own unix socket. The volume mount is the capability. No identity verification needed.

What changed

Profile system — daemon reads ~/.config/airlock/profiles/*.toml at startup, binds one socket per profile, refuses to start without at least one profile. Profile TOML supports optional command whitelist and env injection. Env merge order: command strip → profile inject → command harden (command hardening always wins).

Socket-per-profile — unified to ~/.config/airlock/sockets/<profile>.sock on all platforms. Replaced XDG_RUNTIME_DIR (ephemeral, cleared on reboot) with a durable path that survives airlock init. Stale sockets are cleaned on daemon start.

Socket permissions — explicit 0o600 after bind via bind_profile_socket() helper in lib.rs. No umask reliance. Daemon fails to start if chmod fails.

Audit loggingprofile field added to every log entry.

CLIairlock-daemon profile list and profile show <name>.

Init — creates profiles/ and sockets/ directories. Prints profile-aware mount example.

Tests — renamed from generic mod tests to promise names: idempotent_setup, audit_log, credential_isolation. New tests for socket permissions and stale socket cleanup.

Security model

Addresses two OWASP Agentic Top 10 (2026) risks:

  • ASI03 (Identity & Privilege Abuse) — credentials scoped per-profile. Container A's SSH key is invisible to Container B.
  • ASI07 (Insecure Inter-Agent Communication) — socket reachability is the authentication, enforced by the kernel. Explicit 0600 closes the host-side gap. No SO_PEERCRED, works on Linux and macOS.

Per-socket tokens were evaluated and deferred as "won't implement" — the container is a single trust domain, so a token colocated with the socket doesn't create a new security boundary.

Migration from v1

  1. touch ~/.config/airlock/profiles/default.toml
  2. airlock init
  3. Update docker run to mount ~/.config/airlock/sockets/default.sock:/run/docker-airlock.sock

Profiles scope credentials to individual containers. Each profile gets
its own unix socket — the volume mount is the capability. The daemon
reads ~/.config/airlock/profiles/*.toml at startup, binds one socket per
profile, and refuses to start without at least one profile.

Profile TOML supports an optional command whitelist and env var injection
for credential routing (SSH keys, AWS profiles). Env merge order is
strip → profile → command module, so command hardening always wins.

Adds profile field to audit log entries, profile list/show CLI commands,
and profiles/sockets directories to airlock init. Linux sockets use
$XDG_RUNTIME_DIR/airlock/sockets/, macOS uses ~/.config/airlock/sockets/.

Renames test modules from generic `mod tests` to promise names:
idempotent_setup, audit_log, credential_isolation.
XDG_RUNTIME_DIR is ephemeral (cleared on logout/reboot), so airlock init
couldn't durably pre-create the sockets directory on Linux. Stale socket
files are inert — connection refused, cleaned on next daemon start.

Replace InitConfig.socket_path (v1 single-socket vestige) with
sockets_dir. Remove all XDG_RUNTIME_DIR and /var/run branching from
init.rs and main.rs. Update docs to reflect a single path everywhere.
The socket file is the sole authentication mechanism per profile — any
process that can connect inherits that profile's credentials. Set mode
0600 explicitly after bind rather than relying on umask.

Extract bind_profile_socket() helper (remove stale file, bind, chmod)
into lib.rs so both the daemon and integration tests use the same path.
@calebfaruki calebfaruki changed the title Add credential profiles: socket-per-profile isolation Add credential profiles with socket-per-profile isolation Mar 19, 2026
@calebfaruki calebfaruki merged commit 1db1c07 into main Mar 19, 2026
2 checks passed
@calebfaruki calebfaruki deleted the credential-profiles branch March 19, 2026 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flat trust model lets every container inherit full host credentials (ASI03)

1 participant