Trust center
What protects your credentials, and what doesn't yet.
Every control below says what is built, the release it ships in and the code and tests that prove it. Gaps link the open issue that tracks them.
Download the security review (PDF)
- 43Controls shipped
- 12Partial
- 3Planned
Sneakers-PAM holds no certifications. It is open-source software you run yourself, not a hosted service, so there is no SOC 2 report or ISO 27001 certificate to share. The controls are mapped to SOC 2, ISO 27001, NIST SP 800-63B and OWASP ASVS so your own reviewers can test them.
Sneakers-PAM is in prerelease (v0.1.0-rc.4). Expect the gaps listed here to change from one release candidate to the next.
Architecture
How it fits together.
The services and where each trust boundary sits, then the appliance from firmware to product. The security review has the low-level design.
Controls
Controls by area.
Shipped means the code is on a published tag. Partial means it's built with a named gap. Planned means it isn't built yet.
- Architecture and trust boundaries
- Keys and encryption
- Identity, MFA and sessions
- Authorization and approvals
- Reveal, check-out and rotation
- Audit trail
- MCP and machine API
- Appliance platform
- Supply chain and releases
- Backup and recovery
- Logging, monitoring and health
- Secure development and vulnerability handling
Architecture and trust boundaries
Small services with one entry point, a database each, and an allow-list on every internal call.
Single entry point for people and machines
Shipped in v0.1.0-rc.1Clients reach Sneakers only through the gateway (two GraphQL endpoints, one for browser sessions and one for tokens), the MCP bridge and the web apps. Backend services aren't exposed outside the cluster.
SOC 2 CC6.1, CC6.6 · ISO 27001 A.8.20, A.8.22 · ASVS V1.4.1
Evidence (2)
- doc sneakers-gateway/README.md
- code sneakers-release/charts/sneakers-lib/templates/_resources.tpl · per-service NetworkPolicy
Workload identity on every internal call
Shipped in v0.1.0-rc.1Each service-to-service gRPC call carries the caller's projected Kubernetes ServiceAccount token. The callee checks issuer, audience, expiry and a per-method caller allow-list, and refuses to start without an issuer configured. Only the gateway may pass an end user's identity.
SOC 2 CC6.1, CC6.3 · ISO 27001 A.5.15, A.8.5 · ASVS V1.4.4, V4.1.3
Evidence (4)
- code sneakers-vault/internal/server/workloadauth.go
- test sneakers-vault/internal/server/workloadauth_tokens_test.go · TestWorkloadAuthAcceptsAndRefusesTokens
- test sneakers-audit/internal/grpcsvc/callers_test.go · TestCallerAuth_UnlistedPodIsRefusedEvenWithAValidToken
- test sneakers-gateway/cmd/gateway/backend_test.go · TestBackendDialOptionsSendTheWorkloadTokenOnEveryCall
Open work: sneakers-gateway#27 Workload identity for machine-API callers
Network policy per call-graph edge
Partial since v0.1.0-rc.3The Helm charts install a NetworkPolicy for each service that admits only its declared callers, plus policies for the bundled identity provider and database. The install test checks that blocked pods are blocked. Outbound traffic isn't restricted by default.
SOC 2 CC6.6 · ISO 27001 A.8.20, A.8.22
Hardened containers
Shipped in v0.1.0-rc.3Every service runs as non-root with a read-only root filesystem, no privilege escalation, all capabilities dropped and a seccomp profile. Each chart's values schema rejects an install that turns these off.
SOC 2 CC6.8 · ISO 27001 A.8.9 · ASVS V14.1.1
Evidence (1)
Keys and encryption
Envelope encryption of every secret field, a rotating key ring, and what is and isn't encrypted on the wire.
Envelope encryption of every secret field
Shipped in v0.1.0-rc.1Each secret has its own 256-bit data key from the OS CSPRNG. Every field value is sealed with AES-256-GCM under a fresh 96-bit random nonce, with the field name bound as associated data, so a value can't be moved to another field undetected.
SOC 2 CC6.1, C1.1 · ISO 27001 A.8.24 · ASVS V6.2.2, V6.3.1
Evidence (2)
- code sneakers-vault/internal/vault/crypto/envelope.go
- test sneakers-vault/internal/vault/crypto/envelope_test.go · TestSealStoresNoPlaintext, TestTamperedCiphertextFailsAuth, TestWrongKEKCannotOpen
Three-tier key hierarchy with a rotating key ring
Shipped in v0.1.0-rc.1A root key wraps versioned working keys, which wrap each secret's data key. Working keys rotate by re-wrapping data keys only, without decrypting any value; rotation is resumable, retired keys stay decrypt-only, and a scheduler rotates every 90 days by default. Only a site admin can rotate on demand.
SOC 2 CC6.1 · ISO 27001 A.8.24 · ASVS V6.4.1, V6.4.2
Evidence (3)
- doc sneakers-vault/docs/kek-keyring.md
- test sneakers-vault/internal/vault/grpcsvc/kek_rotate_test.go · TestRotateKek_SiteAdmin_RewrapsEveryRecordAndAudits, TestRotateKek_NonAdmin_Denied
- test sneakers-vault/internal/vault/grpcsvc/kek_schedule_test.go · TestKekSchedulerTick_RotatesWhenDue
Open work: sneakers-vault#104 Key ring design note
Fail-closed key start-up
Shipped in v0.1.0-rc.1Outside development the vault won't start without a root key, and the root key must unwrap every working key before any database migration runs. An unknown key reference fails closed.
SOC 2 CC6.1 · ISO 27001 A.8.24 · ASVS V6.2.1
Evidence (3)
- code sneakers-vault/cmd/vault/boot.go
- test sneakers-vault/cmd/vault/boot_test.go · TestMigrateAfterPreflight_CorrectKEK_MigratesAndBoots
- test sneakers-vault/internal/vault/crypto/keyring_test.go · TestKeyringKEK_UnknownRef_FailsClosed
Root key custody
Partial since v0.1.0-rc.3The vault reads its root key from the environment at start and holds it in memory. On the appliance the key lives on the encrypted state volume, whose key is sealed in the TPM, and is copied into the owner's escrow. The root key itself can't be rotated, and there is no HSM or cloud KMS provider yet.
SOC 2 CC6.1 · ISO 27001 A.8.24 · ASVS V6.4.1
Evidence (2)
- doc sneakers-appliance/docs/key-custody.md · Product keys
- code sneakers-vault/cmd/vault/main.go
Open work: sneakers-vault#41 HSM and cloud KMS key providers
Second-factor secrets and tokens at rest
Shipped in v0.1.0-rc.1TOTP seeds are sealed with AES-256-GCM under a dedicated key. Email codes and API tokens are stored only as SHA-256 hashes. The TOTP key can't be rotated yet without re-enrolling every factor.
SOC 2 CC6.1 · ISO 27001 A.5.17, A.8.24 · ASVS V2.9.1, V6.1.1
Evidence (2)
- code sneakers-identity/internal/secrets/secrets.go
- test sneakers-identity/internal/secrets/secrets_test.go · TestOpenTamperFails, TestOpenWrongKeyFails
Metadata at rest
Partial since v0.1.0-rc.1Only field values are application-encrypted. Secret names, folders, rules, targets and settings are stored as plain JSON in each service's database. On the appliance that database sits on the LUKS2-encrypted state volume; on your own Kubernetes, disk encryption is yours to provide.
SOC 2 C1.1 · ISO 27001 A.8.24
Evidence (1)
Encryption in transit between services
PlannedInternal gRPC calls are authenticated (ARC-2) but not encrypted: every client dials without TLS, and the gateway serves plain HTTP behind the cluster ingress. Confidentiality on the wire depends on the platform today (a private network or a service mesh with mTLS).
SOC 2 CC6.7 · ISO 27001 A.8.24, A.8.20 · ASVS V9.2.2
Evidence (2)
- code sneakers-gateway/cmd/gateway/backend.go
- doc sneakers-gateway/README.md · Before production
Open work: sneakers-appliance#235 TLS on the product endpoint and cert-manager, sneakers-notify#20 TLS in REDIS_URL is ignored
Export-compliant, standard cryptography
Shipped in v0.1.0-rc.1Sneakers uses only standard, published algorithms from the Go standard library and well-known libraries (AES-GCM, AES-XTS through LUKS2, SHA-256, HKDF, ECDSA, age). There is no FIPS 140-3 validated mode yet.
ISO 27001 A.8.24, A.5.31 · ASVS V6.2.2
Evidence (1)
- doc docs/CRYPTO.md
Open work: sneakers-appliance#216 FIPS 140-3 mode
Identity, MFA and sessions
Sign-in, second factors, step-up and how a browser session is held.
Passwords held by a dedicated identity provider
Shipped in v0.1.0-rc.1Passwords are stored and checked by the bundled Ory Kratos, never by Sneakers services. Its hashing parameters are Kratos configuration and aren't asserted by this review. Self-service reset uses an emailed code and answers the same way whether or not the account exists.
SOC 2 CC6.1 · ISO 27001 A.5.17, A.8.5 · 800-63B 5.1.1.2 · ASVS V2.4.1, V2.5.2
Evidence (2)
Second factor required for every session
Shipped in v0.1.0-rc.1A session without a verified second factor gets mfa_required on the API. Factors are TOTP (RFC 6238), emailed six-digit codes (single use, five minutes, five guesses) and WebAuthn passkeys as a second factor with a strictly increasing sign counter.
SOC 2 CC6.1 · ISO 27001 A.8.5 · 800-63B 4.2.1, 5.1.4, 5.1.8 · ASVS V2.7, V2.8, V4.3.1
Evidence (3)
- code sneakers-gateway/internal/bff/http.go
- code sneakers-identity/internal/grpcsvc/mfa.go
- test sneakers-identity/internal/grpcsvc/mfa_pg_test.go · TestPGTotpVerifyAndReEnrollGuard
TOTP replay and guessing limits
Partial since v0.1.0-rc.1A pending second-factor sign-in ends after five wrong codes. TOTP verification itself doesn't yet refuse a code reused inside its period, and email codes don't prove possession of a device, so they don't meet SP 800-63B's out-of-band rules.
800-63B 5.1.4.2, 5.2.2, 5.1.3.1 · ASVS V2.2.1, V2.8.4
Evidence (2)
- code sneakers-gateway/internal/bff/mfa.go
- test sneakers-gateway/internal/bff/stepup_test.go · TestMfaStepUp_AttemptBudgetEndsTheSession
Server-side sessions in a hardened cookie
Shipped in v0.1.0-rc.1The browser holds only an opaque session id in a cookie that is HttpOnly, SameSite=Strict and Secure by default; a malformed setting stops the gateway at start. Sessions slide on use within an admin-set lifetime of 15 to 60 minutes, and an admin cutoff ends every older session.
SOC 2 CC6.1 · ISO 27001 A.8.5 · 800-63B 7.1, 4.2.3 · ASVS V3.2.1, V3.3.1, V3.4.1, V3.4.2, V3.4.3
Evidence (3)
- doc sneakers-gateway/docs/cookies.md
- test sneakers-gateway/internal/bff/cookie_secure_test.go · TestEveryCookieHonoursSecure
- test sneakers-gateway/internal/bff/session_cutoff_test.go · TestASessionIssuedBeforeTheCutoffIsEnded
Open work: sneakers-gateway#31 Session tokens are stored unencrypted in Redis
Step-up for sensitive actions
Shipped in v0.1.0-rc.1Changing factors, approving requests, consenting to an agent's sign-in, revealing where policy requires it, and sensitive check-outs need a second factor verified within MFA_MAX_AGE (30 minutes by default, 4 hours at most).
SOC 2 CC6.1 · ISO 27001 A.8.5 · 800-63B 7.2 · ASVS V3.7.1
Evidence (2)
- doc sneakers-gateway/docs/configuration.md · MFA_MAX_AGE
- test sneakers-gateway/internal/bff/stepup_test.go · TestMfaStepUp_NeedsSessionAndCSRF
CSRF and cross-origin protection
Shipped in v0.1.0-rc.1Every state-changing browser request carries a 32-byte CSRF token checked by double submit in constant time. CORS is an exact-origin allow-list; a wildcard or malformed entry stops the gateway at start.
ISO 27001 A.8.26 · ASVS V4.2.2, V13.2.3, V14.5.3
Evidence (2)
- code sneakers-gateway/internal/bff/csrf.go
- test sneakers-gateway/cmd/gateway/cors_test.go · TestCORSBadEntriesRefused
Browser security headers
Shipped in v0.1.0-rc.2The web apps send a nonce-based Content-Security-Policy with frame-ancestors 'none', plus nosniff, X-Frame-Options DENY and a same-origin referrer policy. Styles still allow 'unsafe-inline'.
ISO 27001 A.8.26 · ASVS V14.4.3, V14.4.4, V14.4.7
Single sign-on and passkey sign-in
Partial since v0.1.0-rc.1SAML sign-on runs through the bundled Ory Polis at the gateway. Passkeys work as a second factor, but passwordless passkey sign-in isn't built, and SSO sessions have an open subject-mismatch bug.
SOC 2 CC6.1 · ISO 27001 A.8.5 · 800-63B 5.1.8, 5.2.5
Evidence (1)
Open work: sneakers-identity#22 Passkey sign-in, sneakers-identity#20 SSO sessions fail with a subject mismatch
Authorization and approvals
Folder rules that deny by default, approvals no one grants themselves, and break-glass.
Deny-by-default folder rules
Shipped in v0.1.0-rc.1Access comes from rules on a folder tree, evaluated most specific first, first match wins, deny by default. Rules grant read, informed, approve and manage separately; approve and manage imply read, informed never does. Access decisions are made in the vault, not the gateway.
SOC 2 CC6.1, CC6.3 · ISO 27001 A.5.15, A.5.18, A.8.3 · ASVS V4.1.3, V4.1.5
Evidence (2)
- code sneakers-vault/internal/vault/authz/resolve.go
- test sneakers-vault/internal/vault/authz/resolve_test.go · TestResolve_ReadableUserActs, TestResolve_InformedIndependentOfRead
Approvals no one grants to themselves
Shipped in v0.1.0-rc.1A secret can require approval or always require it. A requester never approves their own request. Where nobody else can decide (a single-user install, or the only approver), the requester confirms once with a fresh second factor; that is a recorded self-confirmation, not two-person control.
SOC 2 CC6.3 · ISO 27001 A.5.3, A.8.2 · ASVS V4.1.3
Evidence (2)
- doc sneakers-mcp/docs/api.md · Approvals
- test sneakers-vault/internal/vault/grpcsvc/secret_use_test.go · TestSecretUseIsReleasedOnceAfterAnOwnerApproves
Open work: sneakers-gateway#47 Approval queue, renewal, force check-in and quorum
One task, one prompt
Shipped in v0.1.0-rc.1An agent run's requests share one approval page with one second factor. Each item is still decided in the vault and audited on its own, the requester can't decide (the machine API has no decide call), and the stated purpose is shown as untrusted text.
SOC 2 CC6.3 · ISO 27001 A.8.2
Evidence (1)
Break-glass for people only
Shipped in v0.1.0-rc.1Break-glass is open to site admins only, from their own web session with a TOTP code, and lasts 15 minutes. Agents and tokens are refused, refusals are audited, and a break-glass reveal is refused if its audit record can't be written.
SOC 2 CC6.1, CC6.3 · ISO 27001 A.8.2, A.8.18 · ASVS V4.3.1
Evidence (2)
- test sneakers-gateway/internal/resolvers/break_glass_people_only_test.go · TestPlainBreakGlassSecretIsRefusedToAgentsAndTokens
- test sneakers-vault/internal/vault/grpcsvc/breakglass_test.go · TestBreakGlassAuditFailClosedDeniesReveal
Open work: sneakers-vault#70 Dual control for break-glass, sneakers-vault#72 Break-glass rate limits and frequency alerts, sneakers-vault#151 Enforce people-only reveals in the service, not only by routing
Recovery role for history
Shipped in v0.1.0-rc.1Listing a secret's history needs read access; revealing or restoring an earlier version needs the separate recovery role plus a fresh second factor. Site admin doesn't imply recovery.
SOC 2 CC6.3 · ISO 27001 A.8.2, A.8.3
Evidence (1)
- test sneakers-vault/internal/vault/grpcsvc/recovery_test.go · TestRevealingAPriorVersionNeedsRecoveryAndFreshMFA
Reveal, check-out and rotation
How a value leaves the vault, and how credentials are changed on their targets.
Reveal one field, with checks in order
Shipped in v0.1.0-rc.1A reveal is refused for a retired secret, then checks the field is sensitive, read access, approval and step-up, and only then decrypts the one requested field and records secret.reveal. Step-up on reveal is a global setting with per-folder overrides that only site admins set.
SOC 2 CC6.1, C1.1 · ISO 27001 A.8.3, A.8.12 · ASVS V4.1.1, V8.3.4
Evidence (2)
- code sneakers-vault/internal/vault/grpcsvc/secrets.go
- test sneakers-vault/internal/vault/grpcsvc/sensitive_settings_test.go · TestRevealStepUpFollowsTheGlobalSettingAndFolderOverrides
Single-use, short-lived approved uses
Shipped in v0.1.0-rc.1A prepared use expires in 10 minutes; once approved it must be redeemed within one minute, by the same token, once. Access is checked again at redemption, and the audit record never carries the value. Standing pre-approvals are capped at 24 hours.
SOC 2 CC6.1 · ISO 27001 A.8.3 · ASVS V4.1.3
Evidence (2)
- test sneakers-vault/internal/vault/grpcsvc/secret_use_test.go · TestSecretUseOnlyTheSameTokenRedeems, TestSecretUseRechecksAccessAtRedeem, TestSecretUseAuditNeverCarriesTheValue
- test sneakers-vault/internal/vault/grpcsvc/secret_use_hardening_test.go · TestRedeemMustFollowApprovalWithinAMinute
Check-out leases that rotate on check-in
Shipped in v0.1.0-rc.1Check-out needs read access, a type that allows it, a fresh second factor for sensitive types (on by default) and no lease already held. Only the holder can check in, and check-in rotates the credential. Concurrent check-outs issue one lease.
SOC 2 CC6.1, CC6.3 · ISO 27001 A.5.18, A.8.2
Evidence (3)
- code sneakers-vault/internal/workflow/grpcsvc/checkout.go
- test sneakers-vault/internal/workflow/grpcsvc/checkout_checks_test.go · TestCheckinByANonHolderIsRefusedAndRotatesNothing, TestConcurrentCheckoutsIssueOneLease
- test sneakers-vault/internal/workflow/grpcsvc/sensitive_checkout_test.go · TestSensitiveCheckoutNeedsAFreshMFAWhenOn
Rotation without agents on targets
Partial since v0.1.0-rc.1The connector pulls due heartbeat and rotation jobs and changes passwords over LDAP/LDAPS and Kerberos using the account's own current password, so it needs no admin rights. The directory's built-in Administrator is matched by SID and never rotated. SSH, WinRM and SAMR rotation aren't built.
SOC 2 CC6.1 · ISO 27001 A.5.17
Evidence (2)
- doc sneakers-connector/README.md
- test sneakers-connector/internal/adapter/ldap_account_test.go · TestRotateADBuiltinAdministratorIsRefusedWithoutChange
Open work: sneakers-connector#16 SSH, WinRM and SAMR rotation, sneakers-connector#33 Respect directory password rules when rotating, sneakers-connector#75 Pin LDAPS certificates for an enterprise CA
Strong generated passwords
Shipped in v0.1.0-rc.1Generated passwords come from the OS CSPRNG: 20 characters from an 86-character pool by default (about 128 bits), with per-policy length, required classes and excluded characters.
ISO 27001 A.5.17 · ASVS V6.3.1
Evidence (1)
- test sneakers-vault/internal/vault/grpcsvc/pwgen_test.go · TestGeneratePasswordRequiredClasses
Brokered SSH without handing over the key
Partial since v0.1.0-rc.2In-browser SSH uses a single-use ticket that lives 30 seconds and holds no key material. The broker fetches the key as the user when the browser connects, wipes it after use, connects only to pinned host keys and cuts sessions at 8 hours. Sessions aren't recorded yet.
SOC 2 CC6.1 · ISO 27001 A.8.2, A.8.15
Evidence (2)
- test sneakers-sshbroker/internal/session/store_test.go · TestCreateAndConsumeOnce, TestZeroizeWipesKey
- test sneakers-sshbroker/internal/wsproxy/hostkey_test.go · TestHandlerConnectsWhenHostKeyPinned
Open work: sneakers-sshbroker#21 Session recording, sneakers-sshbroker#26 Reject agent principals
Values on screen
Partial since v0.1.0-rc.2The web UI masks values until revealed and tells the user each reveal is logged. Hiding is manual: there is no auto-hide timer and nothing clears the clipboard after a copy.
ISO 27001 A.8.12 · ASVS V8.2.1
Evidence (1)
Audit trail
A hash-chained record of every action, and its limits.
Hash-chained audit records
Shipped in v0.1.0-rc.2Each record's SHA-256 covers its sequence, action, actor, subject, attributes, time and the previous record's hash. VerifyChain reports a gap, a wrong link or a wrong hash, walking the chain in pages so it scales.
SOC 2 CC7.2, CC4.1 · ISO 27001 A.8.15, A.5.33 · ASVS V7.3.3
Evidence (2)
- code sneakers-audit/internal/chain/chain.go
- test sneakers-audit/internal/grpcsvc/audit_test.go · TestChainLinksAndVerifies, TestTamperBreaksChain
Who may write and read the trail
Shipped in v0.1.0-rc.2Only listed services may record, only the gateway may read, the migration job may only record and verify, and the appliance may only write its own admin events. The service won't start without an issuer.
SOC 2 CC6.1 · ISO 27001 A.8.15 · ASVS V7.3.4
Evidence (1)
- test sneakers-audit/internal/grpcsvc/callers_test.go · TestCallerAuth_ReadsAreForTheGatewayOnly
Tamper evidence, not tamper resistance
Partial since v0.1.0-rc.2The chain is keyless and unsigned, and the database doesn't stop UPDATE or DELETE. It detects edits by anyone without database write access; someone with it could rewrite the chain and recompute every hash. Routine audit writes are best-effort (only break-glass fails closed), and there is no retention setting yet.
SOC 2 CC7.2 · ISO 27001 A.8.15 · ASVS V7.3.3
Evidence (1)
Open work: sneakers-audit#60 Signed audit archive, sneakers-audit#17 Run more than one instance safely, sneakers-audit#18 Record vendor sign-ins and denials
No secret values in logs or notices
Shipped in v0.1.0-rc.1Audit records hold metadata only; reveals record which field, never its value. Notifications have no field that could carry a value. Services and the MCP never log tokens or values. The audit service relies on its callers for this and doesn't check it server-side.
SOC 2 C1.1 · ISO 27001 A.8.11, A.8.15 · ASVS V7.1.1, V7.1.2
Evidence (2)
- code sneakers-notify/proto/sneakers/notify/v1/notify.proto
- test sneakers-connector/internal/tokensource/tokensource_test.go · TestFileNeverLogsToken
MCP and machine API
How agents and tokens use secrets through the same rules a person does.
Agents sign in with their own token
Shipped in v0.1.0-rc.1The MCP bridge accepts OAuth JWTs (signature, issuer, audience and expiry checked locally), service-account tokens and personal tokens. Opaque tokens are confirmed by the gateway and cached for at most 60 seconds by hash; any failure is a 401 and is never cached. If the gateway is down, it fails closed.
SOC 2 CC6.1 · ISO 27001 A.8.5 · ASVS V3.5.3, V13.1.3
Evidence (2)
- doc sneakers-mcp/docs/configuration.md
- test sneakers-mcp/internal/authn/authn_test.go · TestAPITokenGatewayDownFailsClosed, TestAPITokenRevokedIsRejectedOnceCacheExpires
Same rules and audit as a person
Shipped in v0.1.0-rc.1The bridge holds no credentials and makes no access decisions; it forwards the caller's own token to the machine API, where the vault applies the same folder rules, approvals and audit. Consent to an agent's sign-in needs a recent second factor, using PKCE with S256.
SOC 2 CC6.1, CC6.3 · ISO 27001 A.5.15 · ASVS V4.1.1
Evidence (2)
Open work: sneakers-gateway#145 Keep CLI tokens off the MCP switch
What an agent can receive
Shipped in v0.1.0-rc.1By design an agent with access receives plaintext values: reads of plain fields, approved reveals (once, within 60 seconds) and new values from rotation. Approval-gated secrets return an approval link, not a value. Super-sensitive fields are withheld from every token unless an admin turns on API access to sensitive secrets (off by default). MCP is an add-on, off by default.
SOC 2 C1.1 · ISO 27001 A.8.3, A.8.12
Evidence (2)
- test sneakers-mcp/internal/tools/tools_reveal_test.go · TestGetSecretOfAnApprovalSecretReturnsTheApprovalLinkNotAValue
- test sneakers-vault/internal/vault/grpcsvc/sensitive_settings_test.go · TestAPIForSensitiveOffKeepsSuperSensitiveFieldsFromMachines
Open work: sneakers-mcp#17 Personal tokens of a disabled user
Appliance platform
A signed, read-only OS with Secure Boot, TPM-sealed disk keys and A/B updates.
Minimal, reproducible, read-only OS
Shipped in v0.1.0-rc.3The appliance isn't a Linux distribution: it is built from a declared file list (a pinned kernel, busybox, OpenSSH and the project's own programs) with its own init as PID 1 and no setuid files. The root is a read-only SquashFS checked block by block with dm-verity, and the build is reproducible byte for byte.
SOC 2 CC6.8, CC7.1 · ISO 27001 A.8.9, A.8.19
Evidence (2)
Open work: sneakers-appliance#45 Build the kernel and static tools from pinned sources
Secure Boot with project-owned keys
Shipped in v0.1.0-rc.3Firmware boots a project-signed systemd-boot and one signed kernel image (UKI) with no shim and no vendor keys. The kernel runs in lockdown, and the dm-verity root hash is inside the signed image. If the box is set to Secure Boot and the firmware stops enforcing it, the product won't start. An admin can choose reduced protection, which is labelled.
SOC 2 CC6.8 · ISO 27001 A.8.9, A.8.19 · ASVS V10.3.2
Evidence (2)
- doc sneakers-appliance/docs/secure-boot.md
- ci sneakers-appliance/.github/workflows/image-e2e.yml · QEMU with Secure Boot firmware and a software TPM
Open work: sneakers-appliance#413 Production Secure Boot enrolment without a manual key reset, sneakers-appliance#62 Turn Secure Boot on or off later and reseal
TPM-sealed disk encryption
Shipped in v0.1.0-rc.3The state and backup partitions are LUKS2 (AES-XTS) under one random 256-bit key, sealed in the TPM to the boot measurements (PCR 7 and 11 with Secure Boot). Without a TPM, including on arm64, the key falls back to a key-file partition, shown as reduced protection. There is no remote attestation.
SOC 2 CC6.1, C1.1 · ISO 27001 A.8.24, A.7.10
Evidence (2)
Signed, encrypted, A/B updates
Shipped in v0.1.0-rc.3An update is checked against the release key built into the running OS, then its channel, size and SHA-256, before it is decrypted. Anything not newer than the running release is refused. Updates install to the inactive slot; three failed boots fall back to the previous release.
SOC 2 CC8.1, CC7.1 · ISO 27001 A.8.19, A.8.32 · ASVS V10.3.2
Evidence (2)
- doc sneakers-appliance/docs/upgrades.md
- test sneakers-appliance/internal/product/slots_test.go · downgrade refusal
Open work: sneakers-appliance#72 Rotate the update key
Certificate-only SSH and a closed firewall
Shipped in v0.1.0-rc.3SSH accepts only box-issued keys with their certificates, then a TOTP code; no passwords and no root login. A root shell needs a one-time challenge from the admin page. The firewall opens SSH and the admin page only on the management interface, step by step during first boot, and can limit them to an allow-list.
SOC 2 CC6.1, CC6.6 · ISO 27001 A.8.2, A.8.5, A.8.20
Evidence (2)
Hash-chained OS audit log
Partial since v0.1.0-rc.3Appliance administration is written to a daily JSONL log on the encrypted volume, each line carrying the previous line's SHA-256. It isn't forwarded off the box yet.
SOC 2 CC7.2 · ISO 27001 A.8.15
Evidence (1)
Open work: sneakers-appliance#103 Forward the OS audit log
Supply chain and releases
Signed artifacts, multi-arch images, protected release keys and what isn't there yet.
Signed release artifacts
Shipped in v0.1.0-rc.3Every release asset (OS image, update headers, release manifest, checksums and a signature per pinned image digest) is signed with cosign using a project-held ECDSA P-256 key. Signatures aren't in a public transparency log, and image signatures are files on the release rather than attached in the registry.
SOC 2 CC8.1 · ISO 27001 A.8.32 · ASVS V10.3.2, V14.2.4
Evidence (2)
Protected release keys
Shipped in v0.1.0-rc.3Production signing keys live only in a protected CI environment that needs the maintainer's approval and accepts only version tags. CI refuses lab keys in a release, keys sit on tmpfs only for the step that uses them, and every other CI run uses fresh lab keys.
SOC 2 CC6.1, CC8.1 · ISO 27001 A.8.24, A.8.31
Evidence (1)
Multi-arch service images
Shipped in v0.1.0-rc.3Service images are built natively for linux/amd64 and linux/arm64 and published as one image index, so the same release runs on a Raspberry Pi. Appliance update and install images are amd64 only.
ISO 27001 A.8.32
Evidence (1)
- ci sneakers-appliance/.github/workflows/release.yml · images job
SBOM and build provenance
PlannedNo SBOM (SPDX or CycloneDX) or SLSA provenance is published yet. This is the main supply-chain gap.
SOC 2 CC7.1, CC9.2 · ISO 27001 A.5.21, A.8.30 · ASVS V14.2.5
Open work: sneakers-release#69 NIST SSDF (SP 800-218) self-assessment
Backup and recovery
Key escrow and migration bundles exist; scheduled backups don't yet.
Key escrow to the owner's recovery keys
Shipped in v0.1.0-rc.3The owner downloads an escrow file holding the disk key and the product's keys (the vault root key and the TOTP key), encrypted with age to one to three SSH recovery keys. A replacement box imports it at first boot so restored data opens.
SOC 2 A1.2 · ISO 27001 A.8.13, A.8.24
Evidence (1)
- doc sneakers-appliance/docs/key-custody.md · Sealed items and the escrow
Encrypted migration bundles
Shipped in v0.1.0-rc.3sneakers-migrate exports every service's data as an age-encrypted archive, verifies the audit chain end to end on import, and is rehearsed in CI, including a 727,000-record audit chain.
SOC 2 A1.2, A1.3 · ISO 27001 A.8.13
Scheduled backups
PlannedThere are no scheduled or offsite backups yet: the appliance's backup service is a stub and its backup partition is unused. Until then, recovery relies on the escrow and a migration export.
SOC 2 A1.2, A1.3 · ISO 27001 A.8.13, A.5.30
Open work: sneakers-appliance#462 Scheduled offsite backups, sneakers-appliance#106 Backup lifecycle
Logging, monitoring and health
Readiness that follows real dependencies, log levels by environment, and telemetry.
Readiness that follows real dependencies
Shipped in v0.1.0-rc.1Each service's gRPC health and /readyz fail while a required dependency (its database, gRPC peers, the workload-identity key set) is down; liveness checks the process only.
SOC 2 A1.1, CC7.2 · ISO 27001 A.8.16
Evidence (1)
- test sneakers-vault/internal/server/health_test.go · TestHealth_ReadinessFollowsRequiredDependencyLivenessDoesNot
Structured logs and telemetry
Partial since v0.1.0-rc.3Services log JSON at a level set per environment (production defaults to error) and can send traces and metrics to an OpenTelemetry collector. The appliance doesn't forward its logs and there is no built-in alerting yet.
SOC 2 CC7.2, CC7.3 · ISO 27001 A.8.15, A.8.16
Evidence (1)
Open work: sneakers-appliance#113 Forward logs to syslog or OTLP, sneakers-appliance#332 Export logs over OpenTelemetry
Secure development and vulnerability handling
CI gates, scanning, public-code scrubbing and how to report a vulnerability.
Gated changes on protected branches
Shipped in v0.1.0-rc.1main accepts only squash-merged pull requests that pass the required checks (build and test, gosec, govulncheck, licence headers, dependency licences and the scrub). Force-push and deletion are blocked. No second reviewer is required: Sneakers has one maintainer today.
SOC 2 CC8.1 · ISO 27001 A.8.25, A.8.32
Evidence (1)
Open work: sneakers-release#23 A required release-review group
Vulnerability and secret scanning
Partial since v0.1.0-rc.1govulncheck and gosec run on every pull request and weekly; gitleaks and pattern checks run in the scrub. There is no CodeQL, container image scan or automated dependency update yet, and actions are pinned by commit only in the appliance repo.
SOC 2 CC7.1 · ISO 27001 A.8.8, A.8.28 · ASVS V14.2.1
Evidence (1)
Open work: sneakers-release#51 Excluded govulncheck finding awaiting an upstream fix
Test-first changes across layers
Shipped in v0.1.0-rc.1Behaviour is specified by tests through public APIs, with real Postgres, real sshd and network namespaces where it matters, and the appliance is exercised end to end in QEMU after each merge and nightly.
SOC 2 CC8.1 · ISO 27001 A.8.29
Evidence (1)
Private vulnerability reporting
Shipped in v0.1.0-rc.1Vulnerabilities are reported privately through GitHub on the affected repository, acknowledged within a few business days, fixed and disclosed on a timeline agreed with the reporter, and credited in the advisory. A signed advisory feed for appliances is planned.
SOC 2 CC2.3, CC7.3, CC7.4 · ISO 27001 A.5.24, A.5.26, A.8.8
Evidence (1)
Open work: sneakers-appliance#330 Signed vulnerability-advisory feed
Documents
Documents.
The security review is the long form of this page: architecture, data flows, key hierarchy and every control with its evidence.
Security review
Architecture, data flows and every control mapped to SOC 2, ISO 27001, SP 800-63B and ASVS, with evidence. PDF.
Security policy
How to report a vulnerability and which versions get fixes.
Cryptography and export
The algorithms Sneakers uses and its export classification.
Key custody
How the appliance seals its keys in the TPM and escrows them to your recovery keys.
Sub-processors
Sub-processors.
Sneakers-PAM is self-hosted. The project runs no service that sees your secrets, users or audit trail. The only outside services are the project's own infrastructure and the ones you choose to connect.
| Service | Purpose | Data it sees | Scope |
|---|---|---|---|
| GitHub | Source code, CI, releases, container images and private vulnerability reports | No customer data. An appliance or cluster pulls images and updates from it. | Project infrastructure |
| Cloudflare Pages | Hosts this website | Visitors' requests to this site. No product data. | Project infrastructure |
| Google Fonts | Serves this website's typefaces | Visitors' requests for font files. No product data. | Project infrastructure |
| Your email relay | Sign-in codes, password resets and notices | Recipient addresses and message text, never a secret value | Chosen and run by you; none is bundled |
| Your identity provider | Optional SAML single sign-on | Sign-in assertions for your users | Chosen and run by you |
Report a vulnerability
Found a vulnerability? Tell us privately.
Please don't open a public issue, discussion or pull request for a suspected vulnerability.
- Open the affected repository on GitHub, go to the Security tab and choose Report a vulnerability.
- Say what you found, how to reproduce it, and the version or commit affected.
- Expect an acknowledgement within a few business days. We'll agree a fix and disclosure timeline with you, and credit you in the advisory unless you'd rather not be named.