Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
中文简介正在准备中。当前显示原文说明。
Use when the server side of the diff fetches, renders, redirects to or validates a URL that input can influence - webhooks, link previews, import-from-URL, PDF renderers, OAuth/JWKS discovery, allowlist and blocklist checks
中文简介正在准备中。当前显示原文说明。
查看安装方法安装前可以查看交给 AI 代理的指令内容。
Server-side request forgery turns your server into the attacker's network client — inside your VPC, past your firewall, next to the cloud metadata service. Since OWASP Top 10:2025 it sits under A01 Broken Access Control (CWE-918).
Core principle: validate the address you actually connect to, after DNS, on every hop — not the string the user typed.
http://169.254.169.254/latest/meta-data/iam/security-credentials/) answers a plain GET with credentials. IMDSv2 (PUT-token), GCP (Metadata-Flavor: Google) and Azure (Metadata: true) require a header a simple SSRF usually cannot set — check what the deployment runs before calling it CRITICAL.// ❌ substring: "https://example.com.evil.net" and "https://evil.net/?x=example.com" pass
if (!url.includes("example.com")) throw new Error("blocked");
// ❌ suffix without a dot boundary: "https://evilexample.com" passes
if (!new URL(url).hostname.endsWith("example.com")) throw ...
// ❌ regex with an unescaped dot and no end anchor: "https://api.example.com.evil.net"
if (!/^https:\/\/api.example.com/.test(url)) throw ...
// ✅ parse once, compare exact host (or a dot-bounded suffix), fixed scheme
const u = new URL(url);
const ok = u.protocol === "https:" && (u.hostname === "example.com" || u.hostname.endsWith(".example.com"));
Parser tricks that defeat string checks:
https://example.com@evil.net/ — the host is evil.net.https://evil.net\@example.com/ — validators and HTTP clients disagree (WHATWG vs RFC 3986). Validate with the same parser the fetcher uses, or better, the fetcher's resolved address.new URL(userPath, base), Python urljoin(base, user) and Java URI.resolve let //evil.net/x or a full https://evil.net replace the base host.A blocklist on the URL string misses:
http://2130706433/, http://0x7f.1/, http://0177.0.0.1/, http://127.1/, http://0.0.0.0/;http://[::1]/, http://[::ffff:127.0.0.1]/, http://[fd00::1]/;localhost., 127.0.0.1.nip.io, an attacker domain with an A record of 10.0.0.5;127.0.0.1;302 Location: http://169.254.169.254/… and the client follows it.// ✅ the check runs on the address actually dialled — after DNS, on every redirect hop
dialer := &net.Dialer{Control: func(_, address string, _ syscall.RawConn) error {
host, _, _ := net.SplitHostPort(address)
ip := net.ParseIP(host)
if ip == nil || ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsUnspecified() {
return errBlockedAddress
}
return nil
}}
client := &http.Client{Transport: &http.Transport{Proxy: nil, DialContext: dialer.DialContext}}
Proxy: nil matters: through a proxy the dialled address is the proxy's, and the check never sees the target. Add any internal ranges the deployment uses (for example 100.64.0.0/10). Node: a request-filtering agent that checks the resolved IP; Python: resolve, check with ipaddress (is_private, is_loopback, is_link_local, is_reserved), then connect to that IP with the original Host header and SNI.
file://, gopher://, dict://, ftp://, Java jar:/netdoc:, and everything libcurl supports. A fetcher that accepts a user URL must restrict the scheme to https (or http/https) before anything else.
<iframe src="http://169.254.169.254/…">, <img src="file:///etc/passwd">.xlink:href; XML parsers with external entities (injection-and-dangerous-sinks); OAuth/OIDC flows fetching a jwks_uri or discovery document from a token-supplied issuer; webhook test buttons; LLM browsing tools whose URL comes from model output (llm-and-agent-security).Full-read SSRF to internal services or credential-bearing metadata → HIGH to CRITICAL. Blind SSRF to an internal network with no known side effect → MEDIUM. Path-only control → not reported.
url.hostname as sufficient while the client follows redirects.fetch(userUrl) in a React component.http.Get(u), requests.get(u), fetch(u), RestTemplate/WebClient, HttpClient.send where u comes from a request body, a stored profile field or a webhook config.includes, contains, endsWith without a leading dot, or an unanchored regex.OWASP Top 10:2025 A01 Broken Access Control · CWE-918 · OWASP API Security Top 10 2023 API7
还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
中文简介正在准备中。当前显示原文说明。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
中文简介正在准备中。当前显示原文说明。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
中文简介正在准备中。当前显示原文说明。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
中文简介正在准备中。当前显示原文说明。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
中文简介正在准备中。当前显示原文说明。
Use when the repository keeps its alerting in code, or a person asks for alerts outside TaskTrooper - PrometheusRule YAML, a Cloud Monitoring alert policy in Terraform, a Datadog monitor, each routed to TaskTrooper's alert ingest URL so it opens an incident here
中文简介正在准备中。当前显示原文说明。