Security
At-rest encryption
Sensitive secrets in the database are encrypted with AES-256-GCM (via
Plug.Crypto.MessageEncryptor) using a key derived from the
TOKEN_ENCRYPTION_KEY environment variable:
-
users.encrypted_github_token— your GitHub OAuth user token -
users.encrypted_cursor_token— your Cursor Cloud Agents token
Each encryption call uses a fresh random IV. The HMAC tag is verified on
decryption — tampered ciphertexts return :error instead of a valid plaintext.
Webhook authenticity
-
GitHub:
X-Hub-Signature-256HMAC-SHA256 verified against the raw request body usingGITHUB_APP_WEBHOOK_SECRET. -
Stripe:
Stripe-Signaturet=…,v1=…header verified against the raw body usingSTRIPE_WEBHOOK_SECRET. Both verifications usePlug.Crypto.secure_compare.
A custom RawBodyReader plug (lib/cursor_automation_web/plugs/raw_body_reader.ex)
captures the unparsed bytes for the two webhook paths so signature checks see
the exact bytes Stripe/GitHub signed.
Retention
- Cached GitHub data is held until you delete the team. Deleting cascades to installations, repositories, issues, PRs, agents, and audit events.
-
Stripe is the source of truth for billing data; we mirror only enough fields
to gate
/appaccess.
GDPR-ish basics
We are happy to answer data-export and right-to-be-forgotten requests at privacy@cursor-automation.com. All data is single-region and never sold.