Security
What mxAURA enforces
- Tenant boundary in the data layer. Every database statement from every worker passes through a query plane that requires a tenant predicate on every tenant table (the list is derived from the schema, not maintained by hand). A statement that could read another account's rows is refused before it runs. The API code cannot forget to check an id; the database layer would refuse anyway.
- Credentials at rest. API keys are stored as SHA-256 hashes. OAuth tokens likewise. HubSpot OAuth tokens and webhook signing secrets are encrypted (AES-256-GCM, envelope keyed by a vault-held master key).
- Keys never in browsers. A request carrying a browser
Originis refused for API keys (403 browser_origin). Browser apps use OAuth. - Rate limits and caps at three levels plus the hourly enrollment cap.
- Idempotency on POST so retries cannot duplicate.
- Model-facing surfaces never see user-authored bodies.
- 5xx text never leaves the platform — you get a reference id, our logs get the detail.
- Every request is logged (credential, route, status, latency) to an analytics dataset an operator watches for runaway keys; every credential action (create, rotate, reveal, revoke) is audited.
What you should do
- One key per integration, named for it. Rotate when someone leaves.
- Least scope. A reporting job needs
dispatch.read, notfull. A content pipeline needsarticles.write+publishing.write, notsubscribers.write. - Set the IP allowlist on keys used from fixed infrastructure.
- Never put
enrollments.writeon a key you are not sure about. It sends email to real people. - Verify every webhook signature and reject stale timestamps.
- Store the key and the webhook secret in a secret manager, not in code
or a
.envcommitted to git. - Use
Idempotency-Keyon any create you might retry. - Watch
X-MXA-Key-Status: rotated_gracein your logs — it means a caller still has the old key.
Reporting a vulnerability
Email support@mxaura.com with "security" in the subject. Do not test against accounts you do not own.