☠ badtests — malicious HTTP response server
Each endpoint returns a deliberately malformed HTTP response to test client resilience.
Click any endpoint to hit it directly.
📋
/logs — View all visitor IPs, user agents, headers, and timestamps
Content-Length Abuses
/cl-word — Content-Length: banana
Content-Length set to a word. Python accepts it, curl rejects.
/cl-empty — Content-Length: (empty)
Empty Content-Length header. Python accepts, curl rejects.
/cl-negative — Content-Length: -99999999999999999
Massive negative Content-Length. Python accepts, curl rejects.
/cl-huge — Content-Length: 99999999999999999
Claims ~100 petabytes. Both accept. curl reports remaining bytes.
/cl-zero — Content-Length: 0 (body sent)
CL is 0 but server sends "surprise!". Both read 0 bytes. Wire shows body was sent.
/cl-float — Content-Length: 3.14159
Float CL. curl truncates to 3 (returns "hel"). Python ignores it, returns all 5 bytes.
/cl-hex — Content-Length: 0xDEAD
Hex CL. curl treats as 0 (empty body). Python ignores it, returns all 5 bytes.
/cl-null — Content-Length: 5\x00
Null byte after digit. curl rejects (Nul byte in header). Python accepts silently.
Simple negative CL. curl rejects, Python accepts.
/cl-nan — Content-Length: NaN
NaN as CL. curl rejects, Python accepts.
/cl-inf — Content-Length: Infinity
Infinity as CL. curl rejects, Python accepts.
/cl-mismatch — Content-Length: 1 (body is 30 bytes)
CL says 1, body is 30 bytes. Both read exactly 1 byte. Extra data poisons keep-alive.
Content-Type Abuses
/ct-garbage — Content-Type: 200 random chars
Random printable chars with \n \r \t. Accidental CRLF injection. Different every time.
/ct-multi — Content-Type: 5 MIME types
Comma-separated MIME types. Both accept. RFC says only one allowed.
/ct-empty — Content-Type: (empty)
Empty Content-Type. Both accept without complaint.
/ct-null — Content-Type: text/\x00html
Null byte in MIME type. curl rejects, Python accepts with null present.
/ct-emoji — Content-Type: 💀/🔥
Emoji MIME type. Both accept. Violates HTTP/1.1 ASCII requirement.
/ct-mega — Content-Type: 10KB long
10,000 A characters. Both accept. No header length limit enforced.
/ct-crlf — Content-Type with CRLF injectionCRITICAL
🚨 CRITICAL: Injects X-Injected: true header via CRLF in Content-Type value. Works on BOTH.
/ct-semicolon — Content-Type with 50 charset params
50 repeated ;charset=utf-8 params. Both accept. Parser could waste cycles.
Status Code Abuses
Negative status code. Both reject.
Zero status code. Both reject.
Out-of-range 3-digit status. Both accept. RFC defines 100-599 only.
5-digit status code. Both reject.
Non-numeric status. Both reject.
curl accepts (no limit). Python rejects (LineTooLong >65536 bytes).
Both reject. Python hits 64KB line limit. curl chokes on 1MB buffer.
curl accepts all 1000. Python rejects (>100 headers).
Empty header name. Both accept. Violates RFC 7230.
curl rejects. Python silently drops the malformed line and continues.
/hdr-dup-cl — Duplicate Content-Length: 5 and 999CRITICAL
🚨 CRITICAL: Smuggling vector. curl uses second CL (999). Python sees both.
/hdr-null — Header with null bytes
curl rejects (Nul byte in header). Python accepts, drops the null header.
curl rejects (Header without colon). Python treats as line folding.
Body Abuses
/body-endless — Infinite body streamWARNING
⚠️ WARNING: Streams 1KB/sec forever. Use --max-time. Neither client protects against this.
/body-none — Content-Length: 5, no body
Promises 5 bytes, sends 0. curl reports transfer closed. Python returns empty, no error.
/body-binary — 4KB binary as text/html
Random binary with text/html Content-Type. Both accept. No content validation.
Transfer-Encoding Abuses
/te-invalid — Transfer-Encoding: banana
Unknown TE. Both accept and ignore it. RFC says this should be an error.
/te-double — Content-Length + Transfer-EncodingCRITICAL
🚨 CRITICAL: Smuggling vector. curl prefers CL, Python prefers TE. Clients disagree.
/te-bad-chunk — Chunked with ZZZ chunk size
Invalid hex in chunk size. Both correctly reject.
Protocol Abuses
/proto-garbage — 512 random bytes (no HTTP)
Pure garbage. Both reject.
/proto-empty — Empty response (0 bytes)
Server closes immediately. Both reject.
Unknown HTTP version. Both reject.
Zero headers. Both accept. Valid in HTTP/1.0 but violates HTTP/1.1.
Only blank CRLF lines. Both reject.
Encoding Abuses
/enc-utf16 — Body is UTF-16, header says UTF-8
Mismatched encoding. Both accept raw bytes. Consuming app would decode garbage.
/enc-gzip-lie — Content-Encoding: gzip (plaintext body)
Claims gzip, sends plaintext. Both accept without decompressing by default.
Redirect Abuses
/redir-self — 301 → /redir-self (loop)
Infinite redirect loop. curl follows up to --max-redirs. Python http.client does not follow.
/redir-garbage — 301 → \x00\xff://💀:99999/../../etc/passwd
Garbage URL with null bytes, emoji, bad port, path traversal. curl rejects, Python accepts (SSRF risk).
/redir-chain — 302 → /redir-chain?n=N+1 (infinite unique chain)
Infinite redirect with unique URLs each hop. Defeats redirect loop detection. curl follows --max-redirs (default 50).
Timing Abuses
/slow-headers — Slowloris: 1 byte per 0.5s headersWARNING
⚠️ WARNING: Hangs until timeout. Classic slowloris attack.
/slow-body — Body: 1 byte per second (a-z)WARNING
⚠️ WARNING: Takes 26 seconds without timeout.
HTML/Content Abuses
/html-utf16 — Full HTML page encoded as UTF-16LE
Title and body encoded as UTF-16LE but served as text/html with no charset. Browser/parser gets mojibake.
Absurdly long <title> tag (1000 A chars). Tests tab/title bar handling in browsers and parsers.
Title contains literal \n characters. Some parsers collapse whitespace, others preserve. Tab bars get weird.
/html-irc-title — Title with \r\nQUIT :reason injectionCRITICAL
🚨 CRITICAL: IRC protocol injection via HTML title. If an IRC bot fetches and relays this title, the QUIT/PRIVMSG could be injected into the IRC stream.
/html-unicode — Random unicode (U+1000 to U+3000) title and body
Title and body filled with random Myanmar, Ethiopic, Devanagari, CJK chars. Different every request.
/html-meta-refresh — Meta refresh loop (0 second)WARNING
⚠️ WARNING: Page reloads itself every 0 seconds via meta tag. Infinite reload loop. Browser tab goes crazy.
Terminal Abuses
/ansi-chaos — ANSI escape code nightmareWARNING
⚠️ WARNING: Clears screen, hides cursor, changes window title, blink text, random cursor positioning. Will wreck your terminal.
JavaScript Browser Abuses
/js-alert — Infinite alert() loopWARNING
⚠️ WARNING: Opens alert dialogs in an infinite loop. Browser tab becomes unresponsive. Must force-kill tab.
/js-history — History flood (50,000 entries)WARNING
⚠️ WARNING: Pushes 50,000 entries to browser history. Back button becomes useless. Browser may lag.
/js-download — Download bomb (200 files)WARNING
⚠️ WARNING: Triggers 200 simultaneous file downloads via Blob URLs. Browser download manager explodes.
/js-clipboard — Clipboard hijackCRITICAL
🚨 CRITICAL: Silently replaces clipboard content with a malicious shell command every 100ms. Paste at your own risk.
/js-forkbomb — JavaScript fork bombWARNING
⚠️ WARNING: Spawns infinite Web Workers and recursive iframes. CPU/RAM will spike. Browser may crash.
/js-webgl — WebGL GPU killerWARNING
⚠️ WARNING: Runs an extremely heavy fragment shader in a tight render loop. GPU usage spikes to 100%. May freeze display.
/js-audio — Audio oscillator hellWARNING
⚠️ WARNING: Creates 20 oscillators at random frequencies changing 10x per second at max volume. Extremely loud.
/js-popup — Popup storm (100 windows)WARNING
⚠️ WARNING: Attempts to open 100 popup windows at random positions. Most browsers block after the first.
/js-cookie — Cookie bomb (3000 cookies)CRITICAL
🚨 CRITICAL: Sets 3000 cookies. Future requests to this server include ~12MB of Cookie headers. May DoS the server.
/js-beforeunload — Unescapable page (beforeunload)WARNING
⚠️ WARNING: Traps you with a beforeunload dialog every time you try to leave. Also opens itself in new tabs.
/js-tabbomb — Tab bomb with audio + downloadsCRITICAL
🚨 CRITICAL: Rapidly opens new tabs in a loop. Each tab auto-plays random oscillator audio with visualizer and spams file downloads. Will overwhelm your browser.
🚨 CRITICAL: Registers a ServiceWorker that intercepts ALL future requests to this origin and injects content.
Image/File Abuses
/img-bait — Image bait-and-switch
Shows a green "SAFE" image on the page. Download link gives you a red "HACKED" image. Same server, different file.
/img-svg-xss — SVG with embedded JavaScriptCRITICAL
🚨 CRITICAL: Serves an SVG image with an embedded <script> tag. If rendered as image/svg+xml, JS executes. XSS via image file.
/img-polyglot — GIF/JS polyglot fileCRITICAL
🚨 CRITICAL: Valid GIF89a image that is also valid JavaScript. Can be loaded as both <img> and <script>.
Network Abuses
/net-gzip-bomb — Gzip bomb (~10KB → 10MB)WARNING
⚠️ WARNING: ~10KB gzip response that decompresses to 10MB of zeros. Clients with auto-decompress will allocate 10MB.
/net-event-flood — SSE event flood (infinite)WARNING
⚠️ WARNING: Server-Sent Events stream that fires events as fast as possible forever. EventSource will buffer infinitely.
/net-mime-sniff — MIME type confusion (JS as image/jpeg)CRITICAL
🚨 CRITICAL: Serves JavaScript code with Content-Type: image/jpeg. If browser MIME-sniffs, the JS executes. Tests X-Content-Type-Options enforcement.
Every cache header contradicts every other: no-cache + max-age=999999, public + private, future Last-Modified, wildcard Vary.
/net-hsts-bomb — HSTS with insane max-ageCRITICAL
🚨 CRITICAL: Sets Strict-Transport-Security with max-age=999999999 and includeSubDomains. Browser will force HTTPS for 31 years.
Miscellaneous
/misc-ipv4 — Shows your connecting IPv4 address
Reflects the client IP from the TCP connection. Use -4 flag with curl to force IPv4.
/misc-ipv6 — Shows your connecting IPv6 address
Reflects the client IP. Server must be reachable over IPv6. Connect to [::1] for loopback IPv6.
Special Pages
/fingerprint — Browser fingerprinting demo
Collects and displays 25+ browser fingerprinting vectors: canvas, WebGL, fonts, timezone, CPU, memory, touch, audio, etc.
☠ badtests — 81 endpoints on port 60666
made by acidvegas