Security
How to report a problem, and what the design already assumes so you can tell the two apart.
On this page
Reporting a vulnerability
Do not open a public issue.
Use GitHub’s private reporting
form, or email
ovalenzuela@ainvirion.com with CRAne security in the subject if you would rather not
use GitHub. Include the version — crane status prints it — what you did, what happened,
and what you expected. A proof of concept is welcome and never required.
This is a single-maintainer project. Expect acknowledgement within five working days, best effort, no paid support and no response-time guarantee. Fixes ship in a new tagged release rather than as a patch to an old tag, so upgrading is the remediation path.
Coordinated disclosure, and credit in the advisory unless you would rather not be named.
Decisions that are not findings
Some behaviour looks like a vulnerability and is a documented choice. Report it anyway if you disagree — this is just the answer you will get.
| Behaviour | Why |
|---|---|
| One shared token, no accounts, no roles | CRANE_API_TOKEN is the whole authentication story. ADR 0002 covers why, and what would have to change first |
| An unauthenticated mode exists | For localhost only. A bare 0.0.0.0 bind is refused without either the token or an explicit override |
| The database is not encrypted at rest | It is a plain SQLite file on purpose, openable with any SQLite browser. Controlling who can read the file is the host’s job |
| An unfixed base-image CVE | The release gate fails on anything HIGH or above that has a fix. A finding Debian marks unfixed in every stable suite cannot be resolved by rebuilding, so it does not block a release — it gets named instead. Where the affected code is something CRAne never calls, it gets deleted rather than accepted: perl-base was removed from the image outright for that reason |
| Validators are not bundled | Each runs as a separate process the worker invokes. A flaw in a validator belongs to that project; a flaw in how CRAne invokes it, or in what it does with the output, belongs here |
In scope
Anything that reads or writes data it should not, escapes the intended process boundary, or leaks a credential:
- Authentication or authorization bypass on any route, the API included.
- Injection of any kind, template injection included, in the interface or in reports.
- Path traversal through an imported document, an export path, or a run directory.
- Credential exposure.
CRANE_GITHUB_TOKENis read from the environment at the moment of use and must never reach the database, a job’s parameters, a job event, an export, or a log line. - Anything that makes CRAne record an approval, a scope decision, or an exception that no human made. The line between an observed fact and a recorded decision is a security property here, not only a modelling one.
Hardening the deployment you run
The defaults are safe for a laptop. Four things matter once it is not one:
- Set
CRANE_API_TOKEN. Everything in Configure about exposure applies the moment the port is reachable by anyone else. - Publish the port to
127.0.0.1, not to every interface, unless a reverse proxy with TLS is doing the listening. There is no TLS inside the container. - Treat
data/as the sensitive artifact. It is the whole inventory in one file. Back it up somewhere with the same access controls, not somewhere convenient. - Scan the tag you are about to run, with
docker scout cvesor trivy, and rebuild or repull rather than pinning an old digest forever.
Licence
CRAne is Apache-2.0. The full text and the attribution notice travel inside the image:
docker run --rm --entrypoint cat ghcr.io/oscarvalenzuelab/crane:latest /app/LICENSE
docker run --rm --entrypoint cat ghcr.io/oscarvalenzuelab/crane:latest /app/NOTICE
Dependencies keep their own licences and are listed in NOTICE. The optional Postgres
backend pulls in an LGPL-3.0 library; it is an extra and is not installed in the
published images.