⚠️ DISCLAIMER — INTENTIONALLY VULNERABLE CODE. This project deliberately contains security vulnerabilities. It exists only for security research, static-analysis tooling validation, and educational testing. Do NOT deploy it, expose it to any untrusted network, or run it against data/systems you care about. This is a single, runnable Java web application (embedded Jetty,javax.servlet) built from the 84 vulnerable snippets listed inexamplesVulnerable.txt. Every class is exposed as its own HTTP-invokable endpoint and has at least one automated end-to-end test that drives a real HTTP request through the running server so the vulnerable code path is genuinely executed. The untrusted source (an HTTP request parameter/body) and the exact sink from each snippet are preserved — nothing is sanitized, encoded, or otherwise mitigated.
- JDK 11+ (uses
java.net.http.HttpClient) - Maven 3.6+
cd vulnerable-app
mvn clean test # runs all end-to-end tests (86 tests covering 84 classes)
mvn -DskipTests package # builds the runnable fat jar
java -jar target/vulnerable-app.jar 8080Run a single test:
mvn test -Dtest=EndToEndTestExample exploit demonstration (reflected XSS):
curl 'http://localhost:8080/xss?page=<script>alert(1)</script>'
# => The page "<script>alert(1)</script>" was not found.Versions are aligned via the Spring Boot 2.7.x dependencies BOM (Apache-2.0), which keeps Spring,
Spring Security, Netty, Groovy, Hibernate/Validator, H2, Jetty, Log4j2, HttpClient and JUnit mutually
compatible (Spring Boot 2.7 still targets javax.*, matching the snippets).
| Dependency | Used by (CWE) | License |
|---|---|---|
| Eclipse Jetty (server/servlet) | embedded container | Apache-2.0 / EPL-2.0 |
| H2 Database | 089 SQLi, JPA | MPL-2.0 / EPL-1.0 |
| SLF4J + slf4j-simple | 117 log injection | MIT |
| Log4j2 (log4j-core/api) | 297 JavaMail, 532 | Apache-2.0 |
| UnboundID LDAP SDK | 090, 522 (in-memory LDAP) | Apache-2.0 |
| OWASP ESAPI | 090 LDAP GOOD-branch encoder | BSD-3-Clause |
| Apache Groovy | 094 Groovy | Apache-2.0 |
| MVEL2 | 094 MVEL | Apache-2.0 |
| Apache Commons JEXL3 | 094 JEXL | Apache-2.0 |
| Spring Expression (SpEL) | 094 SpEL | Apache-2.0 |
| Apache Velocity | 094 SSTI | Apache-2.0 |
| OGNL | 917 | Apache-2.0 |
| Netty (codec-http) | 113 Netty split | Apache-2.0 |
| JJWT (api/impl/jackson) | 347 | Apache-2.0 |
| Apache Shiro | 807 permissions | Apache-2.0 |
| Hibernate Validator + Glassfish EL | 094 bean validation | Apache-2.0 / EPL-2.0 |
| Hibernate ORM (JPA) | 089 JPQL | LGPL-2.1 |
| dom4j + jaxen | 643 XPath (dom4j sinks) | BSD-3-Clause |
| JavaMail (com.sun.mail) | 297 | CDDL-1.1 / GPL-2.0+CE |
| Apache Commons Email | 297 | Apache-2.0 |
| Apache Commons Lang3 | 338 | Apache-2.0 |
| Apache HttpClient | 522 basic auth | Apache-2.0 |
| RabbitMQ amqp-client | 273 | Apache-2.0 / MPL-2.0 / GPL-2.0 |
| AWS SDK core | 798 | Apache-2.0 |
| Spring Web / Security / Boot Actuator | 352, 200 | Apache-2.0 |
| Google Guava | 200 temp dir | Apache-2.0 |
| Stapler | 352 Stapler | BSD-3-Clause |
| JAX-RS API | 1004 | CDDL-1.1 / GPL-2.0 |
| JUnit 5 | tests | EPL-2.0 |
Every row maps an original class → its endpoint. Unless noted, endpoints are GET and reachable at
http://localhost:8080<path>. Inputs shown are illustrative markers, not working payloads. Each servlet class is named CWE_<id>_<OriginalClass> (e.g. CWE_020_ExternalAPISinkExample, file src/main/java/com/example/vulnapp/servlets/CWE_020_ExternalAPISinkExample.java) so it maps 1:1 to the original snippet in the table below.
The vulnerable source→sink of every class is preserved. A few endpoints required small, documented accommodations that do not change the vulnerability:
- GOOD counterpart branches restored: for classes whose original snippet contained both a
// BADsink and a// GOOD(safe) alternative, both are now reproduced in the servlet so it diffs cleanly against the original. The BAD sink remains the unmitigated vulnerability; the GOOD branch is included for comparison. Where a GOOD branch needs infrastructure not shipped here (e.g. the CWE-090 ESAPI encoder'sESAPI.properties, the CWE-1004javax.ws.rsNewCookieruntime, the CWE-295 self-signed certificate file), that GOOD branch is wrapped in its owntry/catchso its absence cannot mask or break the BAD sink. - CWE-190 ComparisonWithWiderType (
/comparison-wider) and CWE-835 InfiniteLoopBad (/infinite-loop): the exact buggy loop runs in a watchdog thread with a short join timeout so the endpoint returns; the incidental multi-gigabyte buffer in the CWE-190 snippet is reduced to avoidOutOfMemoryError(the defect is the short/long comparison, not the buffer). - CWE-421 SocketAuthRace (
/socket-auth-race): the blockingaccept()/write(secretData)sink runs in a background thread that a local client connects to, so the write executes deterministically. - CWE-200 SpringBootActuators (
/actuators): uses Spring Security 5.7'srequestMatcher, the equivalent of the snippet's 5.8securityMatcher; thepermitAll()misconfiguration is unchanged. - Endpoints whose sink legitimately fails without external infrastructure (JNDI/RMI lookup, LDAP
bind, outbound mail, MySQL connect, remote JWT) wrap the sink in
try/catchand still return 200 — the vulnerable call is reached and executed; only the downstream network/IO fails.
- Vulnerability types / CWE IDs: all classes from
examplesVulnerable.txt(CWE-020 … CWE-918); see table. - Source: an HTTP request parameter or request body, per endpoint.
- Sink: the exact vulnerable API call from the original snippet, per endpoint.
- Root cause: missing validation/encoding/authentication/etc. as in each original snippet — not fixed.
- Automated tests:
EndToEndTeststarts real Jetty and issues genuine HTTP requests to every endpoint (86 tests / 84 classes). Run withmvn test. - Disclaimer: intentionally vulnerable code for research/testing only; not for production.
