Skip to content

Security: codegeist-ai/codegeist-os

Security

docs/security.md

Security Requirements

The dedicated AI user is a security boundary, not merely a different home directory. The implementation must combine identity separation, least privilege, isolation, mediation, audit, revocation, and recovery.

These are requirements for future implementation. The repository currently has no NixOS configuration or implemented security control.

Version 1 Security Posture

The first integration milestone is deliberately not a general-purpose AI agent:

  • The human GNOME user and the AI execution user must be separate operating- system identities.
  • The AI identity must be non-root, non-login, absent from administrative groups, and limited to its own private state and empty smoke-test workspace.
  • Ollama must run as a separate restricted inference service, bind only to loopback in a private network namespace and open no host firewall port. It has no model in the base image and must not select, download, or import one. A trusted future installer or test harness may provide a catalog-verified payload to the registration unit; a route-filtering gateway backend is the only runtime client and exposes no model-management operations.
  • The offline ask smoke must run under the AI identity in a VM without external network access using an explicitly external test bundle that is absent from the production VM and ISO closures.
  • Accelerator device access is granted only to the active restricted inference or speech worker through a trusted resource controller, not directly to the AI or human account.
  • Speech requests are accepted only from the configured human desktop UID over a permission-restricted Unix socket with peer-credential verification. The AI, inference, worker, and unrelated UIDs cannot invoke the broker or runtime APIs.
  • Speech input is limited to one explicitly staged WAV or FLAC file per operation. Live microphone capture is not part of Version 1.
  • Diarization uses anonymous labels local to one file. Speaker identification, voiceprint enrollment, persistent speaker embeddings, and voice cloning are prohibited in Version 1.
  • No human-facing general AI launcher, broad file share, desktop control, credential access, MCP integration, or privileged action is part of Version 1.
  • The live ISO does not inventory hardware for model ranking, select a model, download a payload, or persist model state. Those are future installer actions requiring human control.

The current Codegeist CLI includes local file and shell tools and does not yet implement the permission broker required by this design. Installing the binary does not make it safe to run in a human user's home or trusted project. Until a mediated execution path exists, the OS must use it only in an isolated AI-owned workspace for controlled verification.

Least Privilege

  • Create the AI user as a separate non-root UID with no default administrative group membership or unrestricted sudo path.
  • Deny capabilities by default and grant only named operations required for an approved use case.
  • Keep grants narrow in target, action, data exposure, and duration.
  • Prevent the model, prompts, downloaded content, and tool output from changing authorization policy directly.
  • Separate policy decisions from model inference and treat model output as untrusted input.
  • Reserve catalog updates, hardware compatibility decisions, model ranking, payload import, and persistent model deletion for non-AI administrative code.

Filesystem Access

  • Give the AI user a separate home and private runtime directories.
  • Deny human-user homes, system secrets, removable media, and sensitive service data by default.
  • Use explicit mediated shares for individual files or directories instead of broad home-directory access.
  • Define ownership, write limits, conflict handling, deletion protection, and revocation for every shared path.
  • Avoid following attacker-controlled links or mount changes across boundaries.
  • A non-model broker must use held directory descriptors and descriptor-relative openat2 resolution, verify the opened input is a caller-owned regular file with one link, and obtain a read lease that excludes concurrent writers. It records metadata before and after copying, rejects changes, and validates and hashes only the completed broker-owned copy before giving workers read-only access.
  • Reject symlinks, hard-link surprises, special files, unexpected containers, unknown request fields, and files outside configured size and duration limits.
  • Create an unnamed result with O_TMPFILE through the held caller-owned output directory descriptor, copy and revalidate the result on that filesystem, sync it, set caller ownership and bounded mode, and publish it with descriptor- relative linkat(AT_EMPTY_PATH) only after intermediate cleanup. Accept only a bounded single-component basename with no slash, . or ..; reject an existing destination or an output filesystem without the required primitive.
  • Delete the sealed source copy, normalized audio, tensors, embeddings, and staging files before success is reported and on every failure path. Version 1 has no broker-side source retention option.

