Ssrf prevention
Skill ShieldNet-360/secure-vibe/dist/copilot-skills/.github/skills/ssrf-prevention
Defend against Server-Side Request Forgery: cloud metadata blocking, internal IP filtering, DNS rebinding defense, allowlist-based URL fetching — Applies to: when generating code that fetches a URL supplied by the client; when wiring webhooks, image proxies, PDF renderers, oEmbed fetchers; when running in any cloud environment with an instance metadata service; when reviewing a URL-parsing or HTTP-client wrapperFrom its SKILL.md
npx -y skills add ShieldNet-360/secure-vibe --skill ssrf-preventionAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 15 stars15 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.0 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it
SSRF Prevention
Defend against Server-Side Request Forgery: cloud metadata blocking, internal IP filtering, DNS rebinding defense, allowlist-based URL fetching
ALWAYS
- Validate every URL fetched on behalf of a client through an allowlist of expected hosts. The allowlist is the only durable defense — block-lists are bypassable through encoding tricks, IPv6 dual-stack, and DNS rebinding.
- Resolve the hostname once, validate the resolved IP against your block-list of private / reserved / link-local ranges, then connect to that pinned IP using SNI. Otherwise an attacker can race a DNS rebind between validation and connect (
time-of-check / time-of-use). - Block at the network layer and at the application layer. Drop egress to
169.254.169.254,[fd00:ec2::254],metadata.google.internal, and100.100.100.200from any service that doesn't legitimately need the metadata service. - Enforce IMDSv2 on AWS EC2 (session-token, hop-limit=1). IMDSv1 — the pattern Capital One's 2019 breach exploited — must be disabled at the instance level.
- Disable HTTP redirects by default on server-side fetchers (or follow only a small bounded number, re-validating the new URL against the allowlist at each hop). The most common SSRF bypass is
https://allowed.example.comreturning a 302 tohttp://169.254.169.254/.... - Use a separate, restricted HTTP client for user-controlled URLs vs internal URLs. Misusing the wrong client must fail closed (e.g. via type-system distinction in Go / Rust / TypeScript).
- Parse URLs with a single, well-known parser (Go
net/url.Parse, Pythonurllib.parse, JavaScriptnew URL()). Differential parsers between e.g. WHATWG and RFC-3986 are a documented SSRF bypass class.
NEVER
- Trust a hostname / IP that was supplied by the user. Always re-resolve in your trusted resolver and re-check the resolved address.
- Connect to a URL based on its hostname when the protocol allows redirects —
gopher://,dict://,file://,jar://,netdoc://,ldap://are all common SSRF amplifiers. Restrict tohttp://andhttps://(andftp://only if you actually need it). - Trust
0.0.0.0,127.0.0.1,[::],[::1],localhost, or*.localhost.test— all of them reach the local instance. The list also must include link-local169.254.0.0/16, IPv4-mapped IPv6::ffff:127.0.0.1, and IPv6 ULAfc00::/7. - Use the user's URL string in a logging line or an error response — it can be the SSRF reflection oracle that turns blind SSRF into data-exfiltration SSRF.
- Run a metadata-blocking sidecar / proxy as the only defense — an attacker who finds a Unix-domain-socket pseudo-URL or a misconfigured hostname can route around the proxy. Application-level allowlist remains required.
- Ship a generic request forwarder that switches to fetching a full, caller-supplied URL when the input "looks absolute" (
path.startsWith('http') ? path : base + path). It is a latent SSRF: the day any caller passes user-influenced input, the server fetches an attacker URL — internal hosts and cloud metadata included. Keep the internal-base fetcher and the user-URL fetcher as distinct, type-separated clients. - Treat "this endpoint is only reachable from our internal / VPN / allowlisted network" as mitigation for an unsafe server-side fetch. SSRF originates from inside that network, so it reaches exactly the internal services the network control was meant to protect — an IP allowlist is not an authentication boundary against SSRF.
- Allow IDN / Punycode in user URLs without normalization — IDN homograph attacks bypass naive string-allowlist checks (
gооgle.comCyrillic-o ≠google.com).
KNOWN FALSE POSITIVES
- Server-to-server integrations where both sides are operator-controlled and the URL is hard-coded in config (not user-supplied) — the allowlist here is the static config itself.
- Cluster-local Kubernetes service-to-service calls — these don't go through user input, but be aware of any cross-namespace network policy.
- Outbound webhooks to the customer (e.g. Slack, Discord, Microsoft Teams webhooks). Validate that the URL host is in the integration's documented allowlist, not arbitrary.
- A forwarder that uses a hard-coded absolute URL constant (the base is a literal, only a query string or path segment is appended from input) does not change host — the SSRF exists only when the absolute URL itself can be influenced by user input.
What ships with it: 1 file
1.1 KB alongside SKILL.md
- metadata.json1.1 KB