Skip to the content.

← Docs home

Glossary

The words this kit uses precisely, for the reader who keeps tripping on one. Each entry links the doc that owns the full story. If you’re trying to do something rather than decode a term, start at the docs home instead.

Control plane — what this kit is: the shared spine every event runs on (GitHub org, team registration, leaderboard, admin panel, scoring pipeline), as opposed to the challenge content plugged into it. The boundary is the module contract.

Module — a CTF vertical plugged into the control plane: its own challenges, scoring logic, and provisioning. Four ids are registered: secure-development, quiz, classic and ai. Any subset runs alone or together. See modules.md and, for ai specifically, the external integrator’s contract in docs/ai-module.md.

Target — one deliberately vulnerable app the Secure Development module scores (Juice Shop, DVWA, WebGoat, Security Shepherd, VulnerableApp, VAmPI). Each event forks its targets from their own upstreams at pinned versions (setup/targets.tsv); targets are never vendored into this repo.

Fork — the event org’s copy of a target, which a contestant forks again and patches. The fork’s own GitHub Action is what scores a PR — the box never runs contestant code.

Rubric — the scoring content for one target: what to check and what each challenge is worth. Two grammars exist — declarative HTTP probes (<target>.yaml) and executable node:test suites priced by a catalogue (catalogue.<target>.json) — and one rubric directory may mix them. See scorer.md.

Probe — one declarative request/expect check inside a YAML rubric: send this HTTP request, expect this status/body. The executable grammar replaces probes with real test code.

Catalogue — the priced challenge list for an executable-grammar target: challenge ids, names, and difficulty (which is the point value).

Marker — the machine-readable score comment the fork’s Action posts on a PR: <!-- ctf-score: {json} -->. The marker is trust-authoritative — the poller ingests it only from github-actions[bot]-authored comments, and the workflow writes it only from the judge’s own output. See architecture.md’s score data flow.

Poll — the score transport, and the only one: the sync service pulls score comments from GitHub every ~30 s, so nothing has to reach the box from the internet and an event runs behind NAT or on venue wifi. Push — the fork’s Action POSTing the score straight at the box — was removed in v0.6 (#377, ADR 56). How it fits together: hosting.md.

Scorer — the one score writer in the system: an engine (scorer/) with two modes — serve (the leaderboard API and the bearer-authed POST /score) and judge (runs a rubric against a target inside the fork’s Action). See scorer.md.

Freeze vs scoring window — two ways scoring stops. Freeze is the manual switch: ingestion holds (queued, never lost), fork Actions keep running. The scoring window (scoringStartsAt/scoringEndsAt) does the same on a schedule. Both are evaluated at read time by three independent readers that must agree. See operations.md and ADR 32.

Vacuous pass — a rubric check that “passes” only because the app wasn’t actually up or useful — it proves nothing and would hand out free points. The kit’s sweep (scorer/tools/vacuous-sweep.mjs) points every rubric at a deliberately useless stub and fails if anything passes. See scorer.md.

Oracle discipline — the rule that contestant-visible scoring output is pass/fail and points only, never which assertion failed or how. An information-rich comment tells a contestant exactly which check to game. See modules.md, Section 6.

srhhiett/serverless-redis-http, the Upstash-compatible REST proxy in front of Redis. It exists so the vendored app’s @upstash/redis client works unchanged against local Redis, and it is the only service on both compose networks — the app tier has no route to redis:6379 at all.

The two config planes — there is no config file (#386, ADR 55). .env is the bootstrap plane: the box’s secrets plus four keys read once at container start — GITHUB_ORG (the fork org), ADMIN_LOGINS (the bootstrap admins allowlist), SCORE_IMAGE (the scorer image, and by its non-emptiness whether Secure Development is available — it adds the compose profile and seeds the default module set, while /admin still decides what is live), and EVENT_URL, which lives only here so one deployment recipe travels to any hostname (ADR 43). ctf:admin:settings is the runtime plane: everything an organizer changes during the event, written from /admin and re-read on every request — which modules are enabled (enabledModules, ADR 52), which Secure Development targets run (secureDevTargets, defaulting to all six), the event’s identity, the schedule, hints and team caps. Nothing is baked into an image, and no toggle needs a rebuild.

The two planes divide provisioning from selection. With SCORE_IMAGE non-empty, ctf-setup.sh forks and provisions all six targets, every time; with it empty it skips provisioning altogether and there is nothing on GitHub to select from. /admin then owns both live choices: enabledModules, and the secureDevTargets subset of those six that contestants actually see.

The project’s names

Five names orbit “the project”; they are not interchangeable:

Name What it is
OWASP CTF The product / brand (README, dcotelo.github.io/owasp-ctf) and the default event name every deployment shows until an organizer renames it. The two are deliberately the same string since the rebrand; real events override it from /admin → Event → Identity (a runtime setting since #386). One consequence to know: since the name is never baked, a misconfigured box does not betray itself by its name — check for an empty ADMIN_LOGINS and a 403 on /admin instead.
owasp-ctf The local repo directory and the lowercase image namespace.
OWASP-CTF The GitHub org the canonical targets are forked into (GITHUB_ORG in .env).
ghcr.io/owasp-ctf/score The scorer image path. The lowercase owasp-ctf here is a registry-namespace convenience, not the OWASP-CTF org; override SCORE_IMAGE to your own org’s GHCR.
dc34-owasp-secure-development-ctf The upstream repo the rubrics are vendored from (see scorer/rubric.owasp/PROVENANCE.md).

This project is not affiliated with or endorsed by the OWASP Foundation; OWASP® is a registered trademark of the OWASP Foundation.