shieldstack-ts
v0.1.0
Published
High-performance TypeScript-native LLM security & observability middleware
Maintainers
Readme
Overview
ShieldStack TS is a framework-agnostic, edge-compatible middleware layer that sits between your application and any LLM provider — OpenAI, Anthropic, Ollama, and others.
It intercepts every request and response with sub-2ms overhead, enforcing your security policies without changing your application logic.
Your App ──► ShieldStack ──► LLM Provider
↑ ↑ ↑ ↑
│ │ │ └─ Token Budget Enforcement
│ │ └──── Secrets Detection
│ └─────── Prompt Injection Defense
└────────── PII RedactionFeatures
| Feature | Description |
|---|---|
| 🔐 PII Redaction | Automatically strips emails, phone numbers, credit cards, and SSNs |
| 🛡️ Injection Detection | Heuristic risk-scoring blocks jailbreak and system-override attempts |
| 🔑 Secrets Scanning | Detects AWS keys, GitHub/Slack tokens, and high-entropy strings |
| 💰 Denial-of-Wallet Prevention | Per-user async token budgets backed by in-memory or Redis storage |
| 🌊 Stream Sanitization | Real-time chunk-level redaction via native TransformStream API |
| 📊 Audit Logging | Structured JSON telemetry for every security event |
| ✅ Schema Validation | Enforce structured LLM output contracts with Zod |
| ⚡ Edge-First | Runs on Node.js, Bun, and Cloudflare Workers — zero native dependencies |
Installation
npm install shieldstack-tsQuick Start
import { ShieldStack } from 'shieldstack-ts';
const shield = new ShieldStack({
pii: {
policy: 'redact', // 'redact' | 'hash' | 'mask' | 'block'
emails: true,
creditCards: true,
phoneNumbers: true,
},
injectionDetection: {
threshold: 0.8, // 0.0 (lenient) – 1.0 (strict)
},
tokenLimiter: {
maxTokens: 10000, // max tokens per user per window
windowMs: 3600000, // 1 hour
},
});
// Evaluate a prompt before sending to your LLM
// Throws if blocked, returns sanitized text if safe
const safePrompt = await shield.evaluateRequest(userInput, userId, tokenEstimate);
// Sanitize the LLM's streaming response in real-time
const sanitizedStream = llmResponse.body.pipeThrough(shield.createStreamSanitizer());Framework Adapters
Express.js
import { expressShield } from 'shieldstack-ts';
app.post('/chat', expressShield(shield), (req, res) => {
// req.body is already PII-sanitized
});Next.js App Router
import { withShield } from 'shieldstack-ts';
async function chatHandler(req: Request): Promise<Response> {
// your handler
}
export const POST = withShield(shield, chatHandler);Hono (Cloudflare Workers)
import { honoShield } from 'shieldstack-ts';
app.use('/chat', honoShield(shield));Distributed Rate Limiting with Redis
For multi-server deployments, pass a Redis client to share token budgets across all instances:
import { ShieldStack, RedisStore } from 'shieldstack-ts';
import { Redis } from '@upstash/redis'; // or ioredis, node-redis
const shield = new ShieldStack({
tokenLimiter: {
maxTokens: 50000,
windowMs: 3600000,
store: new RedisStore(new Redis({ url: process.env.REDIS_URL })),
},
});Duck-typed client support — any Redis client implementing
.get(),.set(), and.del()works without forced peer dependencies.
Redaction Policies
Configure how PII is handled per field type:
| Policy | Result | Use Case |
|---|---|---|
| redact | [REDACTED_EMAIL] | Maximum privacy |
| hash | [HASHED_EMAIL] | Pseudonymous, consistent |
| mask | *** | Visual concealment |
| block | Throws error | Zero-tolerance compliance |
Structured Output Validation
Enforce a Zod schema on LLM responses to prevent hallucinated shapes:
import { z } from 'zod';
const responseSchema = z.object({
answer: z.string(),
confidence: z.number().min(0).max(1),
});
const shield = new ShieldStack({ schema: responseSchema });
// Validates and throws if LLM output doesn't match
const validatedOutput = shield.validateOutput(llmJsonResponse);Performance
| Operation | Overhead | |---|---| | Token limit check (in-memory) | < 0.1ms | | Token limit check (Redis) | 1–3ms | | Injection detection | < 0.5ms | | PII redaction | < 1ms | | Stream sanitization per chunk | < 0.2ms | | Total end-to-end | < 2ms |
LLM calls take 500ms–5s. ShieldStack adds less than 0.4% overhead.
Testing
npm run test✓ tests/pii.test.ts (3 tests)
✓ tests/injection.test.ts (3 tests)
✓ tests/tokenLimiter.test.ts (3 tests)
✓ tests/redisStore.test.ts (6 tests)
Test Files 4 passed
Tests 15 passedRunning the Demo
A full Next.js demo app is included to visualize the middleware in real-time:
cd examples/demo
npm install
npm run dev
# Open http://localhost:3000Try sending:
- A prompt containing a fake email → watch
[REDACTED_EMAIL]appear in the stream "Ignore previous instructions"→ watch it get blocked with a 403 error
Docker
Build the production image:
docker build -t shieldstack-demo .Run the full stack (Demo + Redis):
docker compose up --buildUses a 3-stage multi-stage build for a minimal (~80MB), non-root, production-hardened container image.
Compatibility
| Runtime | Supported | |---|---| | Node.js 18+ | ✅ | | Bun 1.x | ✅ | | Cloudflare Workers | ✅ | | Deno (via npm compat) | ✅ | | AWS Lambda | ✅ |
Contributing
Contributions, issues, and feature requests are welcome! See CONTRIBUTING.md for guidelines.
- Fork the repository
- Create your feature branch:
git checkout -b feat/my-feature - Commit your changes:
git commit -m 'feat: add my feature' - Push to the branch:
git push origin feat/my-feature - Open a Pull Request
Security
To report a vulnerability, see SECURITY.md. Please do not open a public GitHub issue for security concerns.
License
MIT © Ali Shuja