Credentials

  • Never expose human keyrings, SSH or signing agents, browser sessions, cloud credentials, private keys, or reusable administrator tokens to the AI user.
  • Prefer narrowly scoped brokered operations over handing credentials to a model process.
  • Bind temporary credentials to an operation, target, and short lifetime.
  • Make revocation possible without recreating the human account or reinstalling the system.

Devices

  • Deny cameras, microphones, input devices, removable storage, raw disks, and other sensitive devices by default.
  • Assign accelerators explicitly to the active inference or speech worker and account for driver, DMA, firmware, device-memory residue, denial-of-service, and cross-process isolation risks.
  • Display or record active device grants and revoke them without granting root to the AI user.
  • Keep microphone devices denied even though file-based STT is enabled.
  • Use the Intel iGPU for the human GNOME session on the reference profile. Do not claim service-UID isolation as hardware tenant isolation on an RTX A2000, which has no MIG partitioning.
  • Returning A2000 allocation to the idle baseline does not prove device-memory sanitization. Until an evidenced reset or scrub boundary exists, treat all sequential A2000 inference and speech workers as one accelerator trust domain and make no confidentiality claim between them.
  • Treat each Intel, AMD, NVIDIA, Qualcomm, GPU, NPU, x86_64, or aarch64 profile as unverified until its OS driver, device isolation, telemetry, cleanup, and recovery gates pass.

Processes And Resources

  • Prevent inspection, tracing, signaling, or modification of human-user and privileged processes.
  • Constrain process count, memory, CPU, storage, and accelerator usage so the AI workload cannot make the system unrecoverable.
  • Isolate temporary files, IPC, service sockets, environment variables, and session buses.
  • Define deterministic behavior for crashes, resource exhaustion, and runaway workloads.
  • Serialize Ollama, STT, diarization, and TTS through a trusted accelerator resource controller. The root-owned controller launches transient cgroups, grants profile-specific devices only to the active unit, and permits one atomic backend/model-variant lease at a time. Inactive service UIDs have no static accelerator group membership.
  • Clear service-owned accelerator work and release model allocations on completion, cancellation, timeout, or service failure.
  • Treat 10 GiB as a provisional A2000-profile acceptance ceiling until the physical or passthrough gate measures it, not as a current result, universal requirement, or hardware partition. Use the maximum observed by a pinned NVML sampler running at no more than 10 ms intervals and runtime allocator high-water marks, and require at least 2 GiB below GPU-reported usable memory. On startup, reconcile recorded state against actual transient units, cgroups, device grants, processes, and NVML allocation. Block new leases after controller or worker failure until that evidence proves return to the idle baseline.
  • Store operation data on size-limited tmpfs, disable broker and worker core dumps and hibernation, and use no persistent plaintext swap. Scavenge abandoned operation directories before the broker accepts requests after restart.

Network Access

  • Deny unrestricted network access by default.
  • Grant destination, protocol, direction, and duration explicitly for approved workloads.
  • Treat remote responses, downloaded models, prompts, and tool instructions as untrusted content.
  • Make active network grants visible and revocable, and log policy decisions without recording secrets or unnecessary personal data.
  • Deny all network address families to speech workers and deny Ollama all non-loopback traffic in its private namespace. Give only the trusted registration unit and route-filtering gateway backend access to Ollama's private loopback listener. Disable pyannote telemetry with PYANNOTE_METRICS_ENABLED=0 in addition to network denial.
  • Test denied egress from the service contexts while the human desktop retains normal connectivity; taking the whole test machine offline is not sufficient evidence of service isolation.
  • Deny human and AI access to Ollama itself. A Codegeist-compatible front adapter runs under a separate UID and listens only inside the transient ask unit's private network namespace. It forwards to the route-filtering backend over a permission-restricted Unix socket authenticated with SO_PEERCRED; the AI receives no gateway secret and cannot open that socket. Treat the backend as part of the trusted computing base because it can reach raw Ollama. It must fix the installed catalog-selected model tag and reject pull, create, copy, delete, arbitrary-model, and all other non-inference requests.
  • Do not use the NixOS Ollama model-loader path for Version 1 because it performs registry downloads after service startup. Register only a catalog-verified external test payload or future installer-managed payload without external network access from the inference boundary.

Human Approval And Privilege

  • Require human approval for access to personal data, credentials, sensitive devices, persistent system changes, and elevated operations.
  • Present the exact action, target, data exposure, and side effects before approval.
  • Do not transform one approval into a reusable shell, token, group membership, or unlimited policy exemption.
  • Keep a non-AI path for denial, cancellation, and emergency shutdown.

Audit

  • Record capability requests, policy decisions, human approvals, execution outcomes, revocations, and security-relevant failures.
  • Protect audit data from the AI user and separate integrity evidence from model output.
  • Minimize personal and prompt content in logs while preserving enough context for investigation.
  • Define retention, export, review, and clock-integrity requirements before claiming auditability.
  • Record speech artifact versions, opaque operation identifier, anonymous speaker count, timing, and outcome without storing raw audio, transcript content, speaker embeddings, or voiceprints by default.

Catalog And Artifact Supply Chain

  • Accept only immutable per-architecture Codegeist releases and one OS-owned shared catalog with cryptographic hashes recorded in the OS artifact pin.
  • Require the shared catalog to record the approved logical LLM release, upstream source, training inputs, transformations, every LLM and speech runtime variant, quantization, evaluation, architecture/backend compatibility, resources, licenses, and every released file checksum.
  • Treat SafeTensors, GGUF, release archives, manifests, and converters as untrusted supply-chain inputs until independently verified.
  • Apply the same pin, hash, provenance, license, and offline requirements to every STT, diarization, alignment, VAD, TTS, tokenizer, codec, and voice file.
  • Keep all LLM and speech payloads outside production VM and ISO closures. Base images may contain only reviewed catalog metadata and runtimes.
  • Permit only the future installer/model manager or explicit test harness to import a catalog-approved payload. Codegeist, the AI, Ollama, inference gateway, speech broker, and workers receive no selection or download authority.
  • Keep externally injected test bundles outside release derivation dependencies and prove that removing them restores the model-unavailable state. Before use, verify the bundle-level manifest and complete dependency closure, then mount or copy it read-only into root-owned sealed test state inaccessible to human and AI UIDs.
  • Treat gated model access conditions as additional release terms. Build-time access through a token does not by itself permit redistribution.
  • Acquire gated files only through the isolated prefetch process in docs/artifact-contract.md. Only official bundle-production or test derivations may consume the reviewed files from a credential-free immutable distribution location; production VM/ISO derivations must not reference them.
  • Keep model weights and generated OS images out of Git.
  • Keep Hugging Face, Gitea, GitHub, cache, and signing credentials out of Nix expressions, store paths, logs, images, and release metadata.
  • Do not publish an official model bundle until all base-model, dataset, derivative, and redistribution rights are recorded and accepted. An uncleared bundle does not block publication of the model-free base image.
  • Rebuild and rerun model-free VM/ISO, affected external-bundle, and hardware- profile checks for every update listed in the canonical trigger set in docs/artifact-contract.md.

Rollback, Disablement, And Recovery

  • Provide a clear way to stop AI processes, disable the AI account and services, revoke grants, and block network access.
  • Preserve human login and administrative recovery when AI components fail.
  • Preserve boot, human login, diagnostics, and recovery when no model has ever been installed or installed model state is missing or corrupt.
  • Support rollback of system configuration independently of future model/runtime updates. Installer-owned model rollback and deletion remain a separate later contract.
  • Define offline or rescue recovery that does not require the model, network, or normal AI services.
  • Before the first live-image release, test disablement and model-independent recovery from compromised credentials, corrupted transient state, policy failure, and resource exhaustion. Test recovery from an unbootable installed update before an installer or installed-system release.

Public Repository Boundary

Every Git ref is mirrored publicly to GitHub. Do not commit credentials, personal data, private host information, restricted model artifacts, signing keys, or security-sensitive deployment state.

There aren't any published security advisories