# WebGoat: running OWASP's deliberately insecure app for web security practice

> WebGoat is an OWASP teaching application built to be attacked. This article covers the Docker and standalone install paths, how the lessons and WebWolf fit together, and the isolation rules you have to respect before you start it.

**WebGoat/WebGoat** — WebGoat is a deliberately insecure application

- Repository: https://github.com/WebGoat/WebGoat
- Website: https://owasp.org/www-project-webgoat/
- Stars: 9,375 · Forks: 7,945
- Language: JavaScript
- License: NOASSERTION
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/webgoat-webgoat

## What WebGoat is for, and who should not run it

WebGoat is a web application with intentional server-side flaws, maintained by OWASP and described in its README as a teaching tool for application security and penetration testing techniques. The exercises are the product. You do not read about SQL injection; you send a payload that the lesson's endpoint accepts, and the lesson marks the attempt. That makes it useful for a developer who has never exploited a flaw, for a trainer who needs a shared exercise set, and for anyone preparing for hands-on security work.

The README carries two warnings that define the audience. The first says that while the program runs, your machine will be extremely vulnerable to attack, and that you should disconnect from the Internet while using it. The second says the program is for educational purposes only and that unauthorized use of these techniques is likely to be punished. Those two sentences rule out one deployment entirely: a long-lived instance on a shared or internet-facing host. WebGoat is a lab, not a sandbox you leave behind.

## How the lessons, the container and WebWolf fit together

The application is a Spring Boot service. The repository's Dockerfile starts from eclipse-temurin:25-jdk-noble, which the comment explains is necessary because some lessons need to compile Java code at runtime, then copies the built jar to /home/webgoat/webgoat.jar and exposes 8080 and 9090. The entrypoint runs that jar with a long list of --add-opens flags and sets -Drunning.in.docker=true, and a healthcheck polls http://localhost:8080/WebGoat/actuator/health every five seconds.

Two ports means two applications. WebGoat itself serves the lessons on 8080 under the /WebGoat/ context path. WebWolf, published on 9090, is the companion service the README points to at /WebWolf/; several lessons need a second host that the learner controls, and WebWolf is where that host lives. The README also notes that some lessons require the container to run in the same timezone as you, which is why TZ appears in the run commands and is set to Europe/Amsterdam in the image.

The lesson set is not fixed. Environment variables EXCLUDE_CATEGORIES and EXCLUDE_LESSONS let you drop whole categories or individual lessons, which the README labels as being for specialists. That is the mechanism a trainer would use to trim a course down to the topics being taught.

## Installing WebGoat with Docker

The fastest path assumes you already have a browser and a proxy such as ZAP or Burp. The README gives this command, which binds both ports to loopback only:

```bash
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
```

After it starts, open http://localhost:8080/WebGoat/. The README notes that this link redirects to a login page if you are not logged in, so create an account before expecting a lesson list.

If a lesson depends on your local clock, pass the timezone. The README's example uses America/Boise:

```bash
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=America/Boise webgoat/webgoat
```

There is a catch when you introduce a proxy. The README states that with OWASP ZAP or another proxy you can no longer use 127.0.0.1 or localhost, and that you should add custom host entries instead:

```bash
127.0.0.1 www.webgoat.local www.webwolf.local
```

Then start the container with matching host variables, so the app generates links that resolve through the proxy:

```bash
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e WEBGOAT_HOST=www.webgoat.local -e WEBWOLF_HOST=www.webwolf.local -e TZ=America/Boise webgoat/webgoat
```

With that running, the README says to visit http://www.webgoat.local:8080/WebGoat/ and http://www.webwolf.local:9090/WebWolf/. If both pages load, the host entries and the two container variables agree.

## Running the jar standalone, and changing the port

Docker is not the only route. The README points to the releases page for the latest jar and then shows a standalone start. The version in its example is webgoat-2023.8.jar, so substitute the file you actually downloaded:

```bash
export TZ=Europe/Amsterdam # or your timezone
java -Dfile.encoding=UTF-8 -jar webgoat-2023.8.jar
```

The README says to click the link in the log to start WebGoat, which is how you learn the bound address without guessing. To move the two services off their defaults, the same jar accepts port properties:

```bash
java -jar webgoat-2023.8.jar --webgoat.port=8001 --webwolf.port=8002
```

For the full parameter list the README directs you to webgoat-container/src/main/resources/application-{webgoat, webwolf}.properties. To change the bound address it says to add server.address=x.x.x.x to WebGoat/webgoat-container/src/main/resources/application.properties. Building from source is a heavier path: the README lists Java 25 as a prerequisite, then git clone, ./mvnw clean install, and ./mvnw spring-boot:run on Linux or macOS, with ./mvnw.cmd variants on Windows. It also warns that if you have run WebGoat before you should first run mvn clean -Pcleanall, because leftover files in your temp and home directories can fail the tests.

