Security checks
Before shipping
- Exclude environment secrets
Keep .env files out of version control. Commit an example file with placeholders instead.
- Scan for secrets
Run a secret scanner before committing and in CI. Include Git history in the scan.
- Rotate leaked keys
Revoke and replace exposed credentials. Removing them from a file or Git history does not invalidate them.
- Keep private API keys on the server
Check that browser JavaScript, public assets, and API responses contain no private keys.
- Pin dependency versions
Use explicit dependency versions and commit the lockfile for reproducible installs.
Authentication & access
- Authenticate protected APIs
Verify authentication on the server for every endpoint that exposes private data or actions.
- Test object ID swapping
Try accessing another user’s records by changing IDs in URLs and requests. Confirm that access is denied.
- Test row-level security
Where row-level security is used, verify read and write policies with different users, roles, and tenants.
- Use established authentication
Use a maintained authentication library or provider instead of designing your own login and password handling.
- Revoke sessions
Verify that sessions can be invalidated. Use appropriate token lifetimes and test logout and account revocation.
Authorization & input validation
- Check administrator permissions on the server
Enforce privileged actions on the backend. Hiding an admin button is not an authorization check.
- Throttle authentication attempts
Rate-limit login, signup, and password-reset endpoints to reduce brute force and abuse.
- Validate server input
Validate types, lengths, allowed values, and request sizes on the server. Client validation can be bypassed.
- Parameterize SQL
Use bound query parameters. Never concatenate untrusted input into SQL queries.
- Encode user content
Escape output for its HTML, URL, or JavaScript context. Sanitize any user HTML that you intentionally allow.
Data, integrations & cost
- Restrict CORS
Allow only the origins that need browser access. Keep authentication and authorization checks in place independently.
- Keep storage private
Make buckets and uploaded objects private by default. Grant access only to the users who need it.
- Isolate uploads
Validate file types and sizes, store uploads away from executable application code, and isolate file processing.
- Verify webhooks
Verify the provider’s signature before processing a webhook. Reject invalid requests and handle replayed events safely.
- Cap AI spending
Enforce usage budgets and a cutoff for paid AI calls. Alerts alone do not stop spending.
AI & agents
- Throttle AI calls
Apply per-user or per-tenant request and concurrency limits to prevent credit draining.
- Treat model input as untrusted
Account for prompt injection in user input, retrieved documents, and tool results. Keep permission checks outside the model.
- Constrain agent tools
Limit tool access and permissions, especially SQL and shell execution. Require approval for sensitive actions.
- Verify AI-suggested packages
Check package names, sources, and maintainers before installing dependencies suggested by a model.
- Review agent configuration
Review agent instructions, skills, and MCP connections. Check what they can execute and which data they can access.
Production & recovery
- Scope production credentials
Keep production credentials out of agent prompts and workspaces unless explicitly needed. Grant only the required access.
- Hide stack traces
Return generic public errors. Keep detailed diagnostic information in restricted internal systems.
- Redact logs
Remove credentials, tokens, and unnecessary personal data from application logs and traces.
- Keep audit trails
Record who performed sensitive actions, what changed, and when. Restrict access to audit records.
- Test database restores
Restore a backup in an isolated environment and verify the recovered data. A successful backup job is not a restore test.