Security Policy - thekaveh/atlas GitHub Wiki
9.8. Security Policy
1. Reporting a Vulnerability
This is a personal-project repository. Please open a private security advisory via the GitHub repository's Security tab → Report a vulnerability. Do not file public issues for security-sensitive findings.
Include in the advisory:
- Revision: the commit SHA you ran (
git rev-parse HEAD) and, if you pinned one, the release tag. §2 says which revisions receive fixes. - Enabled SOURCE values: the
*_SOURCEsettings from your.envfor every service involved, with keys, tokens, and passwords removed. - Exposure boundary: where the affected service is reachable from. That is the local machine only, a private LAN or homelab network, or a public hostname published through Cloudflare Tunnel. For a public hostname, include the Cloudflare Access policy in front of it (§6).
- Minimal reproduction: the smallest steps, request, or proof of concept that shows the issue, shared only inside the private advisory.
Triage uses these to score reachability under the posture and tier rules in §3 and §4. Responses and fixes are best-effort; there is no committed acknowledgement or fix timeline.
2. Supported Revisions
Security fixes target the current tips of develop and main. A fix lands
on develop by pull request and reaches main through the Gitflow
promotion; main is the rolling tip described in
Releasing & version tags.
Release tags (vMAJOR.MINOR.PATCH, cut on main) are pinnable checkpoints,
not supported release lines. A pushed tag is immutable, and only a new tag
corrects a released checkpoint. Historical tags, including v0.1.0, and older
commits are not supported and receive no backported fixes. To pick up a fix, a
consumer moves its pin to a later tag that contains it. If no such tag exists
yet, it pins a main commit that does.
3. Project Posture
Atlas is a self-hosted, single-tenant engineering platform for generative AI, ML, and data engineering workloads. It is intended to run on a developer's local machine or a private homelab network. Its default configuration has no public web surface or shared deployment.
The optional Cloudflare Tunnel service deliberately creates a public edge. Every exposed hostname must use a least-privilege Cloudflare Access policy and an explicit Kong origin Host override. It must also keep the destination route's own authentication and authorization controls.
This posture shapes how we triage Dependabot and CVE alerts: vulnerabilities are scored by (severity × tier × reachability), not raw CVSS alone.
Reachability triage must include enabled SOURCE values and edge configuration. A route that is private in the default stack is internet-reachable when an operator maps it through Cloudflare Tunnel. This is true even though the application container itself still publishes no public listener.
4. Operational Tiers
| Tier | Manifest examples | Where it runs |
|---|---|---|
| A — Container-shipped | services/docling/provider/gpu/requirements.txt, services/parakeet/provider/gpu/requirements.txt, services/backend/app/app/requirements.txt, services/jupyterhub/build/requirements.txt, the various */Dockerfiles |
Docker image; ships to every user that runs start.sh (when the corresponding service is enabled) |
| A — Host CLI | bootstrapper/pyproject.toml |
Local Python venv on every contributor's host |
| B — Host install (opt-in) | services/docling/provider/localhost/pyproject.toml, services/parakeet/provider/mlx/requirements.txt |
Only installed when user picks the localhost/mlx provider variant and runs uv sync / pip install -r themselves |
Tier-A vulnerabilities are fast-tracked. Tier-B vulnerabilities are documented; users who pick the localhost path own the deployment risk on their host.
5. Reachability Triage Examples
transformers.TrainerRCE (CVE-2026-1839, medium): unreachable. We usetransformerstransitively via easyocr for inference only and never instantiateTrainer. Dismissed astolerable_risk; the rationale is in the 2026-05-14 remediation report (§8).urllib3decompression-bomb (CVE-2026-44431/44432, high): reachable. The bootstrapper makes outbound HTTPS calls (Docker registry, Hugging Face, Ollama catalog). Floor-bumped immediately to clear.torch.loaddeserialization RCE (CVE-2025-32434, critical) in the formertorch==2.4.1JupyterHub image: remediated. JupyterHub now ships the coordinated PyTorch 2.13 CPU pair and matching PyTorch-Geometric wheel set.torch.jit.scriptmemory corruption (GHSA-rrmf-rvhw-rf47): remediated. Docling GPU and JupyterHub now use Torch 2.13.0; the Jupyter PyG family resolves torch-geometric from PyPI and carries no compiled accelerator. The unused torchaudio, the legacy scatter/sparse/cluster extensions, andpyg_libwere removed rather than held on vulnerable, unavailable, or single-CDN companion releases.- Ragas multimodal URL-processing SSRF (CVE-2026-6587): unreachable. Backend exposes only a closed enum of text metrics and never imports the vulnerable multimodal collection; Jupyter use is operator-authored code.
- DiskCache pickle deserialization (CVE-2025-69872): unreachable in shipped
Backend routes.
diskcache==5.6.3is an unpatched transitive dependency of Ragas and Instructor, but Atlas never constructs their optional disk-cache adapters. Exploitation also requires write access to a cache directory that a later process reads. Keep this exception only while those adapters remain unused; remove it when upstream publishes a patched release or the transitive dependency disappears. - Parakeet GPU model loading: operator-controlled. The GPU runtime lock
pins NeMo
3.0.0and Transformers5.16.1. Atlas loads only thePARAKEET_MODELchosen in process environment at startup. Transcription requests cannot supply or change a model repository. - setuptools source-distribution exclusion bypass (CVE-2026-59890): remediated. Shipped compiled graphs and the Docling localhost lock now resolve setuptools 83.0.0 or newer.
- Local Deep Researcher runtime graph: hash-pinned. The generated lock
enforces reviewed floors for Click, langchain-classic, LangSmith, and Soup
Sieve. Refresh and byte-equivalence tests preserve those floors. Hash
pinning does not establish current vulnerability status. Run
uv run --project bootstrapper python -m scripts.audit_runtime_locksbefore deployment to check for advisories published after the pins were reviewed.
6. Public Edge Requirements
Enabling CLOUDFLARED_SOURCE=container changes the default trust boundary.
Before publishing a hostname, configure its Cloudflare Access application and
restrict the allowed identities. Set the Origin HTTP Host Header to the exact
Atlas Kong alias documented for the service. Keep the route's Kong and
application authentication enabled. Review logs and rotate the tunnel token
if it is exposed.
7. Automated Scanning
Two container-image gates run in services-lint.yml on every pull request:
-
Build-validation (Dockerfile + requirements.txt installability)is a required check. Despite its name it builds no local Dockerfile. It verifies the two commit-pinned remote build contexts against their reviewed base-image index digests. It also Trivy-scans the manifest-owned remote images whose declarations changed in the pull request. That includes an image a Compose line now names by a different${VAR}. Local Dockerfile builds run in the Final-image scan below. -
Final-image scan (local Compose and init images)builds every local Compose and init image and fails on any HIGH or CRITICAL finding. A finding does not stop the run. The job scans every image and fails at the end with the list of images that did not pass. A Trivy error stops it at once.It reports on every run but is not yet a required check while the fleet still carries findings. Its promotion to the required set is tracked in #1002.
Findings that cannot be fixed at the pinned version are excepted in
.trivyignore.yaml. Every exception is scoped to an exact package version or
path, carries a review statement, and expires. The scan refuses to run on a
broad, duplicate, or stale entry. A test fails any statement that names no
owning service.
A package-version scope matches that version in every scanned image, not only the one its statement names. Reconciling each row against per-image scan output is tracked in #1289. Reachability triage for those exceptions follows the same tier and edge rules as §3 and §4.
8. Remediation Reports
Historical Dependabot remediation reports were retired from the working
tree in commit ebdc9d4 (the docs/security/ folder used to host them).
The reports are accessible only through git log / git show:
git log --oneline -- docs/security/ # list the reports' history
git show ebdc9d4^:docs/security/2026-05-14-dependabot-remediation-report.md
git show ebdc9d4^:docs/security/2026-05-06-dependabot-remediation-report.md
- 2026-05-14 report — 77 alerts triaged, 62 phantom, 15 actionable
- 2026-05-06 report — 102 alerts triaged, Phases 1.1/1.2/1.3 landed