## The browser desktop image and what it trades away

For people who do not want to install a proxy locally, the README offers a second image that runs a Linux desktop inside the browser:

```bash
docker run -p 127.0.0.1:3000:3000 webgoat/webgoat-desktop
```

This is the lowest-friction option and the README calls it the best user experience, since the tools you need are already in the image. The trade-off is that you are working inside a container's desktop rather than your own, so anything you configure there is gone when the container is removed, and the port is 3000 rather than 8080. If your goal is to learn your own Burp or ZAP setup, the plain webgoat/webgoat image plus host entries is the better fit. If your goal is to see the lessons working today, the desktop image removes a class of setup problems.

## Where WebGoat is the wrong tool

WebGoat is not a scanner benchmark. Its flaws are curated and labeled by lesson, so a tool that finds them has demonstrated almost nothing about how it behaves against an application whose vulnerabilities were not placed there on purpose. For that job you want a target with unintended and unlabeled weaknesses.

The second limit is operational. The README's own warning that your machine will be extremely vulnerable is not boilerplate. The image runs with --server.address=0.0.0.0 inside the container, and the default configuration binds to localhost only because the published run commands map ports to 127.0.0.1. Change that mapping to 0.0.0.0:8080 on a machine with a public interface and you have published an intentionally broken application. The README does not document a supported way to expose WebGoat safely, and it does not document rollback for the lesson state either; if you want a clean slate you remove the container or clear the files the cleanall profile targets.

Finally, WebGoat teaches server-side flaws. If your interest is purely client-side or infrastructure security, the lesson catalog will feel narrow, though EXCLUDE_CATEGORIES can at least cut what you do not need.

## How WebGoat differs from a general-purpose vulnerable target

The obvious alternative is a deliberately vulnerable application built as a realistic web app, such as OWASP Juice Shop. The difference in approach is the unit of work. WebGoat is organized as named lessons with a scoring mechanism, and the README's exclusion variables operate on categories and lesson identifiers, which only makes sense if lessons are the primary structure. A target like Juice Shop is organized as an application you explore: you find the flaws, and the application does not tell you in advance which category you are in. WebGoat is better for guided instruction and for verifying that you can execute a specific technique; a realistic vulnerable app is better for practicing discovery and for testing tooling against noise. Many people use both, and the README's host-entry instructions exist precisely because WebGoat expects you to bring your own proxy to the lessons.

## Conclusion

Adopt WebGoat if you are learning application security or running a lab where the machine is disposable and offline; skip it if you need a scanner target with realistic noise or a tool that can be left running on a shared host. Before your first lesson, confirm which ports the jar or container bound, that WebWolf answers on 9090, and whether your timezone matches the container's TZ value, because several lessons depend on it.

## FAQ

### What is WebGoat used for?

It is a deliberately insecure web application maintained by OWASP that teaches web application security lessons. The README describes it as a demonstration of common server-side application flaws, intended for people learning application security and penetration testing techniques.

### Is WebGoat safe to run?

The README warns that while it runs your machine will be extremely vulnerable to attack and that you should disconnect from the Internet while using it. Its default configuration binds to localhost to limit exposure, and the published Docker commands map both ports to 127.0.0.1.

### How do I install WebGoat with Docker?

The README's command is docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat, and every release is also published on DockerHub. Once it starts, visit http://localhost:8080/WebGoat/ and expect a redirect to the login page.

### How do I access WebGoat after starting it?

Open http://localhost:8080/WebGoat/ for the lessons and http://localhost:9090/WebWolf/ for the companion service. The README notes the WebGoat link redirects to a login page if you are not logged in, so log in or create an account first.

### How do I install WebGoat on Windows or macOS?

The README does not give platform-specific install steps. Docker is the documented path that works the same everywhere, and the standalone route is to download a release jar and run it with java -Dfile.encoding=UTF-8 -jar, with ./mvnw.cmd variants only for building from source on Windows.

## Sources

- [Issues](https://github.com/WebGoat/WebGoat/issues)
- [Project website](https://owasp.org/www-project-webgoat/)
- [README](https://github.com/WebGoat/WebGoat/blob/main/README.md)
- [Releases](https://github.com/WebGoat/WebGoat/releases)
- [WebGoat/WebGoat on GitHub](https://github.com/WebGoat/WebGoat)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/webgoat-webgoat
