Security

How we secure Asset Hub

Asset Hub is self-hosted: your prompts, assets and provider keys live on your own infrastructure, never ours. That only matters if the software itself is trustworthy — so it's hardened by default, reviewed end to end, and every protection is pinned by an automated test suite.

Encrypted at rest Proxy-isolated sharing SSRF-guarded Non-root containers 100+ security tests

Data & access isolation

Your assets are yours — enforced on every request, not just in the UI.

Per-user ownership

Every asset, set and job is scoped to its owner. Cross-user access is rejected across items, groups and jobs — no reading another account's work by guessing an ID.

Filesystem confinement

Serving assets is confined to the storage root; path-traversal attempts can't escape it to reach other files on disk.

Signed, expiring URLs

Files and avatars are delivered through short-lived, HMAC-signed links backed by a dedicated signing key — never guessable public paths.

Admin-gated operations

Library scans, provider configuration and user management require admin — and admin status is re-read from the database on every request.

File integrity monitoring

Every stored file's checksum is recorded and re-verified by a daily background sweep — silent corruption or tampering is flagged for an operator instead of going unnoticed.

Isolation, audited

Every API route was audited for cross-tenant access, and dozens of automated isolation scenarios pin the result — one account can't see another's assets, jobs, keys or even tag names.

Sharing & public surface

Share an asset with anyone — without ever exposing the app itself.

Isolated share proxy

Public share links are served by a dedicated, credential-less proxy — no database access, no app secrets. It forwards only share traffic, strips any client credentials, and answers 404 to everything else; anonymous visitors never touch the main app.

Expiring, revocable links

Every share is an unguessable random token with optional expiry, revocable at any moment. Revoked, expired and unknown links all return the same 404 — a dead link reveals nothing about what exists.

Password-protected shares

Shares can require a password, stored only as a bcrypt hash. Unlocking exchanges it for a short-lived proof — the password never appears in a URL — and guessing is strictly rate-limited at the proxy.

Self-contained viewer

The public share page makes zero third-party requests — every viewer library ships with the proxy, pinned by a strict Content-Security-Policy, and share pages are excluded from search indexing.

Authentication & sessions

Standard, revocable auth for both people and machines.

Tokens & API keys

JWT bearer tokens for the UI and revocable personal API keys for machine clients such as a Unity plugin.

Rotating, revocable sessions

Refresh tokens rotate on every use — a replayed old token is rejected. Logging out revokes the current session; changing the password revokes every active session of the account.

OIDC / SSO

Standards-based single sign-on with one-time authorization-code exchange, nonce and email_verified checks; the JWT algorithm is pinned.

Brute-force protection

A password policy plus rate limiting on login, registration and password changes. New accounts need explicit admin approval.

Secrets & configuration

Safe defaults, and it fails closed rather than running insecurely.

Provider keys encrypted at rest

API keys entered in the admin UI are encrypted before they touch the database, with a dedicated encryption key.

Fails closed on weak secrets

The app refuses to start on the shipped default, an empty, or a too-short signing secret — it won't silently run in an insecure state.

Separate keys per purpose

Distinct secrets for session auth, secret encryption and asset-URL signing — a single leak doesn't cascade.

Safe defaults

Self-signup off by default, a trusted-host allowlist, an explicit CORS origin list, security headers, and generic errors that don't leak internals.

Network & infrastructure

Locked down at the edges and inside the containers.

SSRF protection

Every outbound request — to a provider or a reference image — is validated, and access to private and link-local networks is blocked by default.

No open inbound ports

Production runs behind a reverse proxy and tunnel; the database and internal services are never directly exposed.

Non-root containers

Services run as an unprivileged user with dropped Linux capabilities, no-new-privileges and process limits.

Optional edge protection

Deployment guidance includes bot- and abuse-mitigation at the edge for public-facing instances.

Testing & review

The guarantees above are verified, not just intended.

Automated security suite

100+ security-focused tests run in continuous integration and lock each protection in place, so a future change can't quietly regress it.

Reviewed end to end

The codebase was put through a full security review and hardened across authentication, access control, file handling, secrets and infrastructure.

Parameterized everywhere

Database access uses bound parameters (no SQL injection) and subprocess calls use argument lists (no shell injection).

Header/bearer auth

Authentication rides on headers and bearer tokens rather than cookies, so there's no classic CSRF surface to exploit.

Reporting a vulnerability

Found a security issue? Please report it privately through GitHub Security Advisories on the repository rather than opening a public issue. We'll acknowledge your report and work with you on a fix before any disclosure. Responsible reports are always welcome.

Asset Hub is open-source software you run yourself. These measures describe the protections built into the project; the security of any given deployment also depends on how it's configured and operated (strong secrets, kept-updated hosts, a properly configured reverse proxy). See the project README and configuration notes for hardening guidance.