Skip to content

Pre-V1 audit: security review and threat model #178

Open
5 of 6 issues completed
Open

Description

@siebe41

One of the audits to finish before 1.0. This issue tracks the security review; each finding is a sub-issue.

Scope

The six areas named for the audit, checked against the threat model in SECURITY.md:

  1. the dashboard's admin API and sign-in (tokens, session cookie, Host check, roles, trusted identity headers, gateway keys)
  2. CSRF (the same-origin check on writes, side-effecting GETs, CORS)
  3. the CLI connectors and every other place that starts a process or opens a URL
  4. the key ring (Data Protection, the secret file, ${env:} / ${secret:} references, masking)
  5. the desktop app's web-view bridge
  6. update-feed integrity (Velopack feed, publisher check, installers' update step)

Method

  • Read SECURITY.md, docs/dashboard.md, docs/host.md, docs/providers.md, docs/desktop.md and docs/enterprise.md.
  • Read the code: DashboardAccess, RouterDashboardEndpoints, SetupApi, EvaluationApi, TuningApi, GatewayGuard, RouterConfiguration (masking, reference rules, process settings), Secrets/*, KeyRing, OwnerOnly, Connectors/Cli/*, AnswerJudge, ServicePlatforms, Desktop/* (bridge, window, shell, updater, publisher check) and deploy/*.
  • Wrote one scratch unit check of the reference rules.
  • Ran the existing security tests (DashboardRole|Secrets|DashboardAccess|CliScratch|CliExecutable|Gateway|UpdatePublisher|DesktopUpdater|KeyRing|Session): 147 passed, 0 failed.

What held up

  • Tokens and gateway keys: compared in constant time (SHA-256, then FixedTimeEquals). Dashboard tokens need at least 16 characters and must differ from each other. Access is refused when a token reference does not resolve.
  • Session cookie: HttpOnly, SameSite=Strict, Secure over HTTPS, and HMAC-signed. Sessions are revoked on the server and the revocations are kept in SQLite.
  • Host check: guards against DNS rebinding.
  • TrustedIdentityHeader: believed only from a known proxy, and refused when repeated or given as a list.
  • Metrics role: works as an allow-list.
  • Same-origin check: applies to every non-GET and to GETs marked as writes.
  • Browser hardening: no CORS, a strict CSP with no inline script, frame-ancestors 'none'.
  • Masked secrets: a masked *** only restores a secret to the same destination.
  • CLI process start:
    • ArgumentList, no shell, and absolute-path resolution that skips relative PATH entries
    • .cmd, .bat and .ps1 refused, and the whole process tree is killed
    • an owner-only scratch parent, and the prompt sent on stdin
  • Key ring: 0700/0600 on Unix and DPAPI on Windows. Unencrypted keys are replaced.
  • Update feed: refuses plain HTTP.
  • Publisher check: guards against path traversal and uses WinVerifyTrust or codesign --deep --strict.

Threat model

Area Asset Attacker position Defence Verdict
1 Admin API prompts, config, routing web page in the browser Host check, same-origin on writes, no CORS, SameSite=Strict Holds
1 Admin API prompts, config, routing another local user or process loopback rules, process-setting and reference rules See sub-issues and private reports
1 Admin API dashboard, gateway another machine on the LAN tokens, sign-in throttle, sessions, gateway keys, known-proxy identity Dashboard holds; gateway keys and the groups header need hardening
2 CSRF writes web page Origin / Sec-Fetch-Site on non-GET and write-marked GETs Holds for writes; see private reports
3 CLI connectors subscriptions, child processes remote client; content in a prompt AllowRemoteClients, argv, scrubbed environment, private working directory, tools off Mostly holds; the scrubbed environment is a short deny-list
4 Key ring keys, secret file local user, backups, compromised backend Data Protection, owner-only files, masking, redaction Holds in the default profile directories; custom directories on Windows keep inherited ACLs
5 Web-view bridge the desktop app page script, a link in the web view same-router navigation check, a 3-action bridge Low risk; no scheme allow-list
6 Updates the installed app compromised feed or mirror HTTPS, Velopack hash from the same feed, optional publisher policy Integrity rests on GitHub unless the policy names a publisher

Reported privately

4 findings that could be used against a current install are not filed here. Following SECURITY.md, they go to private security advisories and will be published when they are fixed.

Not checked here

These need Windows or macOS machines and are covered by the hands-on pass:

  • WebView2 and WKWebView navigation behaviour
  • DPAPI
  • Authenticode and codesign

Also not checked:

  • Velopack's own hash-verification internals
  • the vendor CLIs' argument parsers
  • a full XSS pass over the dashboard scripts (spot-checked only: the h() escaping and the CSP)
  • prompted tool-call forgery, which is tracked in Make prompted tool calls harder to forge #111

Done when

  • Every sub-issue is closed or deliberately deferred past 1.0.
  • The private advisories are fixed and published.

Activity

  1. siebe41 commented on Oct 22, 2026

    @siebe41
    OwnerAuthor

    The XSS pass this audit left undone ("spot-checked only") is in draft PR #334. Every template interpolation and HTML sink in the dashboard scripts was traced to its source. Text from gateway clients, model backends, note files and the URL was escaped everywhere. Connector, profile and virtual-model names, which only an admin writes, went unescaped into form attributes; the CSP kept injected handlers from running. Those are now escaped. A new dashboard-e2e spec (xss.spec.js) puts an attribute-breaking marker into configuration names, a gateway request, note files, a discovered lineup and notices, and fails if any page turns it into markup or trips the CSP.

  2. siebe41 commented on Oct 22, 2026

    @siebe41
    OwnerAuthor

    New finding from the review of #262: #338. A packaged connector type that runs a program is trusted to enforce AllowRemoteClients, MaxConcurrency and MaxQueue itself. The router enforces none of them for packages outside this repository.

  3. added a commit that references this issue on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions