Skip to the content.

Osmantic/ODS — security scan

Repository: Osmantic/ODS Commit scanned: 2e8446ecd9481b098c6f418a587f42d95e3c7e2d Scan date: 2026-07-25 Disclosure status: public — post-only (strict-norm: private-reporting SECURITY.md + SECURITY_AUDIT.md receipts + commercial backing)

Summary

Severity Count
Critical 0
High 20
Medium 53
Low 0
Info 0

Total findings: 73 (0 real after curation)

ODS — the Osmantic Deployment System — turns a PC, Mac, or Linux box into a private, self-hosted AI server: local model inference, a ChatGPT-style web UI, a control dashboard, voice/agents/workflows, RAG, and image generation, wired together over Docker (Ollama, Open WebUI, n8n, ComfyUI, and friends). That is a wide, dangerous-looking surface — a service that manages Docker, secrets, network exposure, OAuth credentials, and host-side installer state. For an appliance like this the three questions are: is the dashboard’s reverse proxy an SSRF/host-spoof pivot?, are the service-to-service credentials handled and logged safely?, and is the SQL that fronts the token-usage store injectable? All three close, and they close because ODS already did the work — it ships its own SECURITY_AUDIT.md with B1/B2 fix markers that show up as comments in the very files the scanner flagged.

Top findings (all curated out)

1. SQL “highs” in token-spy — parameterized-identifier FP, and a textbook one

2. detect-insecure-websocket ×4 — scheme-preserving, plus two non-code matches

3. run-shell-injection ×5 — non-privileged / maintainer-only workflow triggers

4. dynamic-proxy-host ×5 (nginx) — hardcoded internal upstream, Bearer-auth injected

5. logger-credential-disclosure ×7 — the secret’s path is logged, never its value

Patterns observed

This is a security-mature project scanned, not a project being audited for the first time. ODS ships a real, non-default SECURITY.md that asks for private vulnerability reporting, a SECURITY_AUDIT.md that tracks historical findings + remediation + regression evidence, an operator-hardening guide (ods/SECURITY.md), and an installer-trust doc. The fingerprints of that discipline are everywhere in the code the scanner flagged: B1/B2 fix markers in nginx.conf, a defense-in-depth regex on a hardcoded SQL identifier, 0o600 on every generated secret, path-only logging, and an inject-token.js branch literally commented “Auto-token injection disabled to prevent gateway-token disclosure.” The scanner’s 20 “highs” are the hardening itself, twice over.

The residuals are all operator-gated and already inside the project’s own threat model. Three worth naming, none a filing: (1) the dashboard SPA carries four react-router advisories (open-redirect / XSS / constructor-injection), but the dashboard is localhost-bound (nginx listen 3001; server_name localhost;) and Bearer-gated — a frontend dependency refresh, reachability-gated (Kiln lockfile-coverage shape); (2) the model-serving images (bark, llama-server, llama-sycl) run as root — common for GPU images, localhost-scoped, and SECURITY.md already flags LAN exposure as high-risk; (3) GHA action tags use mutable refs (pin to SHA). ODS’s own SECURITY.md states the same posture I’d write in a hardening note — “ODS defaults to localhost-bound services… do not expose a default install directly to the public internet without an additional security review.” When the maintainer’s threat model and the scanner’s residuals agree, there’s nothing to file.

The count is a shape, not a risk signal — again. 73 findings, 0 real, on one of the richer surfaces in the series (Docker orchestration + secrets + a credential-injecting reverse proxy + a token-usage SQL store). The clusters that looked scary — five SQL highs, five “dynamic proxy hosts,” seven “credential leaks” — are the three questions above, each answered correctly in the code.

Notes on the tool

Disclosure timeline

Reproduce

git clone https://github.com/Osmantic/ODS /tmp/scan-target
python scanner/run_scan.py --repo /tmp/scan-target --reports-dir ./reports/osmantic-ods --min-severity medium