Security
Security policies and practices
Security
SoulCache takes security seriously.
Reporting Vulnerabilities
If you discover a security vulnerability, please report it responsibly:
Security Reporting
- Do not open a public issue or pull request
- Email the maintainer or use GitHub's private vulnerability reporting
- Include a description of the vulnerability
- Include steps to reproduce
Security Practices
Zero Runtime Dependencies
SoulCache has zero runtime dependencies, eliminating supply chain risks.
No Remote Code Execution
SoulCache does not execute remote code or use eval().
No Secret Logging
SoulCache does not log sensitive data.
Type Safety
Full TypeScript with strict mode prevents common security issues.
Best Practices
Security Guidelines
- Keep dependencies updated — Use latest versions
- Use environment variables — Don't hardcode secrets
- Validate inputs — Always validate data from external sources
- Use HTTPS — Encrypt data in transit
Scope query keys per user or tenant
Request deduplication is single-flight per query key: two concurrent calls with the same key share one promise. For user-scoped data, always include the user or tenant in the query key so one user can never receive another user's cached response. On a server with a shared cache, prefer a per-request cache instance or key every user-scoped query with the request's user context.
Only hydrate state you can authenticate
hydrate(cache, state) writes whatever state it is given and overwrites
existing entries by default. Only hydrate state from a trusted source (e.g. a
server-signed SSR payload). Use mergeStrategy: 'skip' or 'merge', or a
filter, to limit what is written.
Checksums detect corruption, not tampering
Persistence checksums are unkeyed and detect accidental data corruption. An attacker who can modify persisted bytes can recompute the checksum. If persisted data must be tamper-resistant, protect the storage layer or authenticate the payload (e.g. HMAC-SHA-256 with a server-held secret) before persistence.
Do not ship error.stack to clients
dehydrate() omits error.stack by default. Keep it that way in production;
pass includeStack: true only for server-side debugging.