Challenges
There are two main categories of challenges hosted for BearcatCTF. Each requires a different build process and infrastructure footprint for deployment.
For functional reference templates, check the BearcatCTF Challenges repository.
1. Challenge Types (Architecture)
Static Challenges
Challenges that do not require a live server or backend. Players download artifact files locally to extract the flag. - Examples: Reverse engineering binaries, stego images, PCAP files, or audio forensics. - Infra Footprint: Hosted purely as static file downloads via CTFd/S3
Dynamic Challenges
Challenges that require a live backend server for player interaction
- Examples: Web exploits, pwn/nc targets, or active cryptography services.
- Infra Footprint: Containerized via Dockerfile, deployed to AWS EC2 instances running Docker.
2. File Directory Requirements
Every challenge submission requires a specific set of files based on its type.
| File | Static | Dynamic | Description |
|---|---|---|---|
| challenge.yaml | Required | Required | Metadata and deployment configuration for CTF-Tool. |
| readme.md | Required | Required | Documentation for the internal CTF helpdesk / triage team. |
| Dockerfile | Optional | Required | Container build specification for AWS deployment. |
| solve.py | Optional | Required | Python 3 script for automated health check Lambdas. |
3. Configuration Files
Below is the detailed specification for each of the files mentioned in the requirements matrix.
challenge.yaml
This file is used to help package the challenge up to be deployed within CTF-Tool. Without this file, your challenge will not get bundled into the rest of the challenges for the import into CTFd. Here is an example of a valid challenge.yaml
version: 1
challenges:
Challenge Name:
author: Name # Your first name or alias
brief: PHP SQL Injection # Brief internal technical summary (not public)
flag: BCCTF{abc} # Use 'file:flag.txt' to source from a separate file
case_sensitive: false
flag_type: static # Use 'regex' for pattern matching
message: Hello player! # Public description string OR 'file:message.txt'
player_files: file1.py, file2.txt # Files available for player download
# --- DYNAMIC CHALLENGE PROPERTIES ONLY ---
dockerfile: Dockerfile
connection_hint: http://{{event.address}}:{{chal.port}}/ # DO NOT EDIT
privileged: false # Requires explicit approval from Infra Lead
Do not modify the dockerfile, connection_hint, or privileged default values unless instructed. Incorrect values will break pipeline orchestration.
readme.md
Internal documentation explaining the challenge concept, intended solution path, and standard triage steps for the helpdesk. Written in standard Markdown.
Dockerfile (Dynamic Only)
Defines the runtime environment for the AWS EC2 cluster.
You must pin your base image versions. Utilizing :latest will break the deployment pipeline. Use specific tags (e.g., ubuntu:22.04 or alpine:3.23.4).
solve.py (Dynamic Only)
An automated exploit script executed by AWS Lambda health checks to verify the challenge is up and solving correctly.
- Language: Python 3 only.
- Dependencies: Stick to standard library packages (
socket,urllib,json) or highly standard modules to fit within the Lambda execution boundary.
4. Optional / Content Files
flag.txt: Holds the solution flag if reference-linked inchallenge.yaml.message.txt: Holds the public-facing challenge description if externalized from the YAML.challenge/Folder: Recommended directory to consolidate raw source code or asset files if your challenge requires a messy build context.