Task files
YATB is intended to use with declarative task management: files describe the tasks on the board.
The command-line interface (CLI) reads these files and updates YATB.
The sync command reads the tasks folder inside its target repository.
Use the complete task repository as the target for sync.
Synchronization deletes board tasks that it does not find in that repository.
Even an empty or missing tasks folder leaves all board tasks marked for deletion.
File format
Any folder containing a file named task.yaml (yaml! not yml) is a task folder.
The CLI searches for this exact name, including in nested folders.
It skips a task if its immediate parent folder name starts with a dot.
The FileTask model defines the fields and their defaults:
name: Task Name
description: |-
Multiline Task Description. Hello <https://yaml-multiline.info>.
This is:
1. Keep newlines
2. No newline at end
imho, this is the best possible option.
Renders as markdown -> html inside YATB.
author: '@Rubikoid'
category: web # you can write here effectivly anything, but see below
flag: prefix{flag} # if you didn't specify prefix and `{}` - it will autoselected based on upstream YATB CTF settings.
dynamic_scoring: false
static_scoring_points: 1000 # has effect only when dynamic_scoring=false
dynamic_scoring_decay: 50 # has effect only when dynamic_scoring=true
dynamic_features: []
# flags of dynamic features, supported by task:
# - service # task must be ran in k8s; see below
# - builder # task data must be builded and returned to user; see below
# - vm # broken
# - vpn # broken
hidden: true # show or not task to users. can be changed only here.
# id: 123e4567-e89b-12d3-a456-426614174000 # this is autogenerated. you should never supply it by yourself. or you known what you doin; MUST BE UNIQ ACROSS ONE YATB INSTANCE
# vm_ports: [] # also autogenerated
YATB renders description as Markdown.
The |- marker preserves line breaks in the YAML value and removes the final newline.
Markdown determines how those line breaks appear on the task page.
If dynamic_scoring is omitted, it defaults to true.
Dynamic scoring reduces the score as more players solve the task.
The dynamic_scoring_decay field sets the solve count at which the score reaches its minimum.
Its default is 50.
The flag field accepts a full flag, such as prefix{flag}, or its inner text.
For inner text alone, the CLI uses FLAG_BASE from its local YATB configuration as the prefix.
It does not fetch the prefix from the server.
An empty dynamic_features list selects a fixed flag.
A nonempty list selects a flag generated for each player.
The category field accepts any string.
YATB selects its display color without changing the stored category.
The category mapping ignores letter case:
crypto,web, andforensiceach use their own color group.binary,reverse,pwn, andrevuse thebinarycolor group.- All other values use the
othercolor group.
The hidden field defaults to true.
Synchronization copies this value to the board, including after an administrator changes visibility there.
The unhide command can also make tasks visible.
Event timing and required tasks still control what players can see.
When the CLI creates a task, it writes the assigned id into task.yaml.
Keep this ID for later updates and do not copy it to another task.
The vm_ports field defaults to an empty list.
Task folders
The CLI uses folders next to task.yaml for source files and player downloads.
Public files are shared by all players.
The upload code defines how these folders are processed:
devcontains the Dockerfile and source files for a builder task, or any possible files that required to develop taskpubliccontains files to upload as structured task attachments, with their size and SHA256.deploycontains the service definition indocker-compose.ymland any files needed to build its images.solutionis an optional folder for solution notes, such asREADME.md, and the uploader does not process it.
One or two files in public are uploaded individually. More files, or any subdirectory,
are packed into files.tar.gz; its attachment describes the downloadable archive itself.
Additional attachments can be declared in task.yaml using the
Pydantic attachment models:
attachments:
- type: web
label: Open challenge
url: https://challenge.example.org
- type: endpoint
label: TCP service
host: challenge.example.org
port: 31337
Declared attachments come first, followed by uploaded files sorted by name. Each sync replaces the attachment list, so removing a public file or a declared attachment also removes it from the task.
Dynamic features
A dynamic task runs a service or generates files for a player.
The dynamic task controller (DTC) manages this work in Kubernetes.
Set dynamic_features to [service], [builder], or [service, builder] to select these features.
The file format also accepts vm and vpn.
A virtual machine (VM) runs a separate operating system.
The VM implementation is unfinished, and the task runner has no action for the VPN feature.
This guide covers service and builder tasks.
Service tasks
For a service task, put docker-compose.yml in the deploy folder.
DTC translates a subset of Docker Compose into Kubernetes objects.
The Compose model defines this subset.
The file requires version as a string and a services mapping.
Each service needs either image or build.
The supported service fields are:
imagenames the container image.buildtakes precedence overimageand accepts a path or a mapping withcontextand optionaldockerfile.commandsupplies arguments to the image entry point and accepts a list or a string.portslists container ports that DTC makes available to players.environmentaccepts a mapping of strings or a list ofNAME=valuestrings.exposelists integer ports for access between services.resourcesetsrequestsandlimits, each withcpuandmemorystrings.
The resource field is a DTC extension, not the standard Compose resource configuration.
Omit vm, or set it to false, for container services.
The service runner skips entries with vm: true.
DTC resolves build paths and build.context relative to deploy.
The default Dockerfile is Dockerfile inside the build context.
An explicitly supplied relative build.dockerfile is resolved against deploy.
Use a list for command when an argument contains spaces.
DTC splits a string command at spaces without shell parsing.
The service runner passes the result as container arguments.
Write each ports entry as a quoted string, such as "8080" or "8080:80".
For "8080:80", DTC uses container port 80 and allocates the public port itself.
The service inside the container must listen on that container port.
The parser does not accept an IP address in a port entry.
DTC runs each service in a separate Kubernetes deployment.
A deployment manages the pods that run a container.
Ports listed under expose create internal services that use the Compose service name.
This provides communication between services without implementing all Docker Compose networking features.
YATB generates a flag for each player.
A Kubernetes Secret stores values that containers can read.
DTC supplies it through a Kubernetes Secret as the environment variable FLAG.
Read FLAG in the task program instead of embedding a fixed flag.
A fixed flag will not match the generated flag that YATB expects.
DTC starts a separate service instance for each player. A hash identifies the contents of the source archive. It reuses a built image when the registry contains a tag matching the source archive hash. Changed source files or a missing cached image can cause another build.
Builder tasks
A builder task runs the image built from dev/Dockerfile to generate player files.
The builder runner stores the output in S3.
If output already exists for that player and task, it reuses the first stored object instead of running the builder again.
Write one output file directly into EXPORT_PATH.
For several files, create an archive there yourself.
The uploader does not process subfolders, and the task result links to one uploaded object.
DTC supplies these environment variables to the builder:
EXPORT_PATHis the output folder, currently/build.FLAGis the flag generated for this player.RANDOM_STRING_SEQis a string derived from the flag and stays the same while that flag stays the same.BACKEND_HOSTandBACKEND_PORTidentify the first allocated service address, if the task starts a service with a public port.
Service containers also receive FLAG and RANDOM_STRING_SEQ.
DTC does not automatically supply BACKEND_HOST or BACKEND_PORT to service containers.
The Kubernetes connector defines these environment variables.