Skip to content

Conversation

@TheodorKitzenmaier
Copy link
Contributor

Implements additional features of the dojo application. Planned features for inclusion in this pr are:

  • Flag submission
  • Restarting the current challenge
  • Starting a new challenge

Container auth token is now a signed token instead of a random byte string.
- The server signs the account id, challenge id, and an additional string.
- The challenge ID is included to ensure that the token matches the active challenge.

This allows for verification of the owner of the token and efficient authentication of challenge containers.
Changed return from just the user id to both the user and challenge ids.
- Required for challenge matching.
Added the API endpoint for use by internal container integration.

Key features:
- Gets an authentication token from request headers (auth_token).
- Performs authentication that the token is correctly signed and matches the active challenge container.
- API calls create a session for the duration of the request.
    - The session is destroyed upon completion of the request.
CTFD is open with IP 10.0.0.117.
- iptables configured to accept connections from 10.0.0.0/8 (challenge containers?) to 10.0.0.117 (ctfd).
If we were to use the before/teardown_request decorators, it would have to be applied to the entire application.
- The overhead of this seems excessive, and I see no advantage in running the session teardown check on every endpoing.
- Why Flask does not offer the ability to specify before/after/teardown at the namespace level, I do not know.
Challenge containers now communicate with the nginx container instead of the ctfd container.
Added a python application, starting with a whoami command.
Added a testcase for the dojo cli application.
- WHOAMI command is tested to ensure it returns the name of the random user.
Switched from URLSafeSerializer to URLSafeTimedSerializer to ensure that container tokens are only valid for the maximum lifespan of a container.
dojo-cli.nix is at ./core, not ./code...
Switched from `Requests` to `Urllib`.
Custom auth token header isn't showing up for some reason.
Switched from using auth_token as header to AuthToken.
- Headers with underscores are dropped?

Fixed incorrect signing of container token.
- Docker was incorrectly using `challenge.challenge_id` instead of `challenge.id`.
Improved error handling of CLI application.

Create an `apiRequest` function with "robust" error handling for use in later versions.
Attempt to allow challenge containers to communicate with the main dojo node.
- Open 192.168.42.1 to challenge containers.
Added submit api to the integration endpoint.
Added submit command to dojo cli.
Fixed incorrect arguments for the solve integration function.
Added a test case for the dojo submit command.
- Tests submitting a correct flag.
- Tests submitting to a solved challenge.
Return empty dictionary when failing to find user's container.
Fixed restart test (challenge should support privileged).

Added test to ensure a challenge cannot be restarted in privileged mode if the challenge does not support it.
Added a parser for the start command.
Added start command to application.
Added test cases for the start command.
- Start with absolute path
- Start with relative path
- Start in privileged mode
- Start in privileged mode (unsupported challenge)

Fixed some typos.
Improved output format string.

Compare container dojo with welcome dojo without hex diff.
Further cleaned up start tests.
@TheodorKitzenmaier TheodorKitzenmaier marked this pull request as ready for review January 23, 2026 09:36
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51b212a5eb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +38 to +41
challenge = get_current_challenge()
response = requests.post(
f"{DOJO_API}/dojos/{challenge["dojo"]}/{challenge["module"]}/{challenge["challenge"]}/solve",
headers={"Authorization": f"Bearer {DOJO_AUTH_TOKEN}"},

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate current challenge payload before indexing

When there is no active challenge, GET /docker returns {"success": false, "error": "No active challenge"} with a 200 status, so get_current_challenge() will return an error payload. Indexing it here (challenge["dojo"], etc.) raises a KeyError, which surfaces as a stacktrace for commands like dojo submit, dojo restart, or dojo start (relative paths) when no container is running. Consider checking the success flag (or required keys) in get_current_challenge() and exiting with a user-friendly message before callers access fields.

Useful? React with 👍 / 👎.

@codecov
Copy link

codecov bot commented Jan 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@hidehiroanto
Copy link
Contributor

parse_dojo_path makes no sense, you can't have module or challenge set to None, just do challenge or /dojo/module/challenge using regex

@TheodorKitzenmaier
Copy link
Contributor Author

For this PR it doesn't really have a purpose, I implemented it for reuse as part of the the dojo list command where you might be listing the modules within a dojo, so module and challenge would be None in that case. It might still be cleaner to handle that as its own case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants