Do not open a public issue for a security problem. Use GitHub's private vulnerability reporting on the Security tab. If you cannot use GitHub, open an issue that says only that you have a security report and how to reach you — no details in the issue itself.
Please include:
- what the problem is and what an attacker can do with it;
- the exact version, image tag or commit you tested;
- a reproduction, if you have one;
- whether you intend to publish it, and on what timeline.
We will acknowledge a report within a few days and tell you what we found. We prefer to fix first and publish afterwards, and we will credit you unless you ask us not to.
Decis is pre-1.0. Security fixes land on master and in the next release; only the most
recent release image is supported. Pin a versioned tag (...-v0.3.0 is the current one)
rather than a moving tag in production.
Decis is an inference server. What it protects is access to the model and to the content you send it; it is not a sandbox for untrusted model weights.
- Bearer authentication on every
/v1/*endpoint./healthzand/readyzare intentionally open so orchestrators can probe without a secret. - Unsafe defaults fail closed. With no
DECIS_API_KEYconfigured, the server refuses to start on a non-loopback address unlessDECIS_ALLOW_NO_AUTH=1is set explicitly. Binding loopback is always allowed. - Authentication runs before body validation. An unauthenticated request with a malformed body is 403, not 422, so validation details do not leak to an anonymous caller.
- Constant-time token comparison, and 401 versus 403 distinguishes an invalid credential from a missing one.
- Bounded request size (
DECIS_MAX_REQUEST_BYTES, 2 MiB by default) and a bounded wait for the engine (DECIS_REQUEST_TIMEOUT_MS, 8 s by default). A request that arrives mid-load is refused rather than queued forever. - No mutable business state on the request path.
POST /v1/systemoneis a pure function, because the official SDK retries it automatically. - The container runs as a non-root user and needs no external services.
- Model weights are loaded from a fixed resolution order; a local directory wins over the network, so a deployment can run without outbound connectivity.
The playground attaches the API key server-side and proxies /v1/systemone, so anyone who
can reach its port can use the configured model. Publishing it is the same decision as
publishing the engine's port, without even a token prompt. On a host you do not fully trust,
bind it to loopback:
DECIS_PLAYGROUND_HOST_PORT=127.0.0.1:8080- Set
DECIS_API_KEYand never commit.env(it is in.gitignore). - Prefer a reverse proxy that terminates TLS in front of Decis; the server speaks plain HTTP.
- Keep the playground off a public interface unless you mean to expose the model.
- Give the engine container a memory limit sized from measurement — peak memory is several
times the weight files (see
docs/performance.md). - Use versioned image tags in production, not
latest. - Watch for
X-TypeSafe-Retry-Countin the logs: a client retrying means the server is failing or too slow.
- Vulnerabilities in upstream models or packages (Laya, kev, torch, transformers) — report those to their projects; we will still bump our pins when a fix lands.
- Denial of service from a caller who already holds a valid API key. Decis is not a multi-tenant rate limiter.
- A model returning a wrong or biased answer. That is model behaviour, not a server vulnerability.