Open-source cybersecurity labs that run in Docker. Exploit a real service, find the flag, verify the solve. No accounts, no scoring server. A duckurity project.
Quick start · Labs · Wiki · Contribute
Press play to hear the welcome.
Your browser does not support the audio element.Three things stand between you and your first flag.
git clone https://github.com/Duckurity/openlabs
cd openlabs/labs/web/duck-cross
docker compose up -dOpen http://localhost:8377, work the brief until the flag turns up, then
check the solve:
python3 scripts/check.py labs/web/duck-crossThe checker hashes your input with SHA-256 and compares it against
flag_hash in lab.yml. It prints solved or not solved.1
Tip
After images are pulled, nothing leaves your machine. Labs are self-contained and fully offline.
Every lab is a self-contained exercise: one vulnerable service, one brief, one flag inside. You solve at your own pace, and honesty is built in. The repository stores only the SHA-256 hash of each flag, never the plaintext.
| Self-contained | Runs offline once images are pulled. No phone-home. |
| Reproducible | Pinned base images, one documented host port. |
| Honest | Plaintext flags stay inside lab internals; only the hash ships. |
| Graded | A four-step difficulty ladder from easy to insane. |
| Track | Examples |
|---|---|
web |
injection, broken access control, auth bypass, SSRF |
binary |
memory corruption, exploitation, reverse engineering |
crypto |
weak primitives, protocol misuse, implementation faults |
network |
protocol abuse, traffic analysis, pivoting |
osint |
recon, source analysis, signature tracing |
easy → medium → hard → insane. Grades describe what a player does,
not how long it takes.
| Level | Expectation |
|---|---|
| one vector, minimal recon | |
| chained steps, some enumeration | |
| multiple systems, custom tooling | |
| research-level, an original technique |
1 supported · 19 experimental
Supported labs have documented L0–L6 evidence on file. 19 experimental labs are runnable but not promoted. Experimental entries are not guaranteed supported.
| Lab | Track | Difficulty | Description |
|---|---|---|---|
duck-cross |
web |
A reports portal with a missing object-level authorization check. |
| Lab | Status | Track | Difficulty | Description |
|---|---|---|---|---|
aegis-ctf |
experimental |
web |
Chained API trust vulnerabilities across REST, GraphQL, and gRPC. | |
cafe-house-rules |
experimental |
web |
A cafe rules site with a report bot and a guarded back-room route. | |
cloudvault |
experimental |
web |
A GraphQL document-ingestion API whose SSRF chain reaches a privileged internal vault. | |
duck-nest |
experimental |
web |
An internal project workspace for staff and interns. | |
duckexchange |
experimental |
web |
A tenant document API with a gRPC transcoding authorization bypass. | |
duckrpc-archive |
experimental |
web |
A gRPC document archive with authentication and a SQL injection vulnerability. | |
duckvault |
experimental |
web |
A records portal leaks an internal reference through broken access control and weak authorization. | |
duckvault-web-ctf |
experimental |
web |
A document management API with a broken object-level authorization check. | |
fieldops-360 |
experimental |
web |
A tenant portal with email open tracking and an admin export surface. | |
firmdrama |
experimental |
web |
A law firm's meeting-room portal with chained API authorization flaws and a vulnerable legacy template renderer. | |
invoiceportal |
experimental |
web |
InvoicePortal is a SaaS platform for managing company invoices. | |
nexora-platform |
experimental |
web |
Nexora is a deliberately vulnerable B2B SaaS CTF that simulates a realistic Blind SSRF attack using GraphQL, OAST, internal reconnaissance, and DNS rebinding to bypass hostname validation and reach internal infrastructure. | |
shopvault |
experimental |
web |
An e-commerce REST API whose authentication, lockout, and JWT signing weaknesses chain into manager-level access. | |
snapconnect |
experimental |
web |
SnapConnect is a small social app with profiles and avatars, served by a GraphQL API. | |
snapsync |
experimental |
web |
A staff photo tool where a forged token and a hidden internal route reach the flag. | |
switf01-hit3 |
experimental |
web |
A task-management platform with a chained REST, GraphQL, and gRPC attack path. | |
techvault |
experimental |
web |
An e-commerce GraphQL API with a chained authentication bypass, SSRF, and command injection vulnerability. | |
threadline |
experimental |
web |
A clothing store REST API. One customer sees more than they should. | |
vault-api |
experimental |
web |
Inspect an internal employee management API and recover a protected employee archive. The lab starts with a low-privileged analyst account and explores how security boundaries are enforced across an API. |
Uncatalogued directories are omitted from public totals. Maintainers track them in the lab triage inventory.
duck{...}. Lowercase letters, digits, and underscores between the braces, 16 to 40 characters.2
The plaintext flag lives inside the lab; the repository stores only its SHA-256 hash. Reading lab source to find the flag is a legitimate solve. Open labs work that way.
labs/<track>/<lab>/
├── lab.yml # name, track, difficulty, description, flag_hash
├── README.md # player brief: story, setup, goal
├── docker-compose.yml # service definition
├── Dockerfile # pinned base image
└── app/ # lab internals; the flag lives here
labs/_template/ carries the skeleton. Copy it, fill it in, and open a
pull request. CI validates structure, metadata, and flag hygiene on every
change.
A writeup is your own explanation of a solve. Publish them anywhere. Link the lab so other people can follow the path you took.
Labs are welcome. Read CONTRIBUTING.md before you open a pull request. For behavior standards, see CODE_OF_CONDUCT.md. The full player and authoring guides live on the project wiki.
How a lab ships
flowchart LR
idea["Lab idea<br>issue form"] --> author["Copy<br>labs/_template"]
author --> pr["Pull request"]
pr --> ci{"CI validates"}
ci -->|"fix"| author
ci -->|"pass"| review["Review"]
review --> ship["Merged into<br>labs/"]
Code, configuration, and scripts fall under Apache-2.0. Lab briefs, docs, and prose fall under CC-BY-4.0. One repository, two licenses.
The vulnerabilities inside labs are the product; they need no report. Weaknesses in lab infrastructure, repo tooling, or CI go through GitHub Private Vulnerability Reporting. Details in SECURITY.md.
