Claude
Skills
Sign in
Back

resource-exhaustion-dos-ai-generated-code

Included with Lifetime
$97 forever

Understand resource exhaustion and denial of service vulnerabilities in AI code including unbounded loops, missing rate limits, and uncontrolled resource consumption. Use this skill when you need to learn about DoS vulnerabilities in AI code, understand resource limits, recognize unbounded operations, or prevent resource exhaustion. Triggers include "resource exhaustion", "DoS vulnerabilities", "denial of service", "unbounded resources", "API cost protection", "memory exhaustion", "uncontrolled consumption", "rate limiting DoS".

Backend & APIs

What this skill does


# Resource Exhaustion and Denial of Service in AI-Generated Code

## The Performance Security Nexus

Research from Databricks highlights:

> "Vibe coding often produces functionally correct but resource-inefficient code that can be exploited for denial of service attacks."

The AI's focus on **functionality over performance** creates multiple attack vectors.

## 1.6.1 Uncontrolled Resource Consumption

### The Problem

AI generates code that works perfectly for normal use but has no limits on resource consumption. This creates two major risks:

1. **Denial of Service (DoS):** Attackers overwhelm server, making it unavailable
2. **Cost Explosion:** Attackers abuse expensive operations (AI APIs, compute)

### AI-Generated Vulnerable Code

```javascript
// Prompt: "Create image processing endpoint"
app.post('/process-image', async (req, res) => {
    const { imageUrl, operations } = req.body;

    // ❌ VULNERABLE: No size or quantity limits
    const imageBuffer = await downloadImage(imageUrl);

    let processedImage = imageBuffer;

    // ❌ VULNERABLE: Unbounded loop
    for (const operation of operations) {
        processedImage = await applyOperation(processedImage, operation);
    }

    res.send(processedImage);
});

// Attack: Send huge image or hundreds of operations
// Result: Server memory exhaustion and crash
```

### Multiple Vulnerabilities in This Code

**1. No Image Size Limit:**
```javascript
const imageBuffer = await downloadImage(imageUrl);
```

**Attack:**
- Upload 500MB image
- Server downloads entire image to memory
- Multiple concurrent requests
- Server runs out of memory → crash

**2. No Operation Count Limit:**
```javascript
for (const operation of operations) {
    processedImage = await applyOperation(processedImage, operation);
}
```

**Attack:**
- Send 1000 operations
- Each operation processes image
- Server CPU at 100% for minutes
- Legitimate requests time out

**3. No Rate Limiting:**
```javascript
app.post('/process-image', async (req, res) => {
```

**Attack:**
- Send 10,000 requests simultaneously
- Server processes all (no queue)
- Server crashes or becomes unresponsive

**4. No Timeout:**
- Long-running operations never cancelled
- Malicious requests occupy resources forever
- Server capacity exhausted

**5. No Validation:**
- imageUrl could be anything
- Could point to 10GB file
- Could be internal URL (SSRF attack)

### The $200,000 AI Cost Attack (Real Story)

One startup built a "summarize any article" AI feature without rate limiting:

**Timeline:**
- **T+0:** Feature launches (no rate limiting)
- **T+10 min:** Malicious user scripts 10,000 requests
- **T+10 min:** 10,000 OpenAI API calls made ($0.96 per call average)
- **T+10 min:** **$9,600 in charges**
- **T+4 hours:** Attack still running, unnoticed
- **T+4 hours:** **Total cost exceeds $200,000**
- **T+5 hours:** Startup notices, shuts down endpoint
- **Outcome:** Near bankruptcy, scramble for emergency funding

**What went wrong:**
- No rate limiting (unlimited requests)
- No request queuing (all processed immediately)
- No cost monitoring alerts
- No maximum spend limits on OpenAI API

### Secure Implementation

