Skip to content
Back to skills

Fetch Redirect Ssrf Guard

ASecurity

SSRF prevention via redirect chain control in HTTP fetch. Block automatic redirect following to internal IPs, validate post-redirect destination, manual redirect handling, and timeout enforcement. Sources: node-fetch/node-fetch, OWASP SSRF Cheat Sheet.

  • 10 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 9, 2026
ai-agentsjavascriptrustgojavanode

Works with

  • cli

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add yanacuti1121/Yana-AI --skill fetch-redirect-ssrf-guard --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Fetch Redirect Ssrf Guard?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Fetch Redirect Ssrf Guard
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yanacuti1121-fetch-redirect-ssrf-guard/badge)](https://www.skillsdirectory.com/skills/yanacuti1121-fetch-redirect-ssrf-guard)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: fetch-redirect-ssrf-guard
description: SSRF prevention via redirect chain control in HTTP fetch. Block automatic redirect following to internal IPs, validate post-redirect destination, manual redirect handling, and timeout enforcement. Sources: node-fetch/node-fetch, OWASP SSRF Cheat Sheet.
origin: yana-ai — synthesized from node-fetch/node-fetch (MIT), OWASP SSRF Prevention Cheat Sheet
license: Apache-2.0
version: 1.0.0
compatibility: yana-ai >= 1.3.48
---

# /fetch-redirect-ssrf-guard

## When to Use

- Any HTTP fetch from agent code that follows redirects
- Blocking open-redirect + SSRF chains (trusted URL → redirect → internal IP)
- Enforcing connection timeouts to prevent slow-loris attacks
- Audit-logging all external HTTP calls (pairs with [[http-proxy-intercept]])

## Do NOT use for

- Blocking DNS rebinding (use network namespace + no async DNS lookup after allowlist check)
- Client-side fetch in browser (use CSP + fetch policies instead)

---

## Safe fetch wrapper (no auto-redirect)

```javascript
import fetch, { Response } from 'node-fetch'
import { URL }             from 'url'

const SSRF_RANGES = [
  /^127\./,
  /^10\./,
  /^192\.168\./,
  /^172\.(1[6-9]|2\d|3[01])\./,
  /^169\.254\./,
  /^::1$/,
  /^fd[0-9a-f]{2}:/i,
  /metadata\.(google\.internal|internal)$/,
]

function isSsrfTarget(host: string): boolean {
  return SSRF_RANGES.some(r => r.test(host))
}

export async function safeFetch(
  url: string,
  options: Parameters<typeof fetch>[1] = {}
): Promise<Response> {
  // 1. Parse and validate initial URL
  let parsed: URL
  try { parsed = new URL(url) }
  catch { throw new Error(`[fetch] invalid URL: ${url}`) }

  if (isSsrfTarget(parsed.hostname)) {
    throw new Error(`[fetch] SSRF blocked: ${parsed.hostname}`)
  }

  // 2. Disable automatic redirect following
  const res = await fetch(url, {
    ...options,
    redirect: 'manual',           // never follow automatically
    follow:   0,                  // node-fetch: 0 = manual
    timeout:  10_000,             // 10s hard timeout
    size:     5 * 1024 * 1024,   // max 5MB response
  })

  // 3. If redirect, validate destination before following
  if (res.status >= 300 && res.status < 400) {
    const location = res.headers.get('location')
    if (!location) throw new Error('[fetch] redirect with no Location header')

    const redirectTo = new URL(location, url)
    if (isSsrfTarget(redirectTo.hostname)) {
      throw new Error(`[fetch] SSRF via redirect: ${redirectTo.hostname}`)
    }

    // Follow once (max depth 1 — no chain following)
    return safeFetch(redirectTo.href, { ...options, redirect: 'manual' })
  }

  return res
}
```

---

## Timeout + size enforcement

```javascript
// AbortController for hard timeout (works with native fetch)
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), 10_000)

try {
  const res = await fetch(url, { signal: controller.signal })
  clearTimeout(timer)

  // Enforce response size
  const buf = await res.arrayBuffer()
  if (buf.byteLength > 5 * 1024 * 1024) {
    throw new Error('[fetch] response too large')
  }
  return Buffer.from(buf).toString()
} catch (err) {
  clearTimeout(timer)
  throw err
}
```

---

## Anti-Fake-Pass Checklist

```
❌ redirect:'follow' (default) → attacker redirects trusted URL to 169.254.169.254
❌ No hostname validation after redirect → DNS rebinding bypasses initial check
❌ No timeout → agent hangs on slow-loris connection
❌ No response size limit → agent downloads 1GB payload, OOM
❌ URL constructor not used → regex validation on raw string misses edge cases
❌ Only checking IPv4 SSRF ranges → IPv6 fd::/8 and ::1 bypass
❌ redirect depth > 1 → chained redirects tunnel through to internal network
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.