Skip to main content

Security

Written to be forwarded to a security reviewer.

Summary

QuestionAnswer
Where does data live?Your database and your bucket, in your account
Does the vendor see it?No. There is no vendor-side component
Is analysis performed locally?Yes. Scoring and simulation run in your cluster
Does anything leave the network?Only optional narrative rendering, to OpenAI, under your key
Can that be turned off?Yes. Unset OPENAI_API_KEY
Who holds the encryption keys?You
Authentication?Your OIDC provider, or Google via IAP
Is there telemetry?No

The one claim worth reading carefully is the third and fourth. See Data flow for exactly what is computed where.

Encryption

Sensitive columns are encrypted before they are written, using envelope encryption. The key-encryption key lives wherever KMS_BACKEND points: in the application secret as APP_KEK, or in AWS KMS, Google Cloud KMS, or Vault.

Searchable sensitive columns carry blind indexes HMACed with INDEX_PEPPER, so equality lookups work without decrypting.

Login tokens are hashed at rest with AUTH_TOKEN_PEPPER.

Details and trade-offs in Encryption.

Licensing has no runtime dependency

The license is an Ed25519-signed token verified locally against a public key in the image. LICENSE_VALIDATION_URL adds optional revocation checks and is blank by default.

With it blank, an outage at the vendor cannot affect your deployment, because there is no call to fail.

Authentication

Four paths, and one of them needs a condition attached. Header-trust authentication through an identity-aware proxy is only safe when the app is reachable only through that proxy. See IAP.

ACCESS_TOKENS is a break-glass mechanism that bypasses your identity provider, your MFA, and your offboarding. Remove it after bootstrap.

Container posture

The chart runs the workload as non-root with a read-only root filesystem, allowPrivilegeEscalation: false, and all capabilities dropped.

podSecurityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]

Credentials

On GKE, the deployment can run with no static credentials at all: Workload Identity for storage, IAM database auth through the Cloud SQL Auth Proxy for Postgres, and IAP for sign-in.

On EKS, IRSA covers storage. The database still uses a password in DATABASE_URL.

What to check in a review

  • Is APP_KEK backed up outside the cluster? Its loss is unrecoverable
  • Is KMS_BACKEND still k8s? A real KMS is better
  • Is ACCESS_TOKENS still in the secret after SSO went live?
  • Is the app reachable by any path that bypasses the proxy, if using IAP?
  • Is LICENSE_ENFORCEMENT still enforce?
  • Is OPENAI_API_KEY set, and does your DPA with OpenAI cover it?

Reporting a vulnerability

Open an issue for anything non-sensitive. For a vulnerability, contact your support channel directly rather than filing publicly.