Skip to main content
interlace
Plugin: vercel-ai-securityRules

require-request-timeout

This rule identifies AI SDK calls that don't have timeout or abort signal configuration.

Requires timeout configuration for AI SDK calls to prevent DoS.

📊 Rule Details

PropertyValue
Typesuggestion
Severity🟡 MEDIUM
OWASP LLMLLM04: Model Denial of Service
CWECWE-400: Uncontrolled Resource Consumption
CVSS5.0
Config Defaultoff (recommended), error (strict)

🔍 What This Rule Detects

❌ Incorrect Code

// No timeout
await generateText({
  model: openai('gpt-4'),
  prompt: 'Hello',
});

// Missing timeout in stream
await streamText({
  model: openai('gpt-4'),
  prompt: userInput,
  maxTokens: 4096,
});

✅ Correct Code

// With abort signal timeout
const controller = new AbortController();
setTimeout(() => controller.abort(), 30000);
await generateText({
  model: openai('gpt-4'),
  prompt: 'Hello',
  abortSignal: controller.signal,
});

// With timeout property
await streamText({
  model: openai('gpt-4'),
  prompt: userInput,
  timeout: 30000,
});

⚙️ Options

OptionTypeDefaultDescription
allowInTestsbooleantrueSkip in test files

🛡️ Why This Matters

Missing timeouts can cause:

  • Denial of service - Requests hang indefinitely
  • Resource exhaustion - Threads/connections blocked
  • Cost explosion - Long-running requests accumulate costs
  • Poor UX - Users wait forever

🔄 Changes in the 2026-10-10 FP/FN audit

  • generateText(opts) with options built elsewhere is no longer reported (the options may carry a timeout); a call with no options at all still is.
  • A spread in the options may carry the timeout and counts.
  • Now off in recommended; it duplicated require-abort-signal on the same calls.
  • Options: the documented defaultOptions now apply. Earlier versions read context.options and silently ran a shorter hard-coded list instead.

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Options from Variable

Why: Options stored in variables are not analyzed.

// ❌ NOT DETECTED - Options from variable
const opts = { model: openai('gpt-4'), prompt: 'Hello' }; // No timeout
await generateText(opts);

Mitigation: Use inline options. Always specify timeout.

Wrapper Functions

Why: Custom wrappers may include timeout internally.

// ❌ NOT DETECTED - Wrapper adds timeout
await myGenerateText(prompt); // Wrapper sets timeout

Mitigation: Apply rule to wrapper implementations.

External Timeout Management

Why: Timeout managed outside the call is not visible.

// ❌ NOT DETECTED - Promise.race timeout
await Promise.race([
  generateText({ ... }),
  timeout(30000)
]);

Mitigation: Use built-in timeout/abort signal properties.

Framework-Level Timeouts

Why: Framework request timeouts are not linked.

// ❌ NOT DETECTED (correctly) - Express timeout middleware
app.use(timeout(30000));

Mitigation: Document framework timeout handling.

📚 References

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

🔒 CWE-400 OWASP:A06 CVSS:7.5 | Uncontrolled Resource Consumption (ReDoS) detected | HIGH
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A06_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-400 OWASP:A06 CVSS:7.5
Issue DescriptionSpecific vulnerabilityUncontrolled Resource Consumption (ReDoS) detected
Severity & ComplianceImpact assessmentHIGH
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Use this rule

npm install -D oxlint-plugin-vercel-ai-security
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-vercel-ai-security"],  "rules": {    "vercel-ai-security/require-request-timeout": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-vercel-ai-security'],    rules: {      'vercel-ai-security/require-request-timeout': 'error',    },  },});

oxlint-plugin-vercel-ai-security re-exports eslint-plugin-vercel-ai-security/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.