{"slug": "show-hn-wattzgoat-an-intentionally-vulnerable-web-app-for-security-training", "title": "Show HN: WattzGOAT – an intentionally vulnerable web app for security training", "summary": "WattzGOAT, an intentionally vulnerable web application built as a security-training lab, ships as a single Docker container with 48 hidden weaknesses to find and exploit. The made-up smart-meter company's customer portal and admin side include five bonus flags tied to a simulated AI assistant, and the flaws follow OWASP Top 10 categories such as broken access control and injection. The project's authors state it was built with AI tools and contains AI-written code, and warn users to run it only on their own computer or a private network and never expose it to the internet.", "body_md": "WattzGOAT is an intentionally vulnerable web application built to be hacked. It is a made-up smart meter company with a customer portal, and it's a lab, not a real product. Customers can check their meter, top up their balance, report solar power, look at bills and contact support. Admins can manage meters and look after support tickets.\n\nThe site is vulnerable on purpose, so you can practise finding real security weaknesses in a safe place.\n\n- A full customer portal (signup, meter dashboard, recharge, solar export, bills, support tickets) plus an admin side, so there's a realistic amount of surface to explore, not just a single vulnerable form.\n- 48 hidden weaknesses to find and exploit, from easy to hard.\n- A capture-the-flag style Progress page that tracks which ones you've found.\n- A simulated AI assistant with its own set of weaknesses to find.\n- Runs as a single Docker container with no other setup.\n\nWattzGOAT works like a capture the flag (CTF) game. There are 48 flags hidden in the site. You get a flag by finding a weakness and using it. Five of the 48 are bonus flags about a simulated AI assistant.\n\nThe weaknesses are the kind of problems described in the OWASP Top 10, things like broken access control and injection, so what you practise here applies to real websites too.\n\nTo get started, create an account or log in with one of the sample customer accounts, then look around and try things out. When you find a flag, you can enter it on the Progress page, which keeps track of the ones you have found.\n\nSample customer accounts have emails like `alice.smith@example.com`. Their passwords are the first name followed by `123`.\n\nIf you already have Docker installed, this gets you running in one step. See \"What you need\" and \"Start WattzGOAT\" below for the full explanation.\n\n```\ndocker run -d --name wattzgoat -p 5000:5000 -p 5001:5001 -e INSTANCE_HOST=127.0.0.1 -e STANDALONE=true -e STANDALONE_PASSWORD=YourPasswordHere ghcr.io/wattzgoat/wattzgoat-web:latest\n```\n\nThen open [https://127.0.0.1:5000](https://127.0.0.1:5000) in your browser.\n\nWattzGOAT runs as a single container: the web app and its database both live inside it, reachable over two ports (one HTTPS, one plain HTTP; a couple of the exercises specifically need the unencrypted one). Nothing else needs to be installed or run alongside it.\n\n**This site is insecure on purpose.**\n\n- Run it only on your own computer, or on a private network that you control.\n- Never put it on the internet.\n- Never type real passwords or personal details into it.\n\nAll company names, accounts and data in the site are made up.\n\nThis project was built with the help of AI tools and contains AI-written code. The weaknesses are there on purpose, but the code may also have other bugs or security problems that were not planned. Please keep this in mind and follow the warning above.\n\n- A computer running Windows, macOS or Linux.\n- An internet connection for the first setup.\n- **Docker** , to run the site. Follow the official install steps at[https://docs.docker.com/get-started/get-docker/](https://docs.docker.com/get-started/get-docker/) .\n- **Git** , only if you want to build the site from the source code. Follow the official install steps at[https://git-scm.com/downloads](https://git-scm.com/downloads) .\n\nTo check that Docker works, run these two commands. If the second one prints a \"Hello from Docker!\" message, you are ready.\n\n```\ndocker --version\ndocker run --rm hello-world\n```\n\nYou can either use the ready-made image or build it yourself. Both give you the same site. Use the same commands on Linux, macOS and Windows (in PowerShell).\n\n```\ndocker run -d --name wattzgoat -p 5000:5000 -p 5001:5001 -e INSTANCE_HOST=127.0.0.1 -e STANDALONE=true -e STANDALONE_PASSWORD=YourPasswordHere ghcr.io/wattzgoat/wattzgoat-web:latest\n```\n\nDocker downloads the image the first time you run this.\n\n```\ngit clone https://github.com/wattzgoat/wattzgoat-web.git\ncd wattzgoat-web\ndocker build -t wattzgoat .\ndocker run -d --name wattzgoat -p 5000:5000 -p 5001:5001 -e INSTANCE_HOST=127.0.0.1 -e STANDALONE=true -e STANDALONE_PASSWORD=YourPasswordHere wattzgoat\n```\n\nThe build downloads some packages, so it needs an internet connection and takes a few minutes.\n\n| Setting | What it does | \n|---|---|\n| `-p 5000:5000` | Makes the site available on port 5000 (HTTPS). | \n| `-p 5001:5001` | Makes the site also available on port 5001 (plain HTTP). Some exercises use it, so keep both ports. | \n| `INSTANCE_HOST` | The IP address you will type into your browser. Use `127.0.0.1` if the browser is on the same computer. If you run WattzGOAT on another machine, use that machine's IP address, for example`192.168.1.50` . It must be an IP address, not a name. | \n| `STANDALONE` | Set to `true` when you run a single copy on its own. | \n| `STANDALONE_PASSWORD` | A password of your choice. Replace `YourPasswordHere` with your own. | \n\nGo to [https://127.0.0.1:5000](https://127.0.0.1:5000) in your browser (or use the IP address you set in `INSTANCE_HOST`).\n\nYour browser will warn you that the connection is not private. This is normal, because the site makes its own security certificate. Choose **Advanced**, then continue to the site.\n\n| What you want to do | Command | \n|---|---|\n| See that it is running | `docker ps` | \n| Read the logs | `docker logs wattzgoat` | \n| Stop it | `docker stop wattzgoat` | \n| Start it again (keeps your progress) | `docker start wattzgoat` | \n| Start again from scratch | `docker rm -f wattzgoat` , then run the start command again | \n\nRemoving the container clears everything, including the flags you have found.\n\n**To update to a newer version**\n\nGet the new version first, then replace the old container. Updating clears your progress, because the old container is removed.\n\n- Ready-made image:\n  1. `docker pull ghcr.io/wattzgoat/wattzgoat-web:latest`\n  2. `docker rm -f wattzgoat`\n  3. Run the start command again.\n- Built from source:\n  1. `git pull`\n  2. `docker build -t wattzgoat .`\n  3. `docker rm -f wattzgoat`\n  4. Run the start command again.\n\n- **\"Port is already allocated\"** : another program is using that port. Change the number on the left of the port setting, for example`-p 8443:5000` , and open[https://127.0.0.1:8443](https://127.0.0.1:8443) instead.\n- **The page does not load** : run`docker ps` to check the container is running. If it is not, run`docker logs wattzgoat` to see why.\n- **The container stops right after starting** : check that`INSTANCE_HOST` is an IP address, such as`127.0.0.1` , and not a name like`localhost` .\n- **On Windows or macOS, Docker commands fail** : make sure Docker Desktop is open and running.\n\nIdeas and bug reports are welcome. Please open an issue on the [GitHub Issues page](https://github.com/wattzgoat/wattzgoat-web/issues).\n\nIf you would like to add or change something, you can send a pull request. Pull requests are reviewed before they are merged. For bigger changes, please open an issue first so we can talk about it.\n\nThe weaknesses in the site are there on purpose, so they are not bugs. Problems that stop the site from working, or weaknesses that were not planned, are worth reporting.\n\nTo run the automated tests, you need Python 3.12 and a fresh copy of the site running (see above):\n\n```\npip install -r tests/requirements-dev.txt\npytest tests\n```\n\nSet `WATTZGOAT_BASE_URL` to the address of your copy if it is not `https://127.0.0.1:5000`. The tests change data in the site, so use a fresh copy each time.\n\nWattzGOAT is licensed under the Apache License 2.0. You are free to use, copy and change it. See the [LICENSE](https://github.com/wattzgoat/wattzgoat-web/blob/main/LICENSE) file for the full terms.\n\nCopyright 2026 WattzGOAT", "url": "https://wpnews.pro/news/show-hn-wattzgoat-an-intentionally-vulnerable-web-app-for-security-training", "canonical_source": "https://github.com/wattzgoat/wattzgoat-web", "published_at": "2026-09-30 16:31:52+00:00", "updated_at": "2026-09-30 16:49:55.303299+00:00", "lang": "en", "topics": ["ai-safety", "ai-products", "developer-tools"], "entities": ["WattzGOAT", "Docker", "OWASP Top 10", "GitHub", "ghcr.io"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-wattzgoat-an-intentionally-vulnerable-web-app-for-security-training", "markdown": "https://wpnews.pro/news/show-hn-wattzgoat-an-intentionally-vulnerable-web-app-for-security-training.md", "text": "https://wpnews.pro/news/show-hn-wattzgoat-an-intentionally-vulnerable-web-app-for-security-training.txt", "jsonld": "https://wpnews.pro/news/show-hn-wattzgoat-an-intentionally-vulnerable-web-app-for-security-training.jsonld"}}