CTFs as you need them
This report presents the forensic synthetic code analysis of CTFd/CTFd, a Python project with 6,741 GitHub stars. SynthScan v2.0 examined 93,037 lines of code across 746 source files, recording 882 pattern matches distributed across 13 syntactic categories. The overall adjusted score of 12.3 places this repository in the Low AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 882 distinct pattern matches across 13 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_views.py | 153 | def test_pages_routing_and_rendering(): | CODE |
| LOW | tests/test_views.py | 181 | def test_user_can_access_files(): | CODE |
| LOW | tests/test_views.py | 276 | def test_admin_access_files_with_auth_token(): | CODE |
| LOW | tests/test_views.py | 351 | def test_user_can_access_files_with_auth_token(): | CODE |
| LOW | tests/test_views.py | 486 | def test_user_can_access_files_if_view_after_ctf(): | CODE |
| LOW⚡ | tests/test_themes.py | 18 | def test_themes_run_in_sandbox(): | CODE |
| LOW⚡ | tests/test_themes.py | 33 | def test_themes_cant_access_configpy_attributes(): | CODE |
| LOW | tests/test_themes.py | 82 | def test_that_ctfd_can_be_deployed_in_subdir(): | CODE |
| LOW | tests/test_themes.py | 126 | def test_that_ctfd_subdir_redirects_work(): | CODE |
| LOW | tests/test_themes.py | 160 | def test_that_request_path_hijacking_works_properly(): | CODE |
| LOW | tests/test_themes.py | 187 | def test_theme_fallback_config(): | CODE |
| LOW | tests/test_themes.py | 231 | def test_theme_template_loading_by_prefix(): | CODE |
| LOW | tests/test_themes.py | 240 | def test_theme_template_disallow_loading_admin_templates(): | CODE |
| LOW | tests/test_config.py | 19 | def test_reverse_proxy_config(): | CODE |
| LOW | tests/test_config.py | 59 | def test_server_sent_events_config(): | CODE |
| LOW | tests/test_config.py | 74 | def test_trusted_hosts_config(): | CODE |
| LOW | tests/test_config.py | 174 | def test_preset_admin_token_config(): | CODE |
| LOW | tests/test_config.py | 248 | def test_preset_admin_no_promotion_existing_user(): | CODE |
| LOW | tests/test_config.py | 334 | def test_preset_admin_empty_credentials(): | CODE |
| LOW | tests/test_plugin_utils.py | 29 | def test_register_plugin_asset(): | CODE |
| LOW | tests/test_plugin_utils.py | 42 | def test_register_plugin_assets_directory(): | CODE |
| LOW | tests/test_plugin_utils.py | 71 | def test_admin_override_template(): | CODE |
| LOW | tests/test_plugin_utils.py | 85 | def test_register_plugin_script(): | CODE |
| LOW | tests/test_plugin_utils.py | 99 | def test_register_plugin_stylesheet(): | CODE |
| LOW | tests/test_plugin_utils.py | 113 | def test_register_admin_plugin_script(): | CODE |
| LOW | tests/test_plugin_utils.py | 127 | def test_register_admin_plugin_stylesheet(): | CODE |
| LOW | tests/test_plugin_utils.py | 143 | def test_register_admin_plugin_menu_bar(): | CODE |
| LOW | tests/test_plugin_utils.py | 166 | def test_register_user_page_menu_bar(): | CODE |
| LOW | tests/test_plugin_utils.py | 190 | def test_bypass_csrf_protection(): | CODE |
| LOW | tests/test_plugin_utils.py | 202 | def bypass_csrf_protection_test_route(): | CODE |
| LOW | tests/test_plugin_utils.py | 218 | def test_challenges_model_access_plugin_class(): | CODE |
| LOW | tests/helpers.py | 638 | def gen_module_audience_access(db, module_id, audience_id): | CODE |
| LOW | tests/oauth/test_redirect.py | 15 | def test_oauth_not_configured(): | CODE |
| LOW | tests/oauth/test_redirect.py | 28 | def test_oauth_configured_flow(): | CODE |
| LOW | tests/oauth/test_users.py | 8 | def test_num_users_oauth_limit(): | CODE |
| LOW | tests/cache/test_challenges.py | 14 | def test_adding_challenge_clears_cache(): | CODE |
| LOW | tests/cache/test_challenges.py | 47 | def test_deleting_challenge_clears_cache_solves(): | CODE |
| LOW | tests/cache/test_challenges.py | 87 | def test_deleting_solve_clears_cache(): | CODE |
| LOW | tests/cache/test_cache.py | 43 | def test_clear_all_user_sessions(): | CODE |
| LOW | tests/cache/test_cache.py | 72 | def test_cache_subclass_commands(): | CODE |
| LOW | tests/cache/test_cache.py | 88 | def test_redis_cache_subclass_commands(): | CODE |
| LOW | tests/challenges/test_challenge_types.py | 8 | def test_missing_challenge_type(): | CODE |
| LOW | tests/challenges/test_challenge_logic.py | 15 | def test_all_flags_challenge_logic(): | CODE |
| LOW | tests/challenges/test_challenge_logic.py | 66 | def test_all_flags_challenge_logic_teams_mode(): | CODE |
| LOW | tests/challenges/test_challenge_logic.py | 145 | def test_group_flags_challenge_logic_teams_mode(): | CODE |
| LOW | tests/challenges/test_challenge_logic.py | 227 | def test_challenge_default_logic_is_any(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 18 | def test_can_create_standard_dynamic_challenge(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 53 | def test_can_update_standard_dynamic_challenge(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 101 | def test_can_add_requirement_standard_dynamic_challenge(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 159 | def test_can_delete_standard_dynamic_challenge(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 193 | def test_standard_dynamic_challenge_loses_value_properly(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 246 | def test_standard_dynamic_challenge_doesnt_lose_value_on_update(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 279 | def test_standard_dynamic_challenge_value_isnt_affected_by_hidden_users(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 339 | def test_standard_dynamic_challenges_reset(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 369 | def test_standard_dynamic_challenge_linear_loses_value_properly(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 421 | def test_standard_challenges_default_to_static_function(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 495 | def test_standard_dynamic_challenge_update_overrides_manual_value(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 593 | def test_standard_dynamic_challenge_creation_requires_all_parameters(): | CODE |
| LOW | tests/challenges/test_standard_dynamic.py | 732 | def test_dynamic_challenge_update_requires_all_parameters(): | CODE |
| LOW | tests/challenges/test_ratings.py | 19 | def test_ratings_public_config(): | CODE |
| 526 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | CTFd/auth.py | 22 | from CTFd.utils.helpers import error_for, get_errors, markup | CODE |
| CRITICAL | CTFd/scoreboard.py | 9 | from CTFd.utils.helpers import get_infos | CODE |
| CRITICAL | CTFd/users.py | 10 | from CTFd.utils.helpers import get_errors, get_infos | CODE |
| CRITICAL | CTFd/teams.py | 14 | from CTFd.utils.helpers import get_errors, get_infos | CODE |
| CRITICAL | CTFd/challenges.py | 13 | from CTFd.utils.helpers import get_errors, get_infos | CODE |
| CRITICAL | CTFd/views.py | 47 | from CTFd.utils.helpers import get_errors, get_infos, markup | CODE |
| CRITICAL | CTFd/constants/plugins.py | 4 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/constants/config.py | 34 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/constants/config.py | 40 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/constants/assets.py | 8 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/utils/decorators/__init__.py | 196 | from CTFd.utils.helpers import info_for | CODE |
| CRITICAL | CTFd/models/__init__.py | 70 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/models/__init__.py | 165 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/models/__init__.py | 172 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/models/__init__.py | 224 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/models/__init__.py | 326 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/models/__init__.py | 1081 | from CTFd.utils.helpers import markup | CODE |
| CRITICAL | CTFd/themes/admin/static/assets/htmlmixed-CBfzcasR.js | 19 | `);var m=document.activeElement;Kt(h),setTimeout(function(){r.display.lineSpace.removeChild(d),m.focus(),m==i&&n.showPri | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_config.py | 258 | # Create a regular user with the same credentials as preset admin | COMMENT |
| MEDIUM | tests/challenges/test_challenge_logic.py | 22 | # Create a challenge | COMMENT |
| MEDIUM | tests/challenges/test_challenge_logic.py | 73 | # Create a challenge with "all" logic | COMMENT |
| MEDIUM | tests/challenges/test_challenge_logic.py | 89 | # Create a team with members using gen_team helper | COMMENT |
| MEDIUM | tests/challenges/test_challenge_logic.py | 152 | # Create a challenge with "group" logic | COMMENT |
| MEDIUM | tests/challenges/test_challenge_logic.py | 168 | # Create a team with members using gen_team helper | COMMENT |
| MEDIUM | tests/challenges/test_challenge_logic.py | 234 | # Create a challenge without specifying logic (should default to "any") | COMMENT |
| MEDIUM | tests/challenges/test_standard_dynamic.py | 474 | # Create a user and solve the challenge | COMMENT |
| MEDIUM | tests/challenges/test_ratings.py | 236 | # Create a user and challenge | COMMENT |
| MEDIUM | tests/challenges/test_ratings.py | 275 | # Create a user and challenge | COMMENT |
| MEDIUM | tests/challenges/test_ratings.py | 355 | # Create a user and challenge | COMMENT |
| MEDIUM⚡ | tests/users/test_auth.py | 388 | # Create a user | COMMENT |
| MEDIUM⚡ | tests/users/test_auth.py | 792 | # Create a user before configuring mail to not send any extra emails | COMMENT |
| MEDIUM | tests/users/test_auth.py | 614 | # Create a user with change_password=True | COMMENT |
| MEDIUM | tests/users/test_auth.py | 720 | # Create a user via API with change_password=True | COMMENT |
| MEDIUM | tests/users/test_fields.py | 227 | # Create the fields that we want | COMMENT |
| MEDIUM | tests/teams/test_fields.py | 264 | # Create a user and team who haven't filled any of their fields | COMMENT |
| MEDIUM | tests/teams/test_teams.py | 163 | # Create a team with only one member | COMMENT |
| MEDIUM | tests/teams/test_teams.py | 198 | # Create a team | COMMENT |
| MEDIUM⚡ | tests/api/v1/test_solutions.py | 404 | # Create a challenge | COMMENT |
| MEDIUM⚡ | tests/api/v1/test_solutions.py | 538 | # Create a challenge and solution | COMMENT |
| MEDIUM⚡ | tests/api/v1/test_solutions.py | 548 | # Create a regular user | COMMENT |
| MEDIUM⚡ | tests/api/v1/test_solutions.py | 612 | # Create a hidden challenge and solution | COMMENT |
| MEDIUM⚡ | tests/api/v1/test_solutions.py | 622 | # Create a regular user | COMMENT |
| MEDIUM⚡ | tests/api/v1/test_solutions.py | 676 | # Create a challenge and solution with state="hidden" | COMMENT |
| MEDIUM⚡ | tests/api/v1/test_solutions.py | 686 | # Create a regular user | COMMENT |
| MEDIUM⚡ | tests/api/v1/test_solutions.py | 848 | # Create a user | COMMENT |
| MEDIUM | tests/api/v1/test_solutions.py | 456 | # Create a challenge and solution | COMMENT |
| MEDIUM | tests/api/v1/test_solutions.py | 467 | # Create a regular user | COMMENT |
| MEDIUM | tests/api/v1/test_challenges.py | 379 | # Create a user and generate a solve from before the freeze time | COMMENT |
| MEDIUM | tests/api/v1/test_challenges.py | 390 | # Create a user and generate a solve from after the freeze time | COMMENT |
| MEDIUM | tests/api/v1/test_challenges.py | 433 | # Create a banned user and generate a solve for the challenge | COMMENT |
| MEDIUM | tests/api/v1/test_challenges.py | 816 | # Create a user and generate a solve from before the freeze time | COMMENT |
| MEDIUM | tests/api/v1/test_challenges.py | 827 | # Create a user and generate a solve from after the freeze time | COMMENT |
| MEDIUM | tests/api/v1/test_challenges.py | 865 | # Create a user and generate a solve for the challenge | COMMENT |
| MEDIUM | tests/api/v1/test_challenges.py | 1479 | # Create a challenge and a user | COMMENT |
| MEDIUM | tests/api/v1/test_hints.py | 103 | # Create a challenge and two hints, where hint2 requires hint1 as a prerequisite | COMMENT |
| MEDIUM | tests/api/v1/test_files.py | 112 | # Create a fake file | COMMENT |
| MEDIUM | tests/api/v1/test_teams.py | 873 | # Create a user with a team | COMMENT |
| MEDIUM | tests/api/v1/test_scoreboard.py | 169 | # Create a challenge | COMMENT |
| MEDIUM | …ts/api/v1/challenges/requirements/test_requirements.py | 78 | # Create a new user which will solve the prerequisite | COMMENT |
| MEDIUM | …ts/api/v1/challenges/requirements/test_requirements.py | 106 | # Create a new user which will solve the prerequisite and hide them | COMMENT |
| MEDIUM | …ts/api/v1/challenges/requirements/test_requirements.py | 135 | # Create a new user which will solve the prerequisite and ban them | COMMENT |
| MEDIUM | …ts/api/v1/challenges/requirements/test_requirements.py | 241 | # Create a new user which will solve the prerequisite | COMMENT |
| MEDIUM | tests/api/v1/users/test_users.py | 62 | # Create a user with a null password. Use raw SQL to bypass SQLAlchemy validates | COMMENT |
| MEDIUM | tests/api/v1/teams/test_teams.py | 36 | # Create a user with a null password. Use raw SQL to bypass SQLAlchemy validates | COMMENT |
| MEDIUM | tests/api/v1/teams/test_teams.py | 80 | # Create a new team | COMMENT |
| MEDIUM | CTFd/views.py | 189 | # Create an empty index page | COMMENT |
| MEDIUM | CTFd/utils/security/auth.py | 50 | # Create the preset admin user | COMMENT |
| MEDIUM | CTFd/models/__init__.py | 786 | # Create the team specific secret | COMMENT |
| MEDIUM | CTFd/api/v1/helpers/models.py | 1 | # This file is no longer used. If you're importing the function from here please update your imports | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_views.py | 181 | CODE | |
| LOW | tests/test_views.py | 276 | CODE | |
| LOW | tests/test_views.py | 351 | CODE | |
| LOW | tests/test_views.py | 486 | CODE | |
| LOW | tests/helpers.py | 210 | CODE | |
| LOW | tests/helpers.py | 250 | CODE | |
| LOW | tests/helpers.py | 550 | CODE | |
| LOW | tests/challenges/test_standard_dynamic.py | 193 | CODE | |
| LOW | tests/challenges/test_standard_dynamic.py | 279 | CODE | |
| LOW | tests/challenges/test_standard_dynamic.py | 369 | CODE | |
| LOW | tests/challenges/test_standard_dynamic.py | 495 | CODE | |
| LOW | tests/challenges/test_dynamic.py | 184 | CODE | |
| LOW | tests/challenges/test_dynamic.py | 266 | CODE | |
| LOW | tests/challenges/test_dynamic.py | 354 | CODE | |
| LOW | tests/utils/test_exports.py | 127 | CODE | |
| LOW | tests/utils/test_ctftime.py | 28 | CODE | |
| LOW | tests/utils/test_ctftime.py | 53 | CODE | |
| LOW | tests/utils/test_ctftime.py | 90 | CODE | |
| LOW | tests/utils/test_ctftime.py | 118 | CODE | |
| LOW | tests/users/test_challenges.py | 329 | CODE | |
| LOW | tests/users/test_challenges.py | 518 | CODE | |
| LOW | tests/users/test_auth.py | 786 | CODE | |
| LOW | tests/users/test_fields.py | 54 | CODE | |
| LOW | tests/teams/test_fields.py | 60 | CODE | |
| LOW | tests/api/v1/test_solutions.py | 532 | CODE | |
| LOW | CTFd/auth.py | 239 | CODE | |
| LOW | CTFd/auth.py | 444 | CODE | |
| LOW | CTFd/auth.py | 549 | CODE | |
| LOW | CTFd/config.py | 24 | CODE | |
| LOW | CTFd/teams.py | 191 | CODE | |
| LOW | CTFd/views.py | 394 | CODE | |
| LOW | CTFd/plugins/challenges/logic.py | 72 | CODE | |
| LOW | CTFd/admin/__init__.py | 81 | CODE | |
| LOW | CTFd/admin/__init__.py | 222 | CODE | |
| LOW | CTFd/utils/__init__.py | 45 | CODE | |
| LOW | CTFd/utils/config/visibility.py | 22 | CODE | |
| LOW | CTFd/utils/decorators/__init__.py | 61 | CODE | |
| LOW | CTFd/utils/decorators/__init__.py | 195 | CODE | |
| LOW | CTFd/utils/decorators/__init__.py | 69 | CODE | |
| LOW | CTFd/utils/decorators/__init__.py | 199 | CODE | |
| LOW | CTFd/utils/decorators/visibility.py | 16 | CODE | |
| LOW | CTFd/utils/decorators/visibility.py | 55 | CODE | |
| LOW | CTFd/utils/decorators/visibility.py | 89 | CODE | |
| LOW | CTFd/utils/decorators/visibility.py | 18 | CODE | |
| LOW | CTFd/utils/decorators/visibility.py | 57 | CODE | |
| LOW | CTFd/utils/decorators/visibility.py | 91 | CODE | |
| LOW | CTFd/utils/plugins/__init__.py | 53 | CODE | |
| LOW | CTFd/utils/user/__init__.py | 18 | CODE | |
| LOW | CTFd/utils/updates/__init__.py | 15 | CODE | |
| LOW | CTFd/utils/initialization/__init__.py | 203 | CODE | |
| LOW | CTFd/utils/initialization/__init__.py | 311 | CODE | |
| LOW | CTFd/utils/exports/serializers.py | 38 | CODE | |
| LOW | CTFd/utils/exports/__init__.py | 121 | CODE | |
| LOW | CTFd/utils/exports/__init__.py | 302 | CODE | |
| LOW | CTFd/utils/csv/__init__.py | 477 | CODE | |
| LOW | CTFd/utils/events/__init__.py | 81 | CODE | |
| LOW | CTFd/utils/events/__init__.py | 83 | CODE | |
| LOW | CTFd/utils/helpers/models.py | 4 | CODE | |
| LOW | CTFd/utils/email/__init__.py | 127 | CODE | |
| LOW | CTFd/utils/email/__init__.py | 155 | CODE | |
| 13 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | CTFd/__init__.py | 232 | CODE | |
| LOW | CTFd/__init__.py | 232 | CODE | |
| LOW | CTFd/__init__.py | 232 | CODE | |
| LOW | CTFd/__init__.py | 232 | CODE | |
| LOW | CTFd/__init__.py | 232 | CODE | |
| LOW | CTFd/__init__.py | 232 | CODE | |
| LOW | CTFd/__init__.py | 232 | CODE | |
| LOW | CTFd/__init__.py | 232 | CODE | |
| LOW | CTFd/plugins/dynamic_challenges/decay.py | 1 | CODE | |
| LOW | CTFd/plugins/challenges/decay.py | 1 | CODE | |
| LOW | CTFd/constants/config.py | 6 | CODE | |
| LOW | CTFd/constants/config.py | 6 | CODE | |
| LOW | CTFd/constants/config.py | 6 | CODE | |
| LOW | CTFd/constants/config.py | 6 | CODE | |
| LOW | CTFd/constants/config.py | 6 | CODE | |
| LOW | CTFd/constants/config.py | 6 | CODE | |
| LOW | CTFd/admin/__init__.py | 21 | CODE | |
| LOW | CTFd/admin/__init__.py | 22 | CODE | |
| LOW | CTFd/admin/__init__.py | 23 | CODE | |
| LOW | CTFd/admin/__init__.py | 24 | CODE | |
| LOW | CTFd/admin/__init__.py | 25 | CODE | |
| LOW | CTFd/admin/__init__.py | 26 | CODE | |
| LOW | CTFd/admin/__init__.py | 27 | CODE | |
| LOW | CTFd/admin/__init__.py | 28 | CODE | |
| LOW | CTFd/admin/__init__.py | 29 | CODE | |
| LOW | CTFd/admin/__init__.py | 30 | CODE | |
| LOW | CTFd/utils/security/signing.py | 6 | CODE | |
| LOW | CTFd/utils/security/signing.py | 6 | CODE | |
| LOW | CTFd/utils/security/signing.py | 6 | CODE | |
| LOW | CTFd/api/v1/statistics/__init__.py | 8 | CODE | |
| LOW | CTFd/api/v1/statistics/__init__.py | 9 | CODE | |
| LOW | CTFd/api/v1/statistics/__init__.py | 10 | CODE | |
| LOW | CTFd/api/v1/statistics/__init__.py | 11 | CODE | |
| LOW | CTFd/api/v1/statistics/__init__.py | 12 | CODE | |
| LOW | CTFd/api/v1/statistics/__init__.py | 13 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | populate.py | 467 | # Check if this user has already rated this challenge | COMMENT |
| LOW | tests/test_views.py | 306 | # Set CTF to start in the future (before CTF start scenario) | COMMENT |
| LOW⚡ | tests/users/test_auth.py | 381 | # Set CTFd to send emails | COMMENT |
| LOW⚡ | tests/users/test_auth.py | 795 | # Set CTFd to send emails | COMMENT |
| LOW | tests/users/test_auth.py | 328 | # Set CTFd to only allow confirmed users and send emails | COMMENT |
| LOW | tests/api/v1/user/test_hints.py | 190 | # Set challenges to be visible publicly | COMMENT |
| LOW | tests/api/v1/user/test_hints.py | 236 | # Set challenges to be visible to only authed | COMMENT |
| LOW | CTFd/auth.py | 456 | # Check if credentials match preset admin | COMMENT |
| LOW | CTFd/auth.py | 470 | # Check if the user submitted an email address or a team name | COMMENT |
| LOW | CTFd/auth.py | 606 | # Check if we are allowing registration before creating users | COMMENT |
| LOW | CTFd/views.py | 266 | # Set theme to default and try again | COMMENT |
| LOW | CTFd/plugins/migrations.py | 66 | # Check if the plugin has migraitons | COMMENT |
| LOW | CTFd/plugins/challenges/logic.py | 84 | # Check if the user's submission is correct | COMMENT |
| LOW | CTFd/admin/users.py | 90 | # Check if the user has an account (team or user) | COMMENT |
| LOW | CTFd/utils/security/auth.py | 41 | # Check if user already exists | COMMENT |
| LOW | CTFd/utils/user/__init__.py | 22 | # Check if the session is still valid | COMMENT |
| LOW | CTFd/utils/exports/__init__.py | 182 | # Check if the alembic version is from CTFd 1.x | COMMENT |
| LOW | CTFd/api/v1/challenges.py | 199 | # Iterate through the list of challenges, adding to the object which | COMMENT |
| LOW | CTFd/api/v1/challenges.py | 1220 | # Check if challenge is visible to the user | COMMENT |
| LOW | CTFd/api/v1/challenges.py | 1227 | # Check if user/team has solved this challenge (only allow rating if solved) | COMMENT |
| LOW | CTFd/api/v1/challenges.py | 1313 | # Check if challenge is visible to the user | COMMENT |
| LOW | CTFd/api/v1/helpers/request.py | 39 | # Check if the schema is for enums, if so, we just add in the "enum" key | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | requirements.txt | 1 | # | COMMENT |
| LOW | requirements.txt | 21 | bcrypt==4.0.1 | COMMENT |
| LOW | requirements.txt | 41 | # via flask | COMMENT |
| LOW | requirements.txt | 61 | # via -r requirements.in | COMMENT |
| LOW | requirements.txt | 81 | # sqlalchemy | COMMENT |
| LOW | requirements.txt | 101 | jsonschema-specifications==2025.4.1 | COMMENT |
| LOW | requirements.txt | 121 | # python-geoacumen-city | COMMENT |
| LOW | requirements.txt | 141 | # freezegun | COMMENT |
| LOW | requirements.txt | 161 | # referencing | COMMENT |
| LOW | requirements.txt | 181 | typing-extensions==4.14.1 | COMMENT |
| LOW | tests/utils/test_validators.py | 161 | COMMENT | |
| LOW | tests/utils/test_events.py | 221 | # "team": None, | COMMENT |
| LOW | tests/utils/test_events.py | 241 | # data=saved_event["data"], type="notification", channel="ctf" | COMMENT |
| LOW | tests/users/test_challenges.py | 81 | # email = "user{}@examplectf.com".format(c) | COMMENT |
| LOW | tests/users/test_challenges.py | 101 | # "1": 5, | COMMENT |
| LOW | CTFd/config.ini | 1 | # CTFd Configuration File | COMMENT |
| LOW | CTFd/config.ini | 21 | # | COMMENT |
| LOW | CTFd/config.ini | 61 | # REDIS_URL | COMMENT |
| LOW | CTFd/config.ini | 101 | # Comma seperated string containing valid host names for CTFd to respond to. If not specified, | COMMENT |
| LOW | CTFd/config.ini | 161 | # MAILSENDER_ADDR | COMMENT |
| LOW | CTFd/config.ini | 181 | # By default CTFd will automatically detect the correct email provider based on the other settings | COMMENT |
| LOW | CTFd/config.ini | 201 | # AWS secret token used to authenticate to the S3 bucket. Only used under the s3 uploader. | COMMENT |
| LOW | CTFd/config.ini | 221 | COMMENT | |
| LOW | CTFd/config.ini | 241 | # See https://werkzeug.palletsprojects.com/en/0.15.x/middleware/proxy_fix/#werkzeug.middleware.proxy_fix.ProxyFix. | COMMENT |
| LOW | CTFd/config.ini | 261 | # SWAGGER_UI | COMMENT |
| LOW | CTFd/config.ini | 281 | # Defaults to true | COMMENT |
| LOW | CTFd/config.ini | 301 | # EMAIL_CONFIRMATION_REQUIRE_INTERACTION | COMMENT |
| LOW | CTFd/config.ini | 321 | # PRESET_ADMIN_NAME | COMMENT |
| LOW | CTFd/config.ini | 341 | # Configuration values that will be loaded into CTFd and take precedence over database settings. | COMMENT |
| LOW | CTFd/utils/validators/__init__.py | 21 | # Remove any leading and trailing C0 control or space from input. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/api/v1/test_solutions.py | 853 | # Step 1: Before solving, user queries the challenge detail endpoint | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 863 | # Step 2: Check the challenge solution endpoint - should also return no solution_id | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 871 | # Step 3: User attempts to view the solution directly - should fail (404 for hidden solutions) | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 875 | # Step 4: User solves the challenge | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 885 | # Step 5: After solving, user queries the challenge detail endpoint again | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 895 | # Step 6: User queries the challenge solution endpoint - should now return solution_id | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 903 | # Step 7: User tries to view the solution - should see it but content is locked (not unlocked yet) | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 927 | # Step 9: Verify the unlock was recorded in the database | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 935 | # Step 10: User views the solution again - now they should see the full content | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 946 | # Step 12: Create another user who has NOT solved the challenge | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 951 | # Step 13: Other user queries the challenge detail endpoint | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 960 | # Step 14: Other user queries the solution endpoint directly | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 969 | # Step 15: Other user tries to view the solution directly | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 974 | # Step 16: Other user attempts to unlock the solution | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 987 | # Step 17: Verify the unlock was recorded for the other user | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 995 | # Step 18: Other user tries to view the solution AGAIN after unlocking | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 1014 | # Step 19: Other user now solves the challenge | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 1024 | # Step 20: After solving, other user should now see the solution_id | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 1031 | # Step 21: Other user can now view the solution with full content | COMMENT |
| LOW | tests/api/v1/test_solutions.py | 915 | # Step 8: User unlocks the solution via the unlock API | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/api/v1/test_solutions.py | 853 | # Step 1: Before solving, user queries the challenge detail endpoint | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 863 | # Step 2: Check the challenge solution endpoint - should also return no solution_id | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 871 | # Step 3: User attempts to view the solution directly - should fail (404 for hidden solutions) | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 875 | # Step 4: User solves the challenge | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 885 | # Step 5: After solving, user queries the challenge detail endpoint again | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 895 | # Step 6: User queries the challenge solution endpoint - should now return solution_id | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 903 | # Step 7: User tries to view the solution - should see it but content is locked (not unlocked yet) | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 927 | # Step 9: Verify the unlock was recorded in the database | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 935 | # Step 10: User views the solution again - now they should see the full content | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 946 | # Step 12: Create another user who has NOT solved the challenge | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 951 | # Step 13: Other user queries the challenge detail endpoint | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 960 | # Step 14: Other user queries the solution endpoint directly | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 969 | # Step 15: Other user tries to view the solution directly | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 974 | # Step 16: Other user attempts to unlock the solution | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 987 | # Step 17: Verify the unlock was recorded for the other user | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 995 | # Step 18: Other user tries to view the solution AGAIN after unlocking | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 1014 | # Step 19: Other user now solves the challenge | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 1024 | # Step 20: After solving, other user should now see the solution_id | COMMENT |
| LOW⚡ | tests/api/v1/test_solutions.py | 1031 | # Step 21: Other user can now view the solution with full content | COMMENT |
| LOW | tests/api/v1/test_solutions.py | 915 | # Step 8: User unlocks the solution via the unlock API | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | populate.py | 285 | except Exception: | CODE |
| LOW | populate.py | 488 | except Exception: | CODE |
| LOW | ping.py | 29 | except Exception as e: | CODE |
| LOW⚡ | tests/test_themes.py | 28 | except Exception as e: | CODE |
| LOW | tests/api/test_tokens.py | 38 | except Exception as e: | CODE |
| LOW | tests/api/test_tokens.py | 46 | except Exception as e: | CODE |
| LOW | CTFd/views.py | 282 | except Exception: | CODE |
| LOW | CTFd/utils/initialization/__init__.py | 360 | except Exception: | CODE |
| LOW | CTFd/utils/exports/__init__.py | 176 | except Exception: | CODE |
| LOW | CTFd/utils/exports/__init__.py | 264 | except Exception: | CODE |
| LOW | CTFd/utils/exports/__init__.py | 487 | except Exception: | CODE |
| LOW | CTFd/utils/sessions/__init__.py | 87 | except Exception: | CODE |
| LOW | CTFd/utils/email/providers/smtp.py | 74 | except Exception as e: | CODE |
| LOW | CTFd/cli/__init__.py | 84 | except Exception as e: | CODE |
| MEDIUM | CTFd/cli/__init__.py | 81 | def import_ctf(path, delete_import_on_finish=False): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/helpers.py | 129 | CODE | |
| LOW | CTFd/plugins/challenges/__init__.py | 127 | CODE | |
| LOW | CTFd/utils/__init__.py | 28 | CODE | |
| LOW | CTFd/utils/challenges/__init__.py | 127 | CODE | |
| LOW | CTFd/utils/user/__init__.py | 98 | CODE | |
| LOW | CTFd/utils/user/__init__.py | 132 | CODE | |
| LOW | CTFd/utils/exports/serializers.py | 36 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | CTFd/utils/security/sanitize.py | 40 | "input": ["name", "type", "value", "placeholder"], | CODE |
| LOW⚡ | CTFd/utils/security/sanitize.py | 41 | "select": ["name", "value", "placeholder"], | CODE |
| LOW⚡ | CTFd/utils/security/sanitize.py | 43 | "textarea": ["name", "value", "placeholder"], | CODE |
| LOW | …hemes/admin/static/assets/pages/statistics-IfjpOVH0.js | 1 | import{_ as A,C as h,c,a as t,t as u,h as m,l as v,F as g,r as f,w as p,j as y,v as I,d as C,o as d,i as S,N as U,$ as k | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | CTFd/api/v1/helpers/request.py | 39 | # Check if the schema is for enums, if so, we just add in the "enum" key | COMMENT |