require-abort-signal
This rule identifies streaming AI SDK calls (`streamText`, `streamObject`) that don't include an AbortSignal for cancellation.
Ensures streaming calls have AbortSignal for graceful cancellation.
📊 Rule Details
| Property | Value |
|---|---|
| Type | suggestion |
| Severity | ⚪ LOW |
| OWASP LLM | LLM10: Unbounded Consumption |
| CWE | CWE-404: Improper Resource Shutdown |
| CVSS | 4.0 |
| Config Default | off (recommended), warn (strict) |
🔍 What This Rule Detects
This rule identifies streaming AI SDK calls (streamText, streamObject) that don't include an AbortSignal for cancellation.
❌ Incorrect Code
// No abort signal
await streamText({
model: openai('gpt-4'),
prompt: 'Stream a long response',
});
// Missing signal in streamObject
await streamObject({
model: anthropic('claude-3'),
prompt: 'Generate object',
schema: mySchema,
});✅ Correct Code
// With abort signal
const controller = new AbortController();
await streamText({
model: openai('gpt-4'),
prompt: 'Stream a long response',
abortSignal: controller.signal,
});
// Using signal property
await streamObject({
model: anthropic('claude-3'),
prompt: 'Generate object',
schema: mySchema,
signal: abortController.signal,
});⚙️ Options
| Option | Type | Default | Description |
|---|---|---|---|
signalPropertyNames | string[] | ['abortSignal', 'signal'] | Property names that provide abort signals |
🛡️ Why This Matters
Without abort signals:
- Resource leaks - Streams continue after user navigation
- Wasted costs - Tokens consumed after request cancelled
- Server overhead - Backend continues processing
- Poor UX - No way to cancel long operations
🔗 Related Rules
require-max-tokens- Limit token consumptionrequire-error-handling- Handle errors
Known False Negatives
The following patterns are not detected due to static analysis limitations:
Signal from Variable
Why: Signal stored in variables is not analyzed.
// ❌ NOT DETECTED - Signal from variable
const options = { signal: controller.signal };
await streamText({ model: openai('gpt-4'), ...options });Mitigation: Use inline signal property.
Framework-Provided Signal
Why: Framework signals are not visible.
// ❌ NOT DETECTED (correctly) - Next.js handles signals
export async function GET(req: Request) {
// req.signal provided by Next.js
return streamText({ ..., abortSignal: req.signal });
}Mitigation: Document framework signal handling.
Wrapper Functions
Why: Custom wrappers may include signal internally.
// ❌ NOT DETECTED - Wrapper adds signal
await myStreamText(prompt); // Wrapper adds signal internallyMitigation: Apply rule to wrapper implementations.
📚 References
no-unsafe-output-handling
This rule identifies code patterns where AI-generated output is passed directly to dangerous functions that can execute code, manipulate the DOM, or run databas
require-audit-logging
This rule identifies AI SDK calls that aren't preceded by logging statements. Audit logging is important for security monitoring and debugging.