Security
An overview of Sikwati's authentication, sensitive-token protection, crawler controls and deployment-specific job safeguards.
Controls depend on the deployment profile. Private Cloudflare staging is owner-restricted and does not enable the full paid product. Legacy implementation descriptions and local tests are not certification of an unverified hosted production deployment.
Passwords are stored as bcrypt hashes — never plaintext, never reversible. Session cookies are HTTP-only and follow the standard NextAuth protections.
Every database query that touches your data is scoped by your user ID or by your workspace membership. There is no admin override path that bypasses this scoping in normal operation.
Workspace members can see only the websites and reports their workspace grants them. Workspace owners control invitations and can revoke access at any time. Per-page authorization is checked at the route level, not just on the parent route — a member who lost access can't use a deep link to bypass the check.
Password reset links are time-limited, single-use, and stored as hashes — the plaintext token never persists in our database after the email is sent.
GA4 and GSC OAuth refresh tokens (used for the optional traffic and search integrations) are encrypted at rest with an application-level key before they hit the database. A leaked database snapshot does not expose plaintext Google credentials.
Share-link access tokens (used for white-label client report URLs) are encrypted at rest. Lookup uses a SHA-256 hash of the token rather than the plaintext, so even the indexing layer never sees the secret.
API tokens are not stored in decryptable form at all — only a SHA-256 hash plus a short visible prefix are persisted, so the full plaintext token is only shown once at creation time.
These encryption and hashing schemes use the app's shared secret material; rotating keys may require re-encrypting or reissuing affected credentials depending on the token type.
Sikwati's crawler resolves every hostname through an SSRF guard before fetching. Private IP ranges (RFC 1918, link-local, loopback, carrier-grade NAT) are rejected for both IPv4 and IPv6. The resolved IP is then pinned to the actual fetch so a DNS rebind between guard and request can't redirect the call to an internal address.
robots.txt is honored on every scan. Page discovery is capped at 200 URLs per site to keep crawler load bounded and predictable.
Citation runs talk only to the configured AI engine APIs — never to your own infrastructure or unauthenticated endpoints.
Atomic job claims limit duplicate job processing. They do not alone guarantee exactly-once provider charging: an ambiguous or failed request may already have incurred a provider cost. Durable usage reservations and recovery must be verified in the runtime before paid launch.
If a worker crashes or restarts mid-job, a stale-job recovery sweep marks orphaned jobs as FAILED on next boot and again hourly, so jobs don't lock the queue indefinitely.
Auto-tracking cooldowns are computed against successful runs only. After three consecutive failures on a site, auto-tracking pauses for that site until a manual run succeeds — preventing quota burn on a misconfigured account or persistent provider outage.
The legacy worker has bounded retries for transient provider failures. The private native Cloudflare pilot does not automatically retry provider calls. Recovery and pause behavior depend on the deployed runtime; a failed request is inconclusive, not a negative visibility result.
Plan limits (sites, tracked prompts, monthly citation queries, manual runs, competitors) are enforced server-side on every action. A client tampering with the UI cannot exceed the limits.
Monthly check allowances must be enforced with durable usage accounting independently of deletable result history. Native reservation adapters are locally tested but are not proof of a completed production rollout. Deleting results must not refund already spent checks.
The data layer keeps demo data isolated from real-customer aggregates — dashboard headlines never blend the two.
Workspace outgoing webhooks can be signed with an HMAC-SHA256 signature so the receiver can verify authenticity before processing the payload.
Slack alert delivery and outgoing webhooks are treated as best-effort fan-out integrations. Delivery failures do not block scans, citation runs, or billing state changes.
If you have a security question or want to disclose a vulnerability, contact the support channel for your deployment. We treat coordinated disclosure seriously and will not pursue researchers acting in good faith under standard responsible-disclosure terms.
As the product matures, this page will expand to cover infrastructure regions, formal backup retention windows, audit logging, and the full vendor/subprocessor disclosure list.