Skip to main content
Challenge Submission Requirements
Ryan Gordon avatar
Written by Ryan Gordon
Updated over a week ago

Challenge Requirements

  • If a challenge contains a dockerized component, it shall not include multiple containers but just one.

  • If the challenge contains docker, the memory usage shall not surpass more than 1 GB of RAM, or contact HTB staff to request an exception.

  • Flags in the form of HTB{som3_t3xt}, or contact HTB staff to request an exception (for example not having the flag format but just the contents of it, because the exploitation process requires it).

  • A fully automated solver must be included, or contact HTB staff to request an exception.


Please include:

  • Full writeup showing the intended path to own the challenge. A template is provided here (for machines, but also applicable to challenges). Please include an editable format of the write-up (markdown, word).

  • Description of important processes running on the challenge (ie, HTTP server using Flask, which is started by the service named flask. service).

  • Description of all automation, including copies of any scripts running on the challenge (crons, schedtasks, etc.)

  • If using Docker, please include Dockerfiles and other configuration files for containers.

  • Source code for any custom binaries.

  • Any details about how future patches might impact the exploit path (ie, this package used for the server deployment should be version pinned, as the exploit path requires this version’s vulnerability).

Best Practices


  • Try to keep the challenge realistic where possible.

  • Try to have the exploited code exist for some legit reason.

  • Don’t include things like todo.txt on a web server.

  • Don’t include rabbit holes without a good reason.

  • When picking passwords that are not intended to be cracked, please pick a strong passphrase (something solid but also not that hard to type).

  • Nothing inappropriate, trolly, offensive, political, or insulting.

  • Don’t require brute forcing other than above without talking to HTB staff. The challenge should not include unnecessary or unreasonable guessing.

  • The challenge should present a coherent path containing worthwhile elements. The task is to offer a rewarding challenge experience and “guide” the contestants through the design patterns to the solution.

  • Don’t make use of commercial (paid) software (including trials).

  • Do not include copyrighted material in any form.

  • Good code has a well-thought-out layout and architecture to make managing state obvious.

  • Don’t repeat code and do use a consistent name scheme.

  • Avoid writing long code lines and break down big tasks into smaller chunks.

  • If there’s a docker involved, keep the resulting docker image size as small as possible.

  • If there’s docker involved, keep your dockerized project simple to run. Just like ./ or similar.

Level Definitions

Very Easy: A beginner-friendly, entry-level topic for said category.

Easy / Medium: A topic that requires basic and/or intermediate knowledge of the security landscape in said category.

Hard / Insane: A topic that requires advanced/specialized knowledge of the security landscape in said category.

File Structure

This is the file structure that new challenges should follow. Please read this document before making your challenge submission.

The following are templates. You can always make your adjustments according to your challenge files, but the core structure should remain the same.

Static Challenges

There are two different templates shown above according to the challenge category. For example, the first image shows how a typical crypto challenge should look like, and the second is how a pwn/rev challenge should look like. Feel free to adjust the template according to your own challenge.


This should be the challenge writeup written in markdown language. On the challenge submission form, you will find a writeup template as well.

  • The 'challenge' Folder

This folder should include all the files related to the challenge. The first template assumes that there is a file, but you can ignore it if your challenge doesn’t include such a file. By excluding all of the data that should be kept secret (such as the flag, private keys, and so on), this is the folder you see when you unzip the downloadable.

  • The 'htb' Folder

This folder should contain the files required for solving the challenge.

Note: The solver should work without accessing the private data in the challenge folder at all! In this case, the Python script should solve the challenge without reading Make sure you adjust this concept based on your challenge files.

  • The 'release' Folder

This folder contains the challenge .zip that users download by clicking Download in HTB Labs. You basically have to create a folder with all the files from the challenge folder that are required to solve the challenge and zip it using the following


zip -9 -P hackthebox <category_challenge_name>.zip 

In this case, the .zip file should include the files and output.txt .

The zip file's name should follow our naming convention, which is shown in the image above. Also, if the challenge name contains any whitespaces, make sure you replace the whitespace with an underscore _ .

The zip file should be password-protected with the password hackthebox .

Apart from the final .zip file, the release folder should also include the files that were zipped. For example, suppose the challenge name is The Sunshine. Then the zip's file names should look like the examples below (suppose the challenge belongs to all categories):

Docker Challenges (Requiring connection to a remote instance)

Since the dockerfile can vary a lot among different categories, below we provide a Dockerfile template for the categories that usually require connecting to a remote instance. If you can't build the docker image, don't worry. Make sure you follow the above file structure conventions, submit your challenge, and we will investigate the issue upon reviewing your challenge.

The templates below are intended for more beginner users, so you are not required to follow them. In any case, we will review your challenge and make the final adjustments!


FROM python:3.9-slim-buster
RUN apt update && \
apt install -y socat && \
pip install pycryptodome
# Add application
WORKDIR /challenge
COPY challenge .
# Expose the port
# Switch to use a non-root user from here on
USER nobody
# Start the python application
CMD ["socat", "-dd", "TCP-LISTEN:1337,reuseaddr,fork", "exec:python -u /challenge/"]


FROM ubuntu:22.04
# Update
RUN apt update --fix-missing && \
apt install -y socat && \
rm -rf /var/lib/apt/lists/*
# Create ctf-user
RUN groupadd -r ctf && useradd -r -g ctf ctf
ADD challenge/ /home/ctf/
RUN chmod 440 /home/ctf/flag.txt
RUN chmod 666 /home/ctf/<name_of_the_binary>
USER ctf
ENTRYPOINT ["socat", "tcp-l:1337,reuseaddr,fork", "EXEC:./<name_of_your_binary>"]


FROM python:3.8-alpine
# Setup usr
RUN adduser -D -u 1000 -g 1000 -s /bin/sh www
# Install dependencies
RUN apk add --update --no-cache gcc g++ make libffi-dev openssl-dev
# Install packages
RUN apk add --update --no-cache nginx supervisor uwsgi-python3 chromium chromium-chromedriver
# Upgrade pip
RUN python -m pip install --upgrade pip
# Setup app
RUN mkdir -p /app
# Switch working environment
# Add application
COPY challenge .
# Install dependencies
RUN python -m venv venv
RUN ./app/venv/bin/activate && pip install -r requirements.txt
# Fix permissions
RUN chown -R www:www /var/lib/nginx
# Copy configs
COPY config/supervisord.conf /etc/supervisord.conf
COPY config/nginx.conf /etc/nginx/nginx.conf
# Expose port the server is reachable on
# Disable pycache
# Run supervisord
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

Did this answer your question?