```javascript
const rateLimit = require('express-rate-limit');
const sharp = require('sharp');

// ✅ SECURE: Rate limiting
const imageLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 10, // 10 requests per window
    message: 'Too many requests, please try again later',
    standardHeaders: true,
    legacyHeaders: false,
});

// ✅ SECURE: Request size limiting
app.use(express.json({ limit: '1mb' }));

// ✅ SECURE: Resource limits configuration
const LIMITS = {
    MAX_IMAGE_SIZE: 10 * 1024 * 1024, // 10MB
    MAX_IMAGE_DIMENSION: 4000, // pixels
    MAX_OPERATIONS: 5,
    DOWNLOAD_TIMEOUT: 5000, // 5 seconds
    PROCESSING_TIMEOUT: 30000, // 30 seconds
    MAX_CONCURRENT_JOBS: 3
};

// ✅ SECURE: Job queue for controlled concurrency
const Queue = require('bull');
const imageQueue = new Queue('image-processing', {
    redis: {
        port: 6379,
        host: '127.0.0.1',
    },
    defaultJobOptions: {
        timeout: LIMITS.PROCESSING_TIMEOUT,
        attempts: 2,
        removeOnComplete: true,
        removeOnFail: true
    }
});

// ✅ SECURE: Controlled image download
async function downloadImageSecure(url, limits) {
    // Validate URL
    const urlPattern = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b/;
    if (!urlPattern.test(url)) {
        throw new Error('Invalid URL');
    }

    // ✅ SECURE: Prevent SSRF by checking against internal IPs
    const parsed = new URL(url);
    if (isInternalIP(parsed.hostname)) {
        throw new Error('Access to internal resources not allowed');
    }

    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), limits.DOWNLOAD_TIMEOUT);

    try {
        const response = await fetch(url, {
            signal: controller.signal,
            size: limits.MAX_IMAGE_SIZE, // Limit response size
            headers: {
                'User-Agent': 'ImageProcessor/1.0'
            }
        });

        clearTimeout(timeout);

        // ✅ SECURE: Validate content type
        const contentType = response.headers.get('content-type');
        if (!contentType || !contentType.startsWith('image/')) {
            throw new Error('Invalid content type');
        }

        // ✅ SECURE: Check content length
        const contentLength = parseInt(response.headers.get('content-length'));
        if (contentLength > limits.MAX_IMAGE_SIZE) {
            throw new Error('Image too large');
        }

        return await response.buffer();
    } finally {
        clearTimeout(timeout);
    }
}

app.post('/process-image', imageLimiter, async (req, res) => {
    const { imageUrl, operations } = req.body;

    // ✅ SECURE: Validate operations count
    if (!Array.isArray(operations) || operations.length > LIMITS.MAX_OPERATIONS) {
        return res.status(400).json({
            error: `Maximum ${LIMITS.MAX_OPERATIONS} operations allowed`
        });
    }

    // ✅ SECURE: Queue job instead of processing directly
    const job = await imageQueue.add('process', {
        imageUrl,
        operations,
        userId: req.user?.id,
        ip: req.ip
    });

    res.json({
        jobId: job.id,
        status: 'queued',
        estimatedTime: await imageQueue.getJobCounts()
    });
});

// ✅ SECURE: Process jobs with resource controls
imageQueue.process('process', LIMITS.MAX_CONCURRENT_JOBS, async (job) => {
    const { imageUrl, operations } = job.data;

    // Download with limits
    const imageBuffer = await downloadImageSecure(imageUrl, LIMITS);

    // ✅ SECURE: Use sharp with resource limits
    let pipeline = sharp(imageBuffer, {
        limitInputPixels: LIMITS.MAX_IMAGE_DIMENSION ** 2,
        sequentialRead: true, // Lower memory usage
    });

    // Get image metadata to validate
    const metadata = await pipeline.metadata();

    if (metadata.width > LIMITS.MAX_IMAGE_DIMENSION ||
        metadata.height > LIMITS.MAX_IMAGE_DIMENSION) {
        throw new Error('Image dimensions exceed limits');
    }

    // ✅ SECURE: Apply operations with validation
    for (const op of operations) {
        pipeline = applyOperationSecure(pipeline, op, LIMITS);
    }

    // ✅ SECURE: Output with format restrictions
    const output = await pipeline
        .jpeg({ quality: 80, progressive: true })
        .toBuffer();

    // Store result temporarily
    await storeResult(job.id, output);

    return {
        success: true,
        resultId: job.id,
        size: output.length
    };
});

function applyOperationSecure(pipeline, operation, limits) {
    const { type, params } = operation;

    // ✅ SECURE: Whitelist allowed operations
    const allowedOps = ['resize', 'rotate', 'blur', 'sharpen', 'grayscale'];

    if (!allowedOps.includes(type)) {
        throw new Error(`Operation '${type}' not allowed`);
    }

    sw

Related in Backend & APIs