Security overview
What runs where, what leaves your network (no telemetry, no customer data), identity and access, request handling, audit, secrets, licensing and supply chain, for a procurement or security review.
Applies to self-hosted ShakerScan Enterprise 0.2.0-beta.23 (public beta, September 2026). Every statement below describes behaviour that exists in the product and was exercised in acceptance testing. Items marked not yet are not claimed.
What runs where
Everything runs inside the customer's environment on a Docker host the customer operates.
| Component | Source | Network position | Data it holds |
|---|---|---|---|
Public engine (api, worker, ui, postgres, redis) | Open-source ShakerScan images, digest-pinned, AGPL-3.0 | Private Compose networks; no published ports | Targets, credentials for authorized targets, findings, evidence, HTTP transactions |
| Enterprise gateway | Private image from the vendor registry, digest-pinned and signed | The only service reachable from the customer network, behind Caddy TLS | Identities, sessions, service tokens, audit metadata, MFA secrets (sealed), licensed-slot ledger |
| Caddy | Public image, digest-pinned | Ports 80/443 | TLS certificates |
The gateway proxies every request to the engine. Workers cannot reach the API directly; the API and workers use separate database-facing networks; the storage initializer runs with no network. No container mounts the Docker socket. The gateway runs read-only as an unprivileged user with all capabilities dropped.
Data that leaves the environment
No customer data is sent anywhere by the Enterprise gateway: no telemetry, no license activation or check-in, no usage reporting. The only request the gateway makes on its own is a read-only fetch of the public engine release catalog from GitHub, when an administrator opens or requests an engine update; it sends nothing about the installation. The public engine's own outbound behaviour (target traffic, optional AI providers configured by the customer, model endpoints) is the customer's configuration and network policy. The generated deployment disables automatic retesting, attack-surface discovery defaults and the AI operations router unless the customer turns them on.
The complete outbound list for a generated deployment, for an egress allowlist:
| Destination | Component | When |
|---|---|---|
registry-1.docker.io, auth.docker.io, production.cloudflare.docker.com (Docker Hub) | host Docker | pulling the pinned public engine images at install and upgrade |
ghcr.io, pkg-containers.githubusercontent.com | host Docker | pulling the Enterprise gateway image with the customer's read token |
api.github.com, raw.githubusercontent.com, github.com, release-assets.githubusercontent.com (repository andriyze/shakerscan) | gateway, installer, updater | read-only fetch of the public engine release catalog and the pinned engine installer, at install time and when an administrator opens or requests an engine update |
install.shakerscan.com | host | the public engine installer, only on the manual install and restore paths |
api.github.com and the Sigstore public-good services (Rekor transparency log, TUF root) | cosign and gh on the host | verifying the gateway signature, SBOM attestation and engine build attestations at install and before an upgrade |
acme-v02.api.letsencrypt.org and the ACME HTTP challenge inbound on port 80 | Caddy | only when no customer certificate was given to prepare |
| the OIDC issuer's discovery, authorization, token, JWKS and userinfo endpoints | gateway | sign-in, when OIDC is configured (SHAKERSCAN_ENTERPRISE_OIDC_ENDPOINT_HOSTS pins them) |
| the scan targets the customer authorizes | engine workers | scanning; the workers pin each target's resolved addresses for the run |
| AI provider or model endpoints the customer configures | engine | only if configured; off in the generated deployment |
| a private interactsh server the customer configures | engine | only if configured; the tools run with -no-interactsh otherwise |
The scanner tools run with update checks disabled; templates and vulnerability databases are
baked into the pinned images, so nothing is fetched at scan time. Proxy environment variables
are ignored by the gateway's and the engine's HTTP clients by design (trust_env=False), so no
proxy can ever sit between the gateway and the engine. A corporate proxy is configured
explicitly instead (prepare --outbound-proxy): Caddy's ACME client and the gateway's calls to
the identity provider go through it; the engine's target traffic does not and must be allowed
directly at the firewall; image pulls follow the Docker daemon's proxy configuration.
Identity and access
- Single sign-on: OpenID Connect authorization code with PKCE, one-use state bound to the
browser, nonce check, signed ID-token validation (RS256, ES256), exact issuer match, HTTPS-only
provider endpoints restricted to reviewed hosts. Requires the authorization-code flow with S256
PKCE, RS256 or ES256 ID tokens, and
client_secret_basicorclient_secret_post. Validated with Okta and Keycloak (Okta guide); other providers, such as Microsoft Entra ID, use the same standard flow. Two-step verification for provider accounts is the provider's policy. An administrator configures single sign-on in the console (issuer, client, sealed client secret, group-to-role table) and runs a test sign-in at the provider before saving; saved settings apply without a restart and are audited. - Admission: an identity is admitted by its exact subject or by a deliberate first-sign-in group-to-role mapping. Local role changes are authoritative; removing an IdP group does not remove local access (disable the identity in the console). No SCIM (not yet).
- Roles: viewer (read findings, evidence, scans, targets), operator (start scans, manage credentials and collections), admin (identities, tokens, audit, license). Enforced per request by method and path allowlists; unreviewed engine routes are denied.
- Local accounts: Argon2id password hashing, minimum 14 characters, throttled sign-in,
authenticator-app two-step verification with per-code replay protection. Policy can require
two-step verification for administrators or all local users; a required-but-unenrolled session
can reach only the enrollment screen. Ten single-use recovery codes, shown once, replace a lost
passkey or authenticator; the operator's server-side
reset-mfaandreset-passwordcommands remain the break-glass path. Accounts can be created by one-time invitation links, so the person chooses their own password; an administrator can issue a one-time password-reset code (shown once, valid for an hour) without ever choosing or learning the password. - Passkeys for local accounts: WebAuthn, user verification required, bound to the gateway's hostname, signature counters checked, single-use server-side challenges. A passkey satisfies the two-step policy on its own; an account with a passkey and no authenticator app cannot sign in with its password alone.
- Service tokens: issued to service identities, shown once, stored hashed, viewer or operator scope, at most 90 days, revocable individually, never able to administer or open the UI.
- Sessions: opaque server-side sessions,
__Host-secure cookies, one-hour absolute and fifteen-minute idle limits by default, bound to the password credential verified at sign-in. Role, password or factor changes revoke sessions. No provider back-channel logout (not yet).
Request handling
- Only reviewed request headers are forwarded; cookies, bearer tokens and forwarded-host headers never cross the gateway boundary. Upstream cookies are dropped.
- Browser mutations require a same-origin
Originheader; Enterprise administration also requires a CSRF token. Engine mutations must be JSON. - Evidence and other engine responses are served with a sandboxing Content-Security-Policy and an attachment disposition for non-JSON media, so downloaded evidence cannot execute as a page.
- Streaming responses re-check the session every two seconds and stop when it is revoked.
- Request and response sizes and upstream timeouts are bounded.
- Active work needs a target authorization on the engine. The gateway records it on the submitter's behalf, once per target, naming the operator or administrator; the audit shows who authorized which target and when. The engine's own gate still decides, and the gateway never fabricates a receipt id.
Audit
Administrative actions, sign-in outcomes, engine requests and responses (method and path, never bodies, query strings, tokens or passwords) are recorded with actor and timestamp, viewable in the console and exportable as NDJSON. The audit store is on the host and is not tamper-proof against a host administrator (remote streaming and retention policies not yet).
Secrets and keys
| Secret | Where | Protection |
|---|---|---|
| Passwords | Gateway state volume | Argon2id hashes only |
| Sessions, service tokens | Gateway state volume | SHA-256 digests only |
| Authenticator secrets | Gateway state volume | AES-GCM sealed with a 32-byte key kept on the read-only secrets mount, outside the state volume |
| OIDC client secret, CA bundle, license | Customer secrets mount, read-only | File permissions for the gateway user only |
| Target credentials, evidence | Public engine (PostgreSQL, results directory) | The public engine's own controls |
Identity backups are AES-GCM encrypted under a passphrase-derived key (scrypt) and include the MFA sealing key; restores are create-only and revoke every session and token.
Licensing
Offline. A license is an Ed25519-signed token bound to the installation id and verified against the vendor key embedded in the package. It limits concurrent scans; the gateway reserves a slot before each scan and refuses submissions beyond the allowance. Expiry blocks new scans only; sign-in, administration, existing results and cancellation continue. A customer-attested usage summary can be exported for renewal. No network licensing, no phone-home.
Supply chain
Enterprise images are built from a version tag by a CI workflow that runs the test suite,
start-tests the exact image, pushes it to a private registry, signs the digest with Sigstore
keyless signing and attaches an SPDX SBOM attestation. Publication fails before anything is
pushed or signed if the image has a fixed high or critical vulnerability (Trivy). Customers deploy by digest and can verify
the signature and SBOM with cosign before starting anything; the kit's verify.sh runs these
checks and the engine images' build attestations in one command, and the installer runs it. Engine images are pulled by digest
from the public release lock file.
Operations
Create-only deployment generation, an upgrade command that keeps data and refuses downgrades,
versioned state with pre-migration snapshots, and scripted backup and restore covering the engine
database, evidence, encrypted identity metadata and deployment files (restore drill executed on
2026-09-12). Single-process gateway; high availability (not yet). Kubernetes packaging (not yet).
An ECS Fargate evaluation layout exists and was exercised; it is not the supported production posture.
Known limitations to state in a questionnaire
One organization per installation, no project-level isolation between teams; no SCIM; no provider logout; audit is local only; HA and Kubernetes are not delivered; a single Linux Compose host (Ubuntu 24.04 LTS or 26.04, x86_64) is the supported target.