Skip to content

Security Guide

Opencomplai is designed to handle compliance evidence that may be sensitive. This guide covers the security model and operational best practices.

Signing and verification

Every opencomplai check run can produce a cryptographically signed ScanStatusArtifact using the Ed25519 keypair generated by opencomplai init.

Bash
# Generate signing keypair (run once per install)
opencomplai init --system-id my-system --intended-purpose "..."

# Sign the artifact
opencomplai check --sign
PowerShell
# Generate signing keypair (run once per install)
opencomplai init --system-id my-system --intended-purpose "..."

# Sign the artifact
opencomplai check --sign

The private signing key is stored at ~/.opencomplai/signing.key and never transmitted. In CI, where there is no key file, set SIGNING_KEY_PRIVATE to the base64-encoded PEM of the private key from your CI secret store; it takes precedence over the key file. check --sign exits 2 when neither exists; check --sign-if-available signs when a key is present and otherwise warns and writes an unsigned artifact. The GitHub Actions and GitLab CI connectors use --sign when SIGNING_KEY_PRIVATE is set and --sign-if-available otherwise. The public key is registered with the dashboard when you enroll via opencomplai dashboard enroll.

Key rotation: to rotate the signing key, delete ~/.opencomplai/signing.key and re-run opencomplai init. Re-enroll with opencomplai dashboard enroll to register the new key.

Egress control

All outbound traffic from the Docker Compose stack passes through the egress-proxy service, which enforces an ALLOWED_DESTINATIONS allowlist. To run in fully air-gapped mode (zero outbound traffic):

Bash
# In infra/compose/.env
EGRESS_ALLOWED_DESTINATIONS=

This is the default for a fresh installation.

Secrets management

  • POSTGRES_PASSWORD — required; never set it to the default changeme value in production.
  • Never commit infra/compose/.env to version control. It is in .gitignore by default.
  • Never commit ~/.opencomplai/signing.key. It is not in the repo and should be backed up separately.
  • The compliance-artifact.json and system-manifest.json output files are in .gitignore and should not be committed.

Supply chain

sync/verify-sbom.sh takes a published container image and verifies its cosign signature and its SBOM attestation. It does not generate an SBOM. It needs cosign and jq. By default it expands <service>:<version> to ghcr.io/opencomplai/opencomplai-enterprise/<service>:<version> and expects the signing identity of supply-chain.yml in the release repository Opencomplai/opencomplai-enterprise; a full image reference is used as is, and OPENCOMPLAI_RELEASE_REPO=<owner>/<repo> checks images built in another repository. Verification works only if the GHCR packages are public, and only for a tag that has actually been published (check the registry for the tags that exist).

Bash
./sync/verify-sbom.sh gateway-api:<version>
PowerShell
# Bash-only script — use WSL2 or Git Bash on Windows
./sync/verify-sbom.sh gateway-api:<version>

See Supply Chain for the full supply-chain security model.

Threat model

The core Opencomplai threat model has three boundaries:

  1. The signing key (the local key file or SIGNING_KEY_PRIVATE) — protects artifact authenticity. Compromise of this key allows forged compliance artifacts. Mitigate with filesystem permissions and, in production, a managed KMS.
  2. The PostgreSQL instance — stores the evidence ledger. Compromise allows history tampering. Mitigate with row-level security, encrypted volumes, and restricted network access.
  3. The egress-proxy — enforces the outbound allowlist. Bypass allows exfiltration of metadata. The proxy is fail-closed: if the allowlist is not configured, all outbound traffic is blocked.