Security & Trust Model
Same-UID trust boundary
Section titled “Same-UID trust boundary”All local IPC in xmsg takes place over Unix domain sockets in $XDG_RUNTIME_DIR/xmsg/ (or the
per-user Darwin temporary directory from getconf DARWIN_USER_TEMP_DIR on macOS when
XDG_RUNTIME_DIR is unset):
- The runtime directory is created and verified at mode
0700, owned by the running user’s UID, withhttp.sock,agent.sock, andregister.sockbound at mode0600. - Startup verifies directory and socket ownership and refuses symlinks before binding.
- Every connection on
http.sock,agent.sock, andregister.sockchecks kernel-attested peer credentials (SO_PEERCREDon Linux,getpeereidandLOCAL_PEEREPIDon macOS) and drops any connection whose UID does not equal the server’s UID prior to protocol framing.
Attribution vs. isolation within one UID
Section titled “Attribution vs. isolation within one UID”Within a single OS user (UID), identifying a caller by its process ancestry on agent.sock and
http.sock is attribution, not a hostile security boundary:
- It prevents accidental cross-session or cross-harness misattribution and lets tools derive the caller’s session address automatically.
- It does not stop a same-UID process with shell access from inspecting or impersonating another session running under that same UID.
- Hard security boundaries in
xmsgare separate OS UIDs (for example, running separate tiers or services under distinct users or pods), mTLS peer certificates (/fed/v2), and per-peer authorization policies (allow,principals,targets,from). - Anyone holding a
message_id(from a log or forwarded text) can read that message’s replies viareplies.
Per-harness attestation & identity derivation
Section titled “Per-harness attestation & identity derivation”Among non-adversarial same-UID processes, xmsg verifies each harness’s lifecycle so sessions do
not collide or spoof one another:
- Claude Code: Discovered from
~/.claude/sessions(or repeatable--sessions-dir). Process liveness and start time are verified against/proc/<pid>/stat(orproc_pidinfoon macOS, matching the UTCps -o lstarttimestamp recorded in<pid>.json). Duplicate conversation IDs receive deterministicX~2,X~3fork claims ininstance_claims. - Codex (Linux): Verified via ancestor executable attestation
(
--codex-exe), an open<H>/thread-writer-locks/<P>.lockdescriptor under a configured--codex-home<H>with a continuousinotifylease watch, and boundedO_NOFOLLOWrollout header verification. Runtime MCP calls extractsessionId,threadId, andturn_idstrictly fromparams._meta, never from model-controlledarguments.- Shared app-server daemon note: When multiple Codex root sessions share a single per-home
app-server daemon under the same UID, they share that daemon’s process ancestry and writer-lock
descriptors; running
codex --no-daemongives each root its own owner process. All Codex delivery paths prepend a fixed untrusted-peer-data preamble outside escaped message bodies.
- Shared app-server daemon note: When multiple Codex root sessions share a single per-home
app-server daemon under the same UID, they share that daemon’s process ancestry and writer-lock
descriptors; running
- Antigravity: Verified via ancestor executable attestation
(
--agy-exe) and an open file descriptor to<presence_dir>/<conversation_id>.lockmatched by device and inode(dev, ino)(plus/proc/locksexclusiveFLOCKverification on Linux). - Pi, opencode, and Hermes:
Admitted on
register.sockviaSO_PEERCRED/getpeereidUID verification;xmsgmints a fresh UUID v4 per registered session and scopes all tool calls andcontinues/subagentframes to the owningregister.sockconnection. - Services (
svc): Admitted onregister.sockby verifyingSO_PEERCREDUID and matching canonical/proc/<pid>/exeagainst--svc-exe <NAME>=<PATH>(or--leaf-principalin--leafmode). Executable resolution fails closed on deleted binaries ((deleted)) or changed profile symlinks.
Envelope sanitization & breakout defense
Section titled “Envelope sanitization & breakout defense”- Printable-ASCII anonymous
from: Unattested HTTPfromstrings are restricted to printable ASCII (0x20..=0x7E) and cannot contain:,/, or@, ensuring an anonymous caller can never imitate an attestedid@nodeaddress and is always rendered as<from> · anon@<node>. - Label sanitization: Instance labels strip quotes, angle brackets, control characters, and
newlines, replace non-ASCII characters with
_, drop any label containing@or·, and cap length at 64 characters. - XML breakout defense: Transport envelopes escape attribute double quotes (
") so message metadata or sender labels cannot break out of<cross-session-message>tags. - No-symlink file ingestion: Every path that reads harness state on disk (
~/.claude/sessions, Codex rollouts, Antigravitytranscript.jsonl) validates UUID/subagent identifiers first and walks directories withopenat(..., O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK), rejecting symlinks, FIFOs, sockets, and non-EUID files.
Provenance is not instruction authority
Section titled “Provenance is not instruction authority”An attested sender address answers where a message came from. It does not authorize the receiver to run commands, reveal secrets or override its user’s instructions. Display labels remain sender-provided descriptions. A message from another session, service, Matrix room or hosted model is peer data, including when its transport is authenticated.
The Codex delivery preamble states this distinction explicitly. Apply the user’s instructions and normal tool permissions before acting. Structural envelope escaping prevents a message from breaking the wrapper; it does not prevent semantic prompt injection.
flowchart LR X["External Matrix or hosted client"] --> E["Bridge or gateway: external authentication and policy"] E --> U["xmsg node: UID boundary"] U -->|"mTLS and peer policy"| V["Remote xmsg node"] V --> A["Agent receives peer data"] A --> P["User instructions and tool permissions decide action"]
Within one UID, xmsg does not isolate hostile local processes from each other. It also does not make peer text safe to execute or supply end-to-end outside-service authorization: external bridges and gateways own their outside-facing boundaries.
Palettes adapted from Catppuccin (Macchiato) (MIT), Tokyo Night (Apache-2.0), gruvbox (MIT), Catppuccin (Latte) (MIT), Rosé Pine (Dawn) (MIT).