Operate securely
Security best practices
Key handling, fail-closed defaults, webhook verification, and OWASP LLM alignment.
About 9 minutes hands-on
What this guide does not cover
- Practices, not a compliance certificate. Following them does not make a deployment SOC 2 or ISO 27001 certified.
- Complements secure design, identity controls, monitoring, and incident response. It does not replace any of them.
Keep the API key server-side only
Never expose in browser code
SOTER_API_KEY must never appear in client-side JavaScript, mobile apps, or shipped artifacts.
No NEXT_PUBLIC_ prefix
In Next.js, never prefix with NEXT_PUBLIC_. Read keys only in route handlers or server actions.
Use your server as proxy
The browser talks to your server. Your server talks to SoterAI. API key stays on the server.
WordPress key security
The key lives in the options table used only from PHP. Frontend calls the local REST proxy.
Rotate keys regularly
- Rotate API keys on a schedule and immediately if one may have leaked.
- Use separate
ck_test_…andck_live_…keys per environment. - Use distinct keys per project so a single leak has a limited blast radius.
Always run the output guard
- Guarding input is not enough. Run
guardOutputon every LLM response to catch leaked secrets, PII, system-prompt leakage, and unsafe output. - For RAG, also verify grounding so answers stay attributable to authorized sources.
Redact logs
- Do not log raw prompts or completions in your application.
- The SDKs never log the API key or raw text, even in debug mode; keep that property in your own code.
- When you must persist examples for debugging, store the
redactedText/safe_text, not the original.
Sign and verify webhooks
If you consume SoterAI webhooks, verify the HMAC signature before trusting the payload:
TypeScript
1import { createHmac, timingSafeEqual } from "crypto";
2
3function verify(rawBody: string, header: string, secret: string) {
4 const m = /t=(\d+),v1=([0-9a-f]+)/.exec(header);
5 if (!m) return false;
6 const [, t, sig] = m;
7 const expected = createHmac("sha256", secret)
8 .update(`${t}.${rawBody}`)
9 .digest("hex");
10 return timingSafeEqual(
11 Buffer.from(expected, "hex"),
12 Buffer.from(sig, "hex"),
13 );
14}💡
Reject stale timestamps to prevent replay attacks. Check that the timestamp is within 5 minutes of the current time.
Timeout and fail behavior
- Set a sensible
timeoutMs(5s is a good default). - Decide your failure mode deliberately:
- Fail open (proceed if Soter is unreachable) — favors availability.
- Fail closed (block if Soter is unreachable) — favors safety.
- For high-risk surfaces, prefer fail-closed on the output path.
- Use the SDK
retriesoption for transient errors, but cap it.
Rate limiting and abuse prevention
- Respect
429and theRetry-Afterheader; back off rather than hammering. - Add your own per-IP/per-user limits in front of public chat endpoints.
Known limitations
- Pattern detection produces false positives and negatives — no detector is perfect.
- Rate limits are per-process; use a shared Redis bucket in multi-instance deployments.
- Do not market or describe SoterAI as guaranteeing complete protection.
- Combine SoterAI with least-privilege design, input validation, output encoding, secrets management, and monitoring.
- This reduces risk; it does not guarantee complete protection.