Capture the Flag competitions have been part of the security community's DNA since DEF CON CTF launched at DEF CON 4 in 1996, and three decades later the format still teaches vulnerability classes faster than almost anything else available to a security team. Two structures dominate: Jeopardy-style, where standalone challenges sit in categories and teams solve them independently at their own pace, and Attack-Defense, where teams simultaneously patch their own vulnerable services while exploiting identical services run by opponents — the format DEF CON CTF itself is built around. Most companies running internal training reach for Jeopardy-style, and for good reason: it needs no live infrastructure to defend, it parallelizes across a room of engineers with wildly different skill levels, and a mid-level backend engineer and a principal security architect can both be working the same board without either one blocking the other. The categories that make up that board aren't arbitrary — web exploitation challenges map cleanly onto the OWASP Top 10:2025, binary exploitation and reverse engineering map onto memory-safety and compiled-language risk, and difficulty scales through a points system borrowed from platforms like picoCTF and HackTheBox. This post lays out how to structure categories, tier difficulty, and run the logistics so an internal CTF actually changes how your engineers write code, not just how they spend an afternoon.
What format should an internal CTF use?
Jeopardy-style is the right default for internal engineering training, and Attack-Defense should be reserved for mature security teams running dedicated red/blue exercises. In Jeopardy format, challenges sit on a board organized by category and point value, and participants pick whichever one interests them, submit a flag string when solved, and move to the next — no challenge blocks another, so a room of 40 engineers can all be productive simultaneously regardless of experience. Attack-Defense format, by contrast, requires every team to stand up and continuously monitor an identical vulnerable service, which demands real infrastructure, sustained attention for the full duration of the event, and a baseline of offensive and defensive skill that most non-security engineers don't have yet. DEF CON CTF has run Attack-Defense at its onsite finals for decades specifically because its participants are already elite; that same structure will strand a team of application engineers who've never opened a debugger. Start Jeopardy-style, and only introduce Attack-Defense once your engineering org has run several Jeopardy events and has a security champions group that wants a harder, more adversarial format.
How should challenge categories be structured?
Structure categories around the vulnerability classes your engineers actually ship, not around the full breadth of what a professional pentester needs to know. The most transferable category for an internal engineering CTF is web exploitation, and it maps directly onto the OWASP Top 10:2025: A01 Broken Access Control, A02 Security Misconfiguration, A03 Software Supply Chain Failures, A04 Cryptographic Failures, A05 Injection, A06 Insecure Design, A07 Authentication Failures, A08 Software or Data Integrity Failures, A09 Security Logging and Alerting Failures, and A10 Mishandling of Exceptional Conditions (source: owasp.org/Top10/2025). Beyond web, the classic CTF category set includes binary exploitation/pwn (buffer overflows and memory corruption), reverse engineering (recovering logic from a compiled binary), cryptography (implementation flaws, not math research), forensics (log and artifact analysis), and a networking/misc catch-all. For a first internal event, run four categories — web, crypto, forensics, and misc — and add pwn and reverse engineering only once you have participants with systems-programming backgrounds who won't stall on every challenge.
How do you tier difficulty for a mixed-skill engineering team?
Tier difficulty with a points system correlated to expected solve rate, the same convention used by picoCTF, PlaidCTF, and HackTheBox: challenges are priced at fixed bands — 100, 200, 300, 400, 500 — where the point value signals how many teams are expected to solve it, not how long it should take. A well-built 100-point web challenge should be solvable by an engineer who has never done security work in under fifteen minutes, often just by reading a cookie or inspecting a response header; a 500-point challenge should require chaining two bugs, such as an authentication bypass into a stored injection. Build roughly twice as many low-tier challenges as high-tier ones — a typical distribution is five at 100, four at 200, three at 300, two at 400, and one at 500 per category — so beginners always have a next challenge available and the leaderboard doesn't collapse into a two-team race for the hardest problems. Publish the point curve before the event starts; engineers self-select their tier far more accurately than an organizer guessing skill level in advance, and a visible scoreboard turns tiering into real-time feedback rather than a guess.
How long should an internal CTF run, and how often should you hold one?
A single-day event, four to eight hours, run quarterly, is the cadence that keeps a CTF program alive without turning it into a side project nobody has time for. A shorter two-to-three hour lunch-and-learn format works for onboarding new hires to a handful of easy challenges, but doesn't leave room for the harder tiers that create the most learning value — the 400s and 500s are where engineers genuinely struggle, ask each other for help, and internalize a bug class. Running quarterly rather than annually matters because challenge-writing skill and challenge reuse both decay fast: a flag format or bug pattern used once stays memorable for months, but an annual cadence means you're re-teaching the same lesson to a room that's largely forgotten it. Rotate challenge authors across your security and senior engineering staff each cycle so no single person becomes a bottleneck, and retire any challenge after two uses since write-ups circulate internally the moment an event ends.
How do you keep the challenges realistic instead of academic?
Keep challenges realistic by building them out of code and configurations your own engineers actually write, not out of contrived puzzle logic borrowed from a public CTF archive. A web challenge built around a real ORM misconfiguration that produces a second-order SQL injection teaches your Django or Rails engineers something they'll recognize in production code review; a challenge built around a hand-crafted custom encryption scheme teaches a cryptography trivia fact they'll never see again. The categories that make the best internal challenges are the same classes of bugs that application security testing tools flag in real code — injection, broken access control, SSRF, insecure deserialization — because a scanner tagging a finding with a CWE and OWASP category is describing the exact bug class a CTF challenge should simulate. Safeguard's SAST and DAST engines, for instance, trace findings from source to sink and tag them with CWE/OWASP mappings; pulling a handful of real (sanitized) findings from your own codebase's scan history and turning each into a standalone challenge is one of the fastest ways to build a board that teaches engineers to recognize the exact bugs your own tooling is already catching in their pull requests.
How Safeguard fits into a CTF training program
Safeguard doesn't run CTF infrastructure, but its SAST and DAST findings are a genuinely useful seed for challenge design because they're already categorized the way a CTF board needs to be. Every SAST finding carries a source-to-sink dataflow trace and a CWE/OWASP tag, and every DAST finding maps to the same runtime vulnerability classes — injection, access control, misconfiguration — that anchor the web exploitation category above. Security teams building an internal CTF can pull a sanitized, de-identified version of a real finding (say, an A05 injection finding or an SSRF finding tagged under A01 Broken Access Control) and turn it into a challenge that teaches engineers to recognize the pattern before it ever reaches a pull request, closing the loop between what your scanner catches automatically and what your engineers learn to avoid writing in the first place.