-
Notifications
You must be signed in to change notification settings - Fork 2
security
Active contributors: Zachary BENSALEM
Fleet is a local, single-user tool. It has no account system, no multi-user authorization, and no remote deployment mode. The web process can run model-generated commands with the user's permissions, so process isolation is for lifecycle and recovery, not a security sandbox.
graph LR
B["Browser on loopback"] -->|"HTTP, NDJSON, SSE"| S["Fleet web server"]
S -->|"Local daemon socket"| D["Prime Agent daemon"]
D --> W["Session workers and IPython"]
W --> F["Filesystem, shell, network<br/>as the user"]
The browser/server boundary is protected by loopback binding, request-header checks, typed validation, and path containment. The server-to-runtime boundary is a local process boundary but not a privilege boundary. The runtime can access whatever the user can access.
scripts/prime-agent-web-launcher.mjs enforces local-only access twice:
-
--hostaccepts only127.0.0.1,localhost, or::1; - every request must have a loopback
Hostheader and, when present, a loopbackOriginheader.
Non-loopback requests receive 403 Loopback requests only. The API has no
bearer-token authentication or TLS. This is intentional for the local
single-user product and means that any process able to reach the port is
trusted with the workspace.
Workspace reads use resolveContainedWorkspacePath in
web/server/src/workspace-paths.ts. It canonicalizes the root, resolves the
requested relative path, rejects absolute and .. escapes, resolves symlink
targets, and checks containment again. web/server/src/workspace-file.ts
limits reads to 1 MiB and treats NUL-containing content as binary instead of
returning it to the browser.
The workspace tree in web/server/src/workspace-tree.ts limits recursion to
10 levels and 100 entries per directory. The launcher applies a separate
containment check before serving files from dist/web/client. The root is
fixed for the process: POST /api/workspace/root returns 405, while
GET /api/workspace/browse returns 410 and directs callers to the project
directory picker.
Project registration can use an opaque directory token. The
ProjectRegistry in web/server/src/project-registry.ts validates and
expires those tokens rather than asking the browser to infer a project path
from an identifier. web/server/src/handlers/projects.ts owns project
registration, rename, removal, browsing, and session fork requests.
This picker is intentionally different from workspace file reads: it may browse directories outside the current workspace in order to choose a new root. The selected root is then fixed for the process.
OpenUI HTML is validated on the server by
validateAndNormalizeOpenUIHtmlArtifact in
web/protocol/src/openui-artifact.ts before it is stored by
web/server/src/handlers/chat-openui-artifact.ts. The renderer in
web/design/src/components/openui/html-artifact.tsx validates it again before
rendering.
The validator caps documents at 1 MiB, injects the canonical CSP, and rejects
forms, frames, external resources, inline event handlers, unsafe URL schemes,
network APIs, downloads, and top-level navigation attributes. The renderer
uses an iframe with sandbox="allow-scripts" and srcDoc, keeping the
artifact in an opaque origin without app same-origin access.
PRIME_AGENT_RUNTIME.json pins prime-agent 0.9.1 to a specific R2 tarball
and SHA-256:
573bce0cd004fc62052e9a924089941b7f39266ab71e66a94c85a1f9d35835ba
scripts/check-prime-agent-runtime.mjs cross-checks that URL in
web/server/package.json, packages/fleet-web/package.json, and
pnpm-lock.yaml. With PRIME_RUNTIME_VERIFY_TARBALL=1, it downloads the
archive and verifies both the manifest SHA-256 and lockfile SHA-512.
pnpm-workspace.yaml adds a seven-day release-age gate, a no-downgrade trust
policy, restricted install scripts, and explicit security overrides. The
known upstream extract-zip 2.0.1 advisory is documented in
docs/guides/upstream-runtime.md because no patched version is available to
override in Fleet.
- The release pipeline uses separate least-privilege CircleCI contexts for
release-PR preparation and GitHub release assets. npm publication uses a
short-lived CircleCI OIDC token with the npm registry audience, not a
stored
NPM_TOKEN. - Provider credentials are managed by Prime Agent's
AuthStorage. Fleet'sweb/server/src/prime-provider-env-map.tssupplies provider labels and environment names; credentials are not part of browser responses. -
redactSessionLabelSecretsinweb/protocol/src/session-label.tsremoves common API-key and token shapes before transcript-derived labels reach browser chrome. - Error responses pass through
safeErrorMessageinweb/server/src/wrap-api-handler.ts, which removes local filesystem paths from browser-facing messages.
- Authentication and multi-user access: the product serves one local user.
- TLS on loopback: the launcher is zero-config and local-only.
- Sandboxed agent execution: worker and kernel isolation does not prevent filesystem, shell, or network access available to the user.
Report vulnerabilities through GitHub private vulnerability reporting as
described in SECURITY.md; do not open a public issue for security reports.
The same trust boundaries are shown in the system architecture.