CTFd / CTFd/CTFd

[BUG] Custom Challenge (Polymorphic) Causes Persistent TypeError: o.preRender is not a function in Core Theme

Open
#2,864 2 comments 1 reaction 0 assignees View on GitHub
Dominant language
Python
Stars
6.8k
Forks
2.8k
Avg merge
1d 6h
Merged PRs (30d)
5

Description

When attempting to register a custom challenge type (inheriting BaseChallenge or DynamicValueChallenge) and load its content into the challenge modal, the core frontend script crashes immediately upon fetching the challenge data. This occurs because a legacy component of the theme's JavaScript insists on calling o.preRender or similar methods on the raw challenge object returned by the API.

This issue makes implementing any custom UI functionality for a custom challenge type highly unstable or impossible without resorting to core file modification or aggressive Python hacks.

Minimal Reproduction Steps:

Create a custom challenge plugin (e.g., llm_standard_challenge).

Define the challenge class inheriting from CTFdStandardChallenge or DynamicValueChallenge.

The plugin registers its view.js script and view.html template.

The Python read method either returns super().read(challenge) or attempts to manually inject HTML (as a bypass).

On the challenge board, click the custom challenge card.

Observed Crash (Core Theme JS):

The console throws a critical error originating from a minified internal file:

Uncaught TypeError: o.preRender is not a function

at index.b6be5691.js:3:1998 (or similar location in challenges.js)

Root Cause Analysis:

The crash happens because the theme's execution order is:

AJAX: Request GET /api/v1/challenges/.

Legacy Check: An old script component (running before the custom plugin's JavaScript loads/executes) attempts to process the returned JSON object as if it were an instance of an old challenge class.

Failure: Since the JSON object lacks a preRender() method, the script crashes, preventing the modal from displaying correctly or the custom view.js Alpine component from ever initializing.

Recommendation:

The core theme's challenge modal initialization routine needs to be audited to ensure that the calling of methods like preRender and render is conditional or entirely removed for types that do not explicitly define the legacy interface. The system should rely solely on the content provided in the data["view"] or Alpine.store("challenge").data object.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.