How we handle security reports and vulnerability disclosure
We shipped three security releases in five days. Here is how a report reaches us, what we promise when one does, and how you can check that a release really came from us.
Between 27 September and 1 October we shipped three security releases, each with a public advisory. ATLAS runs commands on your machine, so when it gets something wrong there, you should hear about it from us, quickly and in plain words.
why a private channel
When someone finds a flaw in software, the order of events matters. If the details become public before a fix exists, everyone running the software is exposed and there is not much they can do about it. The practice that avoids this is called coordinated vulnerability disclosure. The CERT guide to the subject defines it as "the process of gathering information from vulnerability finders, coordinating the sharing of that information between relevant stakeholders, and disclosing the existence of software vulnerabilities and their mitigations to various stakeholders, including the public."
In practice the report arrives privately, the fix is prepared before anyone else learns the details, and then the fix and its description are published together, so the public first hears of the problem when the fix is ready. Two international standards cover the two halves of this work. ISO/IEC 29147 is about receiving reports and publishing advisories, and ISO/IEC 30111 is about what happens in between. Our security policy and our incident-response guide follow the same division.
how to report
Please report privately, through a GitHub security advisory. A public issue would show the details to everyone before a fix exists. The advisory form opens a draft that only you and the maintainers can see, and the fix can be prepared together there, in a private copy of the repository.
A useful report says which part of ATLAS is affected (the proxy, the terminal interface, the command-line tool, the pipeline service, the lens, the sandbox or the install scripts), gives the steps that show the problem, and describes the impact for a single user running ATLAS on their own machine.
If you cannot use the advisory form, open a minimal public issue that says you need a private channel, and leave every detail out. If someone posts details in public by mistake, we ask them to move to a private advisory, and we hide the issue.
what we promise
You can expect an acknowledgment within a week. After that, our targets depend on how serious the problem is.
| Severity | What it covers | Acknowledge | Fix |
|---|---|---|---|
| critical | an escape from the sandbox or workspace reachable from model output, code execution through a verified download, credential theft from a default install | 48 hours | a patch release as soon as possible, in days |
| high | the same classes needing a non-default setup, or a way around artifact verification | 72 hours | the next release, within 30 days |
| medium | hardening gaps with real but bounded impact | one week | a scheduled release |
| low | defence-in-depth improvements, documentation fixes | one week | the backlog, with an issue |
Confirmed critical and high reports stay private until a fixed release is out, with a target of ninety days at most from confirmation. Ninety days is also the deadline Google's Project Zero gives vendors to ship a fix. During that time, a fix may land on our development line with a neutral commit message, so that the change itself does not announce the problem. We agree the advisory text with the reporter, and we credit them unless they ask us not to. When a report warrants one, we request a CVE identifier through GitHub.
ATLAS is a small project, so those targets are best effort. We work to meet them and cannot guarantee them.
Security fixes go to the current release, and to the release before it for ninety days after a new one ships. Today, that means the 3.1 line.
what is in scope
ATLAS is a local tool for a single user. Its services listen only on your own machine, and there is no hosted component. The policy draws its line around that model.
In scope are a way out of the workspace or the sandbox, an escape from the sandbox container, a model or artifact download that is not verified, a secret written to disk or to a log, and a flaw in the install scripts.
Out of scope are problems that need ATLAS's ports to be exposed to a network you do not trust, isolation between different users of one machine, and a model persuaded into writing bad code. That last one is a real problem. It is the reason the sandbox and the review of changes exist.
The policy says: "Model-generated tool calls are treated as untrusted input … If you find a way around either boundary, that is exactly the kind of report we want." It also lists the current limits of those boundaries, so that a report can be weighed against what is actually enforced.
what happens after a report
The first hour of a response has four steps, in this order: write it down, rate it, contain it, and tell the people who need to act. Writing it down comes first on purpose. The guide asks that logs, workflow runs and images be kept, because "they're the evidence."
The fix lands on the development line and ships as a patch release. If the development line is not ready to release, the fix goes out as a hotfix from the release branch and is then merged back. All three of the recent releases shipped that way. A security release uses the normal pipeline, with its signed tags and test-gated images, and adds a changelog entry and the advisory.
Once the fix is out, the advisory is published and users are told what they need to do. Within two weeks, a short written review is posted as an issue: what happened, why, and what changes. If the policy changes, the change is recorded as a decision in the repository.
A bad release is corrected in the open. A release tag cannot be moved or deleted, by anyone, so the fix is a new release, with the old one marked as withdrawn. A bad model file is withdrawn by changing its pinned hash in a patch release. Installers check every download against those hashes, so the bad file stops installing anywhere.
the last three
| Advisory | Severity | Affected | Fixed in |
|---|---|---|---|
| GHSA-5hvw-59r4-7rcq | medium | 3.1.0 to 3.1.3 | 3.1.4 |
| GHSA-c3p6-m657-h629 | high | up to 3.1.4 | 3.1.5 |
| GHSA-m9w4-p32x-chx9 | low | 3.1.0 to 3.1.5 | 3.1.6 |
In order, their titles read: "Commands and deletions could run without approval, and file search could read credential files"; "Tool argument names in another letter case could bypass the workspace check and the command deny-list"; and "Command policy skipped commands behind a prefix or a nested shell."
The three releases came on 27 and 29 September and 1 October. Each advisory was published with its fix, within about an hour of the release. The release notes for 3.1.5 record that its new tests fail on the unfixed version and pass on the fixed one. We want every security fix to ship with a regression test like that.
The third advisory was reported and fixed by Rendegou, who is credited in the advisory, the changelog and the release notes. The first two list no outside reporter.
If you run any version before 3.1.6, please upgrade.
how to check a release is ours
A fix only helps if you can trust the release that carries it, so the tag, the images and the models can each be checked.
Release tags are signed with a key listed in the repository's allowed_signers file, and an automated check rejects any tag that is unsigned or signed by another key. In a checkout of the repository, you can verify it yourself:
git -c gpg.ssh.allowedSignersFile=.github/allowed_signers verify-tag v3.1.6
The container images are signed too, by the build itself, with no long-lived key that could be stolen. This is Sigstore's keyless signing. The build proves its identity to a certificate authority, receives a short-lived certificate naming the exact workflow and tag that produced the image, signs with it, and records the signing in a public transparency log. So checking a signature tells you which build made the image:
cosign verify \
--certificate-identity https://github.com/inferstep/ATLAS/.github/workflows/build-images.yml@refs/tags/v3.1.6 \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/inferstep/atlas-proxy:3.1.6
The atlas upgrade command checks these signatures before it applies an upgrade, when cosign is installed, and a signature that fails stops the upgrade with the previous release still in place. If cosign is missing, the upgrade logs that it could not check and continues. Installing cosign takes about a minute, and it is worth it.
Models are covered differently. The default model, and the lens and steering files, are pinned to a SHA-256 hash in the model registry. A download that does not match is deleted and the install fails, and atlas model verify re-checks an installed model against the registry at any time. Some other models in the registry have no hash yet, and the installer says so.
If you want the most careful install, you can also pin it to a release: fetch the install script at the tag, pin the checkout to the signed tag, and pull the matching signed images. The setup guide shows how.
what is not there yet
Releases do not yet carry signature bundles that would let anyone verify offline (#252). Tags are signed and checked, but individual commits are not yet (#197). Releases are signed with a single key today, and there should be a second (#198). The weekly image vulnerability scan reports its findings without stopping a release.
sources
- SECURITY.md, the incident response guide, the release process, and releases 3.1.4 to 3.1.6.
- Householder, Wassermann, Manion and King (2017), The CERT Guide to Coordinated Vulnerability Disclosure, Software Engineering Institute.
- ISO/IEC 29147:2018, vulnerability disclosure, and ISO/IEC 30111:2019, vulnerability handling processes.
- OpenSSF, Guide to coordinated vulnerability disclosure for open source projects.
- Google Project Zero, vulnerability disclosure policy.
- GitHub Docs, About repository security advisories.
- Sigstore, Signing overview.
run it yourself
ATLAS is open source under AGPL-3.0, and it runs on your own hardware.