The source code that powers readthedocs.org
This report summarizes scanner evidence for readthedocs/readthedocs.org, a Python project with 8,396 GitHub stars. SynthScan examined 143,524 lines of code across 847 source files, recording 2314 pattern matches distributed across 20 syntactic categories. The legacy adjusted pattern signal is 18.1 (Elevated pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 2121 finding(s).
Are imports declared and package/API names verified? 86 finding(s).
Are wrappers, guards, and repeated structures necessary? 1998 finding(s).
Which changes need focused human review? 2314 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 2314 distinct pattern matches across 20 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. 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 configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/organizations/signals.py | 33 | def remove_organization_completely(sender, instance, using, **kwargs): | CODE |
| LOW | readthedocs/organizations/signals.py | 70 | def mark_organization_assets_not_cleaned(sender, instance, created, **kwargs): | CODE |
| LOW | readthedocs/organizations/querysets.py | 59 | def subscription_trial_plan_ended(self): | CODE |
| LOW | readthedocs/organizations/models.py | 36 | def _upload_organization_avatar_to(instance, filename): | CODE |
| LOW | readthedocs/organizations/models.py | 56 | def _get_user_content_storage(): | CODE |
| LOW | readthedocs/organizations/filters.py | 37 | def get_organization_queryset(self): | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 183 | def test_create_organization_with_empty_slug(self): | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 194 | def test_create_organization_with_invalid_unicode_slug(self): | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 206 | def test_create_organization_with_big_name(self): | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 215 | def test_create_organization_with_existent_slug(self): | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 226 | def test_create_organization_with_nonexistent_slug(self): | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 237 | def test_create_organization_with_invalid_slug(self): | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 247 | def test_create_organization_with_dns_invalid_slug(self): | CODE |
| LOW | readthedocs/organizations/tests/test_forms.py | 40 | def test_add_team_member_by_name(self): | CODE |
| LOW | readthedocs/organizations/tests/test_forms.py | 50 | def test_add_duplicate_member_by_username(self): | CODE |
| LOW | readthedocs/organizations/tests/test_forms.py | 63 | def test_add_team_member_by_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_forms.py | 83 | def test_add_team_invite_unverified_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_forms.py | 103 | def test_add_fresh_member_by_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_forms.py | 123 | def test_add_team_member_with_username_matching_other_user_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_forms.py | 143 | def test_add_team_member_with_username_matching_unverified_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_forms.py | 159 | def test_add_duplicate_invite_by_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 204 | def test_member_add_regression(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 211 | def test_member_delete_regression(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 229 | def test_team_add_slug_conflict(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 261 | def test_team_delete_regression(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 300 | def test_add_member_by_email_on_org_with_members(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 330 | def test_add_duplicate_member_by_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 356 | def test_add_existing_user_by_username(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 372 | def test_invite_already_invited_member_by_username(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 398 | def test_invite_already_existing_member_by_username(self): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 415 | def test_invite_user_from_the_same_org(self, send_email): | CODE |
| LOW | readthedocs/organizations/tests/test_orgs.py | 452 | def test_invite_myuself_to_team(self, send_email): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 96 | def test_update_avatar_invalid_dimensions(self): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 119 | def test_update_avatar_invalid_image(self): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 142 | def test_update_avatar_invalid_extension(self): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 197 | def test_delete_blocked_for_banned_owner(self): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 210 | def test_delete_blocked_for_spam_project_score(self, get_spam_score): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 270 | def test_add_owner_with_username_matching_other_user_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 288 | def test_add_owner_with_username_matching_unverified_email(self): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 560 | def test_choose_organization_edit(self): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 596 | def test_unspecified_slug_redirects_to_organization_edit(self): | CODE |
| LOW | readthedocs/organizations/tests/test_views.py | 617 | def test_choose_organization_edit(self): | CODE |
| LOW | readthedocs/organizations/tests/test_querysets.py | 97 | def test_organizations_with_trial_subscription_plan_ended(self): | CODE |
| LOW | readthedocs/organizations/tests/test_querysets.py | 139 | def test_organizations_to_be_disabled(self): | CODE |
| LOW | readthedocs/organizations/tests/test_querysets.py | 283 | def test_organizations_disable_serving(self): | CODE |
| LOW | readthedocs/organizations/tests/test_querysets.py | 357 | def test_organizations_clean_artifacts(self): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 135 | def test_filtered_queryset_choice(self, user, organization): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 150 | def test_filtered_queryset_invalid_choice(self, user, organization): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 173 | def test_organization_filter_choices(self, user, organization): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 221 | def test_filtered_queryset_project_choice(self, user, organization, project): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 245 | def test_filtered_queryset_project_invalid_choice( | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 276 | def test_filtered_queryset_team_choice( | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 302 | def test_filtered_queryset_team_invalid_choice(self, user, organization, project): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 329 | def test_project_filter_choices(self, user, organization, project): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 402 | def test_filtered_queryset_team_choice(self, user, organization, team): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 426 | def test_filtered_queryset_team_invalid_choice(self, user, organization, team): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 498 | def test_filtered_queryset_team_choice(self, user, organization, team, users): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 524 | def test_filtered_queryset_access_choice(self, user, organization, access, users): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 548 | def test_filtered_queryset_team_invalid_choice(self, user, organization): | CODE |
| LOW | readthedocs/organizations/tests/test_filters.py | 588 | def test_access_filter_choices(self, user, organization): | CODE |
| 1831 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | readthedocs/organizations/tests/test_orgs.py | 306 | # Create a team member that has no invite. | COMMENT |
| MEDIUM | readthedocs/settings/docker_compose.py | 70 | # Create a Token for an admin User and set it here. | COMMENT |
| MEDIUM | readthedocs/oauth/tests/test_githubapp_webhook.py | 1132 | # Create a webhook automation rule that matches docs files | COMMENT |
| MEDIUM | readthedocs/oauth/tests/test_githubapp_webhook.py | 1177 | # Create a webhook automation rule that matches docs files | COMMENT |
| MEDIUM | readthedocs/oauth/tests/test_githubapp_webhook.py | 1355 | # Create a webhook automation rule for external versions (PRs) | COMMENT |
| MEDIUM | readthedocs/oauth/tests/test_githubapp_webhook.py | 1442 | # Create a webhook automation rule for external versions (PRs) | COMMENT |
| MEDIUM | readthedocs/oauth/tests/test_githubapp_webhook.py | 1720 | # Create a webhook automation rule that only matches PRs (EXTERNAL), | COMMENT |
| MEDIUM | readthedocs/oauth/tests/test_githubapp_webhook.py | 1771 | # Create a webhook automation rule that only matches branches, not PRs. | COMMENT |
| MEDIUM⚡ | readthedocs/core/tests/test_db_utils.py | 270 | # Create a project with 3 versions | COMMENT |
| MEDIUM⚡ | readthedocs/core/tests/test_db_utils.py | 282 | # Create a project with 20 versions | COMMENT |
| MEDIUM⚡ | readthedocs/core/tests/test_db_utils.py | 324 | # Create a project with 5 versions | COMMENT |
| MEDIUM | readthedocs/core/tests/test_db_utils.py | 120 | # Create a project with multiple versions | COMMENT |
| MEDIUM | readthedocs/core/tests/test_db_utils.py | 214 | # Create a project with 3 versions | COMMENT |
| MEDIUM | readthedocs/core/tests/test_db_utils.py | 231 | # Create a project with exactly 5 versions | COMMENT |
| MEDIUM | readthedocs/core/tests/test_db_utils.py | 244 | # Create a project with 10 versions | COMMENT |
| MEDIUM | readthedocs/core/tests/test_db_utils.py | 257 | # Create a project with 25 versions | COMMENT |
| MEDIUM | readthedocs/core/tests/test_db_utils.py | 296 | # Create a project with 5 versions | COMMENT |
| MEDIUM | readthedocs/core/tests/test_db_utils.py | 310 | # Create a project with 10 versions | COMMENT |
| MEDIUM⚡ | readthedocs/vcs_support/base.py | 50 | # Defining a base API, so we'll have unused args | COMMENT |
| MEDIUM | readthedocs/projects/tasks/builds.py | 156 | # Create the object to store all the task-related data | COMMENT |
| MEDIUM | readthedocs/projects/tasks/builds.py | 405 | # Create the object to store all the task-related data | COMMENT |
| MEDIUM | readthedocs/projects/tests/test_build_tasks.py | 328 | # Create the artifact paths, so that `store_build_artifacts` | COMMENT |
| MEDIUM | readthedocs/projects/tests/test_build_tasks.py | 542 | # Create the artifact paths, so it's detected by the builder | COMMENT |
| MEDIUM | readthedocs/projects/tests/test_build_tasks.py | 918 | # Create the artifact paths, so it's detected by the builder | COMMENT |
| MEDIUM | readthedocs/projects/tests/test_build_tasks.py | 1200 | # Create the artifact paths, so it's detected by the builder | COMMENT |
| MEDIUM | readthedocs/projects/tests/test_build_tasks.py | 1464 | # Create the artifact paths, so it's detected by the builder | COMMENT |
| MEDIUM | readthedocs/projects/tests/test_domain_views.py | 199 | # Create the first domain | COMMENT |
| MEDIUM | readthedocs/projects/tests/test_domain_views.py | 207 | # Create the second domain | COMMENT |
| MEDIUM | readthedocs/builds/tests/test_trigger_build.py | 40 | # Create a running build | COMMENT |
| MEDIUM | readthedocs/builds/tests/test_trigger_build.py | 72 | # Create a running build | COMMENT |
| MEDIUM⚡ | readthedocs/builds/tests/test_buildconfig.py | 87 | # Create a build with actual config | COMMENT |
| MEDIUM⚡ | readthedocs/builds/tests/test_buildconfig.py | 92 | # Create a build with same config on the same version | COMMENT |
| MEDIUM | readthedocs/builds/tests/test_tasks.py | 217 | # Create a Build and manually assign the BuildConfig | COMMENT |
| MEDIUM | readthedocs/search/parsers.py | 265 | # Create a copy of the node to avoid manipulating the | COMMENT |
| MEDIUM | readthedocs/search/tests/test_views.py | 48 | # Create a project in bn and add it as a translation | COMMENT |
| MEDIUM | readthedocs/search/tests/test_views.py | 67 | # Create a project in bn and add it as a translation | COMMENT |
| MEDIUM | readthedocs/api/v2/client.py | 36 | # Define a retry mechanism trying to attempt to not fail in the first error. | COMMENT |
| MEDIUM | readthedocs/api/v3/tests/test_filters.py | 61 | # Create a running build. | COMMENT |
| MEDIUM | readthedocs/api/v3/tests/test_filters.py | 78 | # Create a running build to make sure it's excluded. | COMMENT |
| MEDIUM | readthedocs/doc_builder/environments.py | 717 | # Create the checkout path if it doesn't exist to avoid Docker creation | COMMENT |
| MEDIUM | readthedocs/doc_builder/environments.py | 897 | # Create the container in the same network the web container is | COMMENT |
| MEDIUM | readthedocs/doc_builder/director.py | 95 | # Create the VCS repository where all the commands are going to be | COMMENT |
| MEDIUM | readthedocs/doc_builder/director.py | 556 | # Create a symlink for ``root`` user to use the same ``.asdf`` | COMMENT |
| MEDIUM | readthedocs/doc_builder/tests/test_director.py | 30 | # Create a minimal data object that BuildDirector expects | COMMENT |
| MEDIUM | readthedocs/rtd_tests/tests/test_version.py | 16 | # Create a External Version. ie: pull/merge request Version. | COMMENT |
| MEDIUM | readthedocs/rtd_tests/tests/test_oauth.py | 1007 | # Create an external version (PR build) that is not built | COMMENT |
| MEDIUM | readthedocs/rtd_tests/tests/test_domains.py | 250 | # Creating the third (3) domain should fail the validation form | COMMENT |
| MEDIUM | readthedocs/rtd_tests/tests/test_api.py | 3552 | # Create a second GitHub integration for the same project with the same secret | COMMENT |
| MEDIUM | readthedocs/rtd_tests/tests/test_project.py | 43 | # Create a External Version. ie: pull/merge request Version. | COMMENT |
| MEDIUM | readthedocs/rtd_tests/tests/test_automation_rules.py | 943 | # Create a tag version | COMMENT |
| MEDIUM | scripts/upload.sh | 22 | # Create a symlink so the zip command uses the name "html" instead of last part of the directory. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | readthedocs/organizations/forms.py | 6 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | readthedocs/organizations/templatetags/organizations.py | 5 | from django.core.exceptions import FieldError | CODE |
| CRITICAL | readthedocs/domains/validators.py | 2 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | readthedocs/oauth/tests/test_models.py | 1 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | readthedocs/projects/validators.py | 7 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | readthedocs/projects/tasks/builds.py | 361 | response = self.data.api_client.build.concurrent.get( | CODE |
| CRITICAL | readthedocs/projects/tasks/utils.py | 13 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | readthedocs/projects/tests/test_validators.py | 2 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | readthedocs/projects/tests/test_models.py | 2 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | readthedocs/builds/version_slug.py | 25 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL⚡ | readthedocs/storage/tests/test_s3_storage.py | 22 | mock_bucket.objects.filter.return_value.delete.assert_called_once() | CODE |
| CRITICAL⚡ | readthedocs/storage/tests/test_s3_storage.py | 31 | mock_bucket.objects.filter.return_value.delete.assert_called_once() | CODE |
| CRITICAL | readthedocs/redirects/validators.py | 2 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | readthedocs/doc_builder/director.py | 577 | for tool, version in self.data.config.build.tools.items(): | CODE |
| CRITICAL | media/javascript/jquery/jquery-2.0.3.min.js | 23 | })}},k.pseudos.nth=k.pseudos.eq;for(T in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})k.pseudos[T]=u(T);for(T in{s | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | readthedocs/settings/docker_compose.py | 264 | except KeyError: | CODE |
| HIGH | readthedocs/core/forms.py | 36 | except AttributeError: | CODE |
| HIGH | readthedocs/vcs_support/backends/git.py | 364 | except ValueError: | CODE |
| HIGH | readthedocs/projects/models.py | 1650 | except KeyError: | CODE |
| HIGH | readthedocs/projects/ordering.py | 33 | except model.DoesNotExist: | CODE |
| HIGH | readthedocs/projects/version_handling.py | 52 | except UnicodeError: | CODE |
| HIGH | readthedocs/builds/models.py | 674 | except KeyError: | CODE |
| HIGH | readthedocs/storage/filesystem.py | 42 | except FileNotFoundError: | CODE |
| HIGH | readthedocs/search/parsers.py | 310 | except StopIteration: | CODE |
| HIGH | readthedocs/integrations/utils.py | 21 | except AttributeError: | CODE |
| HIGH | readthedocs/api/v2/views/model_views.py | 164 | except AttributeError: | CODE |
| HIGH | readthedocs/api/v3/tests/mixins.py | 261 | except ImportError: | CODE |
| HIGH | readthedocs/doc_builder/backends/sphinx.py | 92 | except ProjectConfigurationError: | CODE |
| HIGH | readthedocs/proxito/tests/test_hosting.py | 97 | except: | CODE |
| HIGH | readthedocs/proxito/tests/test_hosting.py | 103 | except: | CODE |
| HIGH | readthedocs/proxito/views/serve.py | 685 | except StorageFileNotFound: | CODE |
| HIGH | readthedocs/proxito/views/serve.py | 139 | except InfiniteRedirectException: | CODE |
| HIGH | readthedocs/proxito/views/serve.py | 282 | except InfiniteRedirectException: | CODE |
| HIGH | readthedocs/proxito/views/serve.py | 350 | except InfiniteRedirectException: | CODE |
| HIGH | readthedocs/proxito/views/serve.py | 491 | except InfiniteRedirectException: | CODE |
| HIGH | readthedocs/proxito/views/serve.py | 872 | except StorageFileNotFound: | CODE |
| HIGH | readthedocs/rtd_tests/base.py | 83 | except KeyError: | CODE |
| HIGH | readthedocs/rtd_tests/base.py | 102 | except (TypeError, KeyError): | CODE |
| HIGH | readthedocs/rtd_tests/tests/test_imported_file.py | 53 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker-compose.override.yml | 1 | # docker-compose.override.yml file to launch a full instance of Read the Docs. | COMMENT |
| LOW | requirements/deploy.txt | 1 | # | COMMENT |
| LOW | requirements/deploy.txt | 21 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 41 | bumpver==2026.1132 | COMMENT |
| LOW | requirements/deploy.txt | 61 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 81 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 101 | # via | COMMENT |
| LOW | requirements/deploy.txt | 121 | # django-simple-history | COMMENT |
| LOW | requirements/deploy.txt | 141 | django-debug-toolbar==8.0.0 | COMMENT |
| LOW | requirements/deploy.txt | 161 | django-simple-history==3.13.0 | COMMENT |
| LOW | requirements/deploy.txt | 181 | # via -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 201 | # django-elasticsearch-dsl | COMMENT |
| LOW | requirements/deploy.txt | 221 | # via -r requirements/deploy.in | COMMENT |
| LOW | requirements/deploy.txt | 241 | lexid==2021.1006 | COMMENT |
| LOW | requirements/deploy.txt | 261 | # requests-oauthlib | COMMENT |
| LOW | requirements/deploy.txt | 281 | prompt-toolkit==3.0.53 | COMMENT |
| LOW | requirements/deploy.txt | 301 | # via stack-data | COMMENT |
| LOW | requirements/deploy.txt | 321 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 341 | # via | COMMENT |
| LOW | requirements/deploy.txt | 361 | # via -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 381 | # via | COMMENT |
| LOW | requirements/deploy.txt | 401 | sqlparse==0.6.0 | COMMENT |
| LOW | requirements/deploy.txt | 421 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 441 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 461 | # via -r requirements/pip.txt | COMMENT |
| LOW | requirements/deploy.txt | 481 | # celery | COMMENT |
| LOW | requirements/testing.txt | 1 | # | COMMENT |
| LOW | requirements/testing.txt | 21 | asgiref==3.12.1 | COMMENT |
| LOW | requirements/testing.txt | 41 | # boto3 | COMMENT |
| LOW | requirements/testing.txt | 61 | # via | COMMENT |
| LOW | requirements/testing.txt | 81 | # via | COMMENT |
| LOW | requirements/testing.txt | 101 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/testing.txt | 121 | # django-filter | COMMENT |
| LOW | requirements/testing.txt | 161 | # via | COMMENT |
| LOW | requirements/testing.txt | 181 | # via | COMMENT |
| LOW | requirements/testing.txt | 201 | drf-flex-fields==1.0.2 | COMMENT |
| LOW | requirements/testing.txt | 221 | # via -r requirements/pip.txt | COMMENT |
| LOW | requirements/testing.txt | 241 | # botocore | COMMENT |
| LOW | requirements/testing.txt | 261 | # via jinja2 | COMMENT |
| LOW | requirements/testing.txt | 281 | # via | COMMENT |
| LOW | requirements/testing.txt | 301 | # psycopg | COMMENT |
| LOW | requirements/testing.txt | 321 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/testing.txt | 341 | pytest-django==4.14.0 | COMMENT |
| LOW | requirements/testing.txt | 361 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/testing.txt | 381 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/testing.txt | 401 | s3transfer==0.19.2 | COMMENT |
| LOW | requirements/testing.txt | 421 | # via sphinx | COMMENT |
| LOW | requirements/testing.txt | 441 | stripe==11.6.0 | COMMENT |
| LOW | requirements/testing.txt | 461 | # pydantic-core | COMMENT |
| LOW | requirements/testing.txt | 481 | # user-agents | COMMENT |
| LOW | requirements/testing.txt | 501 | # via -r requirements/pip.txt | COMMENT |
| LOW | requirements/docker.txt | 1 | # | COMMENT |
| LOW | requirements/docker.txt | 21 | # -r requirements/pip.txt | COMMENT |
| LOW | requirements/docker.txt | 41 | bumpver==2026.1132 | COMMENT |
| LOW | requirements/docker.txt | 61 | # via | COMMENT |
| LOW | requirements/docker.txt | 81 | # via | COMMENT |
| LOW | requirements/docker.txt | 101 | # pyquery | COMMENT |
| LOW | requirements/docker.txt | 121 | # django-csp | COMMENT |
| LOW | requirements/docker.txt | 161 | django-ipware==7.0.1 | COMMENT |
| LOW | requirements/docker.txt | 181 | djangorestframework==3.18.1 | COMMENT |
| 62 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/organizations/forms.py | 98 | except Exception: | CODE |
| LOW | readthedocs/oauth/tasks.py | 117 | except Exception: | CODE |
| LOW | readthedocs/oauth/tasks.py | 188 | except Exception: | CODE |
| LOW | readthedocs/oauth/services/bitbucket.py | 329 | except Exception: | CODE |
| LOW | readthedocs/oauth/services/gitlab.py | 357 | except Exception: | CODE |
| LOW | readthedocs/oauth/services/gitlab.py | 412 | except Exception: | CODE |
| LOW | readthedocs/oauth/services/gitlab.py | 473 | except Exception: | CODE |
| LOW | readthedocs/oauth/services/gitlab.py | 478 | except Exception: | CODE |
| LOW | readthedocs/oauth/services/github.py | 281 | except Exception: | CODE |
| LOW | readthedocs/core/signals.py | 78 | except Exception: # noqa | CODE |
| LOW | readthedocs/core/history.py | 56 | except Exception: | CODE |
| LOW | readthedocs/core/utils/contact.py | 90 | except Exception: | CODE |
| LOW | readthedocs/core/utils/tasks/public.py | 73 | except Exception as e: | CODE |
| LOW | readthedocs/core/views/hooks.py | 130 | except Exception: | CODE |
| LOW | readthedocs/embed/v3/views.py | 107 | except Exception: # noqa | CODE |
| LOW | readthedocs/embed/v3/views.py | 362 | except Exception: # noqa | CODE |
| LOW | readthedocs/projects/models.py | 2532 | except Exception: | CODE |
| LOW | readthedocs/projects/models.py | 2581 | except Exception: | CODE |
| LOW | readthedocs/projects/models.py | 2615 | except Exception: | CODE |
| MEDIUM | readthedocs/projects/forms.py | 1289 | def _get_cname(self, domain): | CODE |
| LOW | readthedocs/projects/forms.py | 1054 | except Exception as exc: | CODE |
| LOW | readthedocs/projects/forms.py | 1571 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/builds.py | 369 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/builds.py | 808 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/builds.py | 854 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/builds.py | 929 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/builds.py | 945 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/builds.py | 999 | except Exception as exc: | CODE |
| LOW | readthedocs/projects/tasks/builds.py | 1023 | except Exception as exc: | CODE |
| LOW | readthedocs/projects/tasks/builds.py | 1054 | except Exception: | CODE |
| MEDIUM | readthedocs/projects/tasks/builds.py | 359 | def _check_concurrency_limit(self): | CODE |
| MEDIUM | readthedocs/projects/tasks/builds.py | 1043 | def _log_directory_size(self, directory, media_type): | CODE |
| LOW | readthedocs/projects/tasks/utils.py | 136 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/utils.py | 142 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/utils.py | 368 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/utils.py | 447 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/storage.py | 90 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/search.py | 319 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/search.py | 330 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/search.py | 370 | except Exception: | CODE |
| LOW | readthedocs/projects/tasks/search.py | 415 | except Exception: | CODE |
| LOW | readthedocs/projects/views/private.py | 367 | except Exception: | CODE |
| LOW | readthedocs/builds/tasks.py | 229 | except Exception: | CODE |
| LOW | readthedocs/builds/tasks.py | 238 | except Exception: | CODE |
| LOW | readthedocs/builds/tasks.py | 427 | except Exception: | CODE |
| LOW | readthedocs/builds/tasks.py | 440 | except Exception: | CODE |
| LOW | readthedocs/builds/tasks.py | 562 | except Exception: | CODE |
| LOW | readthedocs/builds/tasks.py | 750 | except Exception: | CODE |
| LOW | readthedocs/builds/models.py | 951 | except Exception: | CODE |
| LOW | readthedocs/subscriptions/signals.py | 58 | except Exception: | CODE |
| LOW | readthedocs/subscriptions/views.py | 88 | except Exception: | CODE |
| LOW | readthedocs/search/tasks.py | 91 | except Exception: | CODE |
| LOW | readthedocs/search/parsers.py | 85 | except Exception: | CODE |
| LOW | readthedocs/search/parsers.py | 221 | except Exception as e: | CODE |
| LOW | readthedocs/search/parsers.py | 236 | except Exception: | CODE |
| LOW | readthedocs/search/parsers.py | 482 | except Exception: | CODE |
| LOW | readthedocs/search/utils.py | 70 | except Exception: | CODE |
| LOW | readthedocs/api/mixins.py | 49 | except Exception: | CODE |
| LOW | readthedocs/api/v2/views/model_views.py | 383 | except Exception: | CODE |
| LOW | readthedocs/aws/security_token_service.py | 114 | except Exception: | CODE |
| 5 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | readthedocs/oauth/services/bitbucket.py | 0 | gets provider data from git providers webhooks api. :param project: project :type project: project :param integration: i | STRING |
| HIGH | readthedocs/oauth/services/gitlab.py | 0 | gets provider data from git providers webhooks api. :param project: project :type project: project :param integration: i | STRING |
| HIGH | readthedocs/oauth/services/github.py | 0 | gets provider data from git providers webhooks api. :param project: project :type project: project :param integration: i | STRING |
| HIGH | readthedocs/oauth/services/base.py | 0 | gets provider data from git providers webhooks api. :param project: project :type project: project :param integration: i | STRING |
| HIGH | readthedocs/oauth/services/bitbucket.py | 0 | update webhook integration. :param project: project to set up webhook for :type project: project :param integration: web | STRING |
| HIGH | readthedocs/oauth/services/gitlab.py | 0 | update webhook integration. :param project: project to set up webhook for :type project: project :param integration: web | STRING |
| HIGH | readthedocs/oauth/services/github.py | 0 | update webhook integration. :param project: project to set up webhook for :type project: project :param integration: web | STRING |
| HIGH | readthedocs/oauth/services/base.py | 0 | update webhook integration. :param project: project to set up webhook for :type project: project :param integration: web | STRING |
| HIGH | readthedocs/oauth/services/gitlab.py | 0 | create commit status for project. :param build: build to set up commit status for :type build: build :param commit: comm | STRING |
| HIGH | readthedocs/oauth/services/github.py | 0 | create commit status for project. :param build: build to set up commit status for :type build: build :param commit: comm | STRING |
| HIGH | readthedocs/oauth/services/base.py | 0 | create commit status for project. :param build: build to set up commit status for :type build: build :param commit: comm | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/organizations/apps.py | 10 | CODE | |
| LOW | readthedocs/domains/apps.py | 11 | CODE | |
| LOW | readthedocs/oauth/apps.py | 10 | CODE | |
| LOW | readthedocs/core/utils/tasks/__init__.py | 3 | CODE | |
| LOW | readthedocs/core/utils/tasks/__init__.py | 3 | CODE | |
| LOW | readthedocs/core/utils/tasks/__init__.py | 7 | CODE | |
| LOW | readthedocs/core/utils/tasks/__init__.py | 8 | CODE | |
| LOW | readthedocs/core/utils/tasks/__init__.py | 9 | CODE | |
| LOW | readthedocs/config/__init__.py | 3 | CODE | |
| LOW | readthedocs/config/__init__.py | 5 | CODE | |
| LOW | readthedocs/config/__init__.py | 6 | CODE | |
| LOW | readthedocs/projects/apps.py | 15 | CODE | |
| LOW | readthedocs/projects/apps.py | 16 | CODE | |
| LOW | readthedocs/projects/apps.py | 17 | CODE | |
| LOW | readthedocs/projects/apps.py | 18 | CODE | |
| LOW | readthedocs/projects/apps.py | 19 | CODE | |
| LOW | readthedocs/projects/tests/mockers.py | 10 | CODE | |
| LOW | readthedocs/builds/apps.py | 17 | CODE | |
| LOW | readthedocs/builds/apps.py | 18 | CODE | |
| LOW | readthedocs/builds/tests/test_views.py | 3 | CODE | |
| LOW | readthedocs/subscriptions/apps.py | 13 | CODE | |
| LOW | readthedocs/subscriptions/apps.py | 14 | CODE | |
| LOW | readthedocs/subscriptions/apps.py | 15 | CODE | |
| LOW | readthedocs/subscriptions/tests/test_event_handlers.py | 8 | CODE | |
| LOW | readthedocs/search/apps.py | 9 | CODE | |
| LOW | readthedocs/gold/apps.py | 11 | CODE | |
| LOW | readthedocs/gold/tests/test_signals.py | 2 | CODE | |
| LOW | readthedocs/audit/apps.py | 14 | CODE | |
| LOW | readthedocs/telemetry/apps.py | 15 | CODE | |
| LOW | readthedocs/doc_builder/tests/test_director.py | 7 | CODE | |
| LOW | readthedocs/notifications/apps.py | 11 | CODE | |
| LOW | readthedocs/proxito/tests/handler_404_urls.py | 17 | CODE | |
| LOW | readthedocs/rtd_tests/utils.py | 14 | CODE | |
| LOW | readthedocs/rtd_tests/tests/test_notifications.py | 7 | CODE | |
| LOW | readthedocs/rtd_tests/tests/test_project.py | 1 | CODE | |
| LOW | readthedocs/rtd_tests/tests/test_project.py | 11 | CODE | |
| LOW | readthedocs/rtd_tests/tests/test_project.py | 14 | CODE | |
| LOW | readthedocs/rtd_tests/tests/test_project.py | 14 | CODE | |
| LOW | readthedocs/rtd_tests/tests/test_project.py | 14 | CODE | |
| LOW | readthedocs/rtd_tests/tests/test_project.py | 22 | CODE | |
| LOW | readthedocs/rtd_tests/files/conf.py | 3 | CODE | |
| LOW | readthedocs/rtd_tests/files/conf.py | 3 | CODE | |
| LOW | readthedocs/rtd_tests/files/conf.py | 3 | CODE | |
| LOW | readthedocs/invitations/apps.py | 15 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | readthedocs/organizations/forms.py | 46 | "email": forms.EmailInput(attrs={"placeholder": "accounting@example.com"}), | CODE |
| LOW⚡ | readthedocs/organizations/forms.py | 49 | attrs={"placeholder": "Engineering docs for Example company"} | CODE |
| LOW⚡ | readthedocs/organizations/forms.py | 52 | "url": forms.TextInput(attrs={"placeholder": "https://"}), | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 186 | "email": "test@example.org", | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 197 | "email": "test@example.org", | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 209 | "email": "test@example.org", | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 218 | "email": "test@example.org", | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 229 | "email": "test@example.org", | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 240 | "email": "test@example.org", | CODE |
| LOW⚡ | readthedocs/organizations/tests/test_forms.py | 250 | "email": "test@example.org", | CODE |
| LOW | readthedocs/domains/tests/test_tasks.py | 22 | self.user = get(User, email="user@example.com") | CODE |
| LOW⚡ | readthedocs/projects/forms.py | 1505 | "version_match_pattern": forms.TextInput(attrs={"placeholder": "^release-.*$"}), | CODE |
| LOW⚡ | readthedocs/projects/forms.py | 1506 | "webhook_labels_match_pattern": forms.TextInput(attrs={"placeholder": "^docs|build$"}), | CODE |
| LOW⚡ | readthedocs/projects/forms.py | 1508 | attrs={"placeholder": "^fix|feature$"} | CODE |
| LOW | readthedocs/projects/forms.py | 91 | self.fields["repo"].widget.attrs["placeholder"] = self.placehold_repo() | CODE |
| LOW | readthedocs/projects/forms.py | 463 | self.fields["repo"].widget.attrs["placeholder"] = self.placehold_repo() | CODE |
| LOW | readthedocs/projects/forms.py | 532 | "placeholder": "\n".join( | CODE |
| LOW | readthedocs/projects/forms.py | 814 | "placeholder": "\n".join( | CODE |
| LOW | readthedocs/projects/forms.py | 923 | "options_root_selector": forms.TextInput(attrs={"placeholder": "[role=main]"}), | CODE |
| LOW | readthedocs/projects/forms.py | 1476 | "placeholder": "\n".join( | CODE |
| LOW | readthedocs/search/tests/conftest.py | 16 | from .dummy_data import ALL_PROJECTS, PROJECT_DATA_FILES | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/settings/docker_compose.py | 253 | CODE | |
| LOW | readthedocs/oauth/tasks.py | 563 | CODE | |
| LOW | readthedocs/oauth/tasks.py | 642 | CODE | |
| LOW | readthedocs/core/management/commands/contact_owners.py | 122 | CODE | |
| LOW | readthedocs/core/utils/__init__.py | 362 | CODE | |
| LOW | readthedocs/core/utils/contact.py | 15 | CODE | |
| LOW | readthedocs/embed/v3/views.py | 158 | CODE | |
| LOW | readthedocs/config/config.py | 612 | CODE | |
| LOW | readthedocs/vcs_support/backends/git.py | 60 | CODE | |
| LOW | readthedocs/projects/filters.py | 55 | CODE | |
| LOW | readthedocs/projects/tasks/search.py | 272 | CODE | |
| LOW | readthedocs/projects/views/base.py | 19 | CODE | |
| LOW | readthedocs/projects/views/private.py | 302 | CODE | |
| LOW | readthedocs/projects/views/private.py | 104 | CODE | |
| LOW | readthedocs/builds/tasks.py | 641 | CODE | |
| LOW | readthedocs/subscriptions/views.py | 112 | CODE | |
| LOW | readthedocs/search/parsers.py | 239 | CODE | |
| LOW | readthedocs/search/api/v3/queryparser.py | 28 | CODE | |
| LOW | readthedocs/redirects/querysets.py | 50 | CODE | |
| LOW | readthedocs/api/v2/utils.py | 26 | CODE | |
| LOW | readthedocs/api/v2/views/model_views.py | 352 | CODE | |
| LOW | readthedocs/telemetry/collectors.py | 174 | CODE | |
| LOW | readthedocs/doc_builder/python_environments.py | 44 | CODE | |
| LOW | readthedocs/proxito/middleware.py | 123 | CODE | |
| LOW | readthedocs/proxito/views/hosting.py | 334 | CODE | |
| LOW | readthedocs/proxito/views/serve.py | 813 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/organizations/views/private.py | 93 | # Check if user has exactly 1 organization and automatically redirect in this case | COMMENT |
| LOW | readthedocs/core/mixins.py | 83 | # Check if resp is a redirect, which means the object was deleted | COMMENT |
| LOW⚡ | readthedocs/core/tests/test_db_utils.py | 187 | # Set limit to 1 | COMMENT |
| LOW⚡ | readthedocs/core/tests/test_db_utils.py | 329 | # Set limit to 1 | COMMENT |
| LOW | readthedocs/vcs_support/backends/git.py | 585 | # Check if ref is a branch of the origin remote | COMMENT |
| LOW | readthedocs/projects/models.py | 1089 | # Check if there is `_has_good_build` annotation in the queryset. | COMMENT |
| LOW | readthedocs/projects/tasks/builds.py | 230 | # Set GIT_SSH_COMMAND to use ssh with options that disable host key checking | COMMENT |
| LOW | readthedocs/projects/tasks/builds.py | 653 | # Check if there are multiple files on artifact directories. | COMMENT |
| LOW | readthedocs/projects/tasks/builds.py | 730 | # Check if the project is spam | COMMENT |
| LOW | readthedocs/doc_builder/director.py | 208 | # Check if the key has write access to the repository (RTD Business only). | COMMENT |
| LOW | readthedocs/doc_builder/director.py | 749 | # Set GIT_SSH_COMMAND to use ssh with options that disable host key checking | COMMENT |
| LOW | readthedocs/proxito/views/serve.py | 265 | # Check if the old language code format was used, and redirect to the new one. | COMMENT |
| LOW | readthedocs/proxito/views/serve.py | 307 | # Verify if the project is marked as spam and return a 401 in that case | COMMENT |
| LOW | readthedocs/proxito/views/serve.py | 638 | # Verify if the project is marked as spam and return a custom robots.txt | COMMENT |
| LOW | readthedocs/rtd_tests/tests/test_project_views.py | 768 | # Set version to private | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | readthedocs/oauth/tasks.py | 364 | "single_file_name": null, | STRING |
| HIGH | readthedocs/oauth/tasks.py | 367 | "suspended_by": null, | STRING |
| HIGH | readthedocs/oauth/tasks.py | 384 | "requester": null, | STRING |
| HIGH | readthedocs/oauth/tasks.py | 462 | "single_file_name": null, | STRING |
| HIGH | readthedocs/oauth/tasks.py | 465 | "suspended_by": null, | STRING |
| HIGH | readthedocs/oauth/tasks.py | 478 | "requester": null, | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | readthedocs/vcs_support/base.py | 46 | # ========================================================================= | COMMENT |
| MEDIUM⚡ | readthedocs/vcs_support/base.py | 48 | # ========================================================================= | COMMENT |
| MEDIUM | readthedocs/vcs_support/base.py | 101 | # ========================================================================= | COMMENT |
| MEDIUM | readthedocs/vcs_support/base.py | 103 | # ========================================================================= | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | readthedocs/search/parsers.py | 256 | # In this example, we cannot use the current <dt>'s ID because they contain invalid | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/oauth/models.py | 358 | # (or v3) to just return the linked Project (slug, url) if the ``RemoteRepository`` | COMMENT |
| LOW | readthedocs/projects/version_handling.py | 150 | # we just return the first branch found. | COMMENT |
| LOW | readthedocs/search/api/v3/executor.py | 62 | # we also just return. | COMMENT |
| LOW | readthedocs/api/v2/views/integrations.py | 139 | # In that case, we just return it as is. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/core/resolver.py | 335 | we need to check if the main translation is a subproject. | STRING |
| LOW | readthedocs/api/v2/views/integrations.py | 574 | # webhooks. If we receive a PUSH event we need to check if the webhook doesn't | COMMENT |
| LOW | readthedocs/proxito/views/hosting.py | 619 | # if only we need to check if there are results or not. | COMMENT |
| LOW | readthedocs/proxito/views/serve.py | 167 | # For .com we need to check if the project supports custom domains. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …th/management/commands/reconnect_remoterepositories.py | 54 | # TODO: consider using same login than RemoteRepository.matches method | COMMENT |
| LOW | readthedocs/api/v2/serializers.py | 399 | # TODO: handle exceptions | COMMENT |
| LOW | readthedocs/proxito/views/hosting.py | 434 | # TODO: consider adding this field into the ProjectSerializer itself. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/oauth/services/__init__.py | 10 | __all__ = [ | CODE |
| LOW | readthedocs/builds/querysets.py | 29 | __all__ = ["VersionQuerySet", "BuildQuerySet", "RelatedBuildQuerySet"] | CODE |
| LOW | readthedocs/builds/managers.py | 24 | __all__ = ["VersionManager"] | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/projects/views/private.py | 158 | # NOTE: This method is called twice, on .org it doesn't matter, | COMMENT |
| LOW | readthedocs/search/tasks.py | 37 | # WARNING: This must use the exact same queryset as from where we get the ID's | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | readthedocs/settings/base.py | 1012 | # Everytime we need to do a re-index, make sure to check the size of the index and adjust the | STRING |
| LOW | readthedocs/projects/models.py | 747 | # make sure to use the clone URL from the repository. | COMMENT |