Repository navigation
Conversation
…emory with other processes) The install security check (#508) refuses ipc: host without privileged consent, and the read-only prod dry run of its Start check flagged this one bundle. llama-server is a single process (--no-mmap, weights in GPU memory through Vulkan) and uses no POSIX shared memory with other processes, so the host IPC namespace is not needed; the private /dev/shm keeps shm_size 16g as headroom. Manifest gets a version (1.0.1). Claude-Session: https://claude.ai/code/session_01N9fXzvNy8rCEArj1y5p6fp
…ll security check
- bundleUp/bundleStop run only model bundles (repo manifest inference: true), with the
gateway's allowlisted compose env (never its secrets or COMPOSE_*), and every up is
checked by the shared model check first, on exactly the invocation up runs (-f, cwd,
env). The check runs before any mutex sibling is evicted, so a refused start never
costs the box its resident model. A refusal is a ComposeGuardError; nothing starts.
- What model bundles need is declared, not loopholed: manifest host_grants (gpu,
shm_size, env_files, path_env), read from the repo manifest only, never for community
bundles. GPU devices, gpus, GPU reservations, runtime nvidia and NVIDIA_* env need
host_grants.gpu; /dev/shm above 1 GiB needs host_grants.shm_size; env_file outside the
bundle only for a declared, existing file in ~/.crow/env (inference: true no longer
opens any host file).
- 4b, embed and vllm-cuda-{embed,rerank,vision} drop ipc: host (their private /dev/shm
is shm_size). The 35B's is dropped by its own PR; this one must merge after it.
- composeEnv moves to compose-guard.js (routes keep their wrapper); loadComposeModel
takes the caller's -f file and cwd.
- Grants and versions: 4b, embed, vllm-cuda-* 1.0.1; 35B 1.0.2 (grants only); sdxl,
vllm 1.0.2; ollama, localai 1.0.1. Docs (en/es) list host_grants.
Claude-Session: https://claude.ai/code/session_01N9fXzvNy8rCEArj1y5p6fp
… clearer refusal wording Code review I1: the model is built with --no-env-resolution, so NVIDIA_VISIBLE_DEVICES / NVIDIA_DRIVER_CAPABILITIES in an env_file never showed up in it. Each env_file the check admits is now read for them. A refused stop says "stop"; comments no longer name hosts and say that operatorRoots relaxes nothing until the host-path allowlist uses it. Claude-Session: https://claude.ai/code/session_01N9fXzvNy8rCEArj1y5p6fp
… and only a small regular file Re-review N1: the NVIDIA_* scan opened every env_file path before the outside-path refusal, so env_file: /dev/zero (or a FIFO) could block and crash the gateway. The scan now runs inside the admission loop, after the path is accepted, and reads only a regular file of at most 1 MiB (anything else is refused). N2: it matches the KEY: value form Compose accepts, and format: raw keeps quotes literal. Claude-Session: https://claude.ai/code/session_01N9fXzvNy8rCEArj1y5p6fp
…ng file, no container-writable file Final security pass on the install check's env_file handling: - Any NVIDIA_ mention in an admitted env_file (any case, separator, quoting or line ending) needs the gpu grant. The line regex it replaces could disagree with Compose's dotenv parser (a lone CR, a NEL prefix). - The file is stat'ed before it is opened (a device or FIFO is never opened), opened non-blocking, checked to be the same regular file, and read up to 1 MiB from the descriptor. - A missing env_file is refused unless it is marked required: false. - An env_file under a read-write bind or a bind-device volume of the same project is refused: a container could swap it before Compose reads it. Claude-Session: https://claude.ai/code/session_01N9fXzvNy8rCEArj1y5p6fp
…ass the check; operatorRoots now count (#524) Stacked on #509, so the test's ipc: host exception for the 35B is dead and is removed: all model bundles in the repo must pass the install security check as the orchestrator runs it. The preflight comment said the check ignores ctx.operatorRoots; since #524 the host-path allowlist uses them (a mount outside Crow's home must sit under one, and the floor applies). Claude-Session: https://claude.ai/code/session_01N9fXzvNy8rCEArj1y5p6fp
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up (a) to #508, recorded in queue item 30. Stacked on #509, so merge #509 first. Once #509 lands, this branch is rebased onto main, so only its own commits remain.
The problem.
servers/gateway/gpu-orchestrator.jsstarted model bundles withdocker compose upfrom the repo's compose file. That path skipped the install security check (compose-guard.js), and it passed the gateway's whole environment, secrets included, to Compose.What changes
inference: trueand names the same id. A provider row synced from the fleet can name any id, so the row alone isn't trusted.upis checked first by the shared model check. The check sees the exact model thatupwill apply: the same-ffile, the same working folder, and the gateway's allowlisted compose env (no secrets, noCOMPOSE_*).stopuses the same invocation.ComposeGuardErrorand nothing starts.host_grantsfield listsgpu,shm_size,env_filesandpath_env. It is read from the repo manifest only, never from a community bundle or an installed copy.gpus, GPU reservations,runtime: nvidiaandNVIDIA_*env needhost_grants.gpu./dev/shmabove 1 GiB needshost_grants.shm_size.env_fileoutside the bundle is allowed only if it is declared and sits in~/.crow/env.inference: trueno longer opens any host file by itself.path_envkeys (for exampleLLM_CACHE) come from the bundle's.envin the checkout and are passed as the check's operator roots. Since fix(bundles): outside Crow's home, extensions mount only folders the owner allowed #524, a mount outside Crow's home must sit under one of them, and the floor still applies: system folders, home dot-folders and~/bin, a git checkout, and anything containing Crow's home stay refused.NVIDIA_mention in an admitted env_file needs the gpu grant. This covers any case, separator, quoting or line ending.required: false.ipc: host. The 4b, embed,vllm-cuda-embed,vllm-cuda-rerankandvllm-cuda-visionbundles drop it and keep their private/dev/shmatshm_size. Each is one container, so the host IPC namespace only matters for sharing with other containers, and there are none. fix(models): the 35B bundle drops ipc: host (follow-up to #508) #509 drops the 35B's.composeEnvmoves tocompose-guard.js. The routes keep a thin wrapper.vllm-cuda-*bundles: 1.0.1.host_grants.⚠ Merge inside a scheduled model window.
upof either container recreates it. That happens at their next start, not at merge time: a resident model is never re-upped.docker compose configonly) ran this branch's check on the three crow model bundles with that host's real.envvalues. All three pass and come out with a private IPC namespace.Tests
tests/compose-guard.test.js: grants, env_file handling, and every repo model bundle passing the check as the orchestrator runs it.tests/gpu-orchestrator-compose-guard.test.js: covers these cases.inference: truebundles.check-port-allocationpasses.Not in this PR
https://claude.ai/code/session_01N9fXzvNy8rCEArj1y5p6fp