Skip to content

feat(system_settings): add a read-only mode - #16386

Open
svader0 wants to merge 13 commits into
DefectDojo:devfrom
svader0:feat/read-only-mode
Open

svader0 wants to merge 13 commits into
DefectDojo:devfrom
svader0:feat/read-only-mode

Conversation

@svader0

@svader0 svader0 commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Description

This adds a "Read-only mode" checkbox to System Settings. When a superuser turns it on, DefectDojo rejects every change from the UI and the API until a superuser turns it off again. Use it to freeze an instance before a migration or a database copy, so the data stops changing while you copy it.

While it is on:

  • Every POST, PUT, PATCH and DELETE is rejected, superusers included. Reads keep working.
  • API, htmx and AJAX calls get 423 Locked with a JSON message. Normal form submits go back to the page they came from with an error message.
  • Sign-in, sign-out, password reset, change password, the API token endpoint and System Settings stay open, so a superuser can always turn it off again. The list is the new READ_ONLY_MODE_EXEMPT_URLS setting.
  • Celery beat jobs are skipped. Tasks that were already queued still run.
  • Every page shows a warning banner.

Turn it on in Configuration > System Settings, or with PATCH /api/v2/system_settings/1/ and {"read_only_mode": true}. No restart is needed. The check reads the settings cache each request already fills, so it adds no database queries.

Known limits: GET views that write as a side effect, management commands and the Django shell are not blocked. Webhooks get a redirect instead of a 423. htmx actions show only the banner. A few POSTs that only read (report builder, generate_report, Celery purge, banner dismiss) are blocked too.

Test results

  • New unittests/test_read_only_mode.py (18 tests): blocked writes, safe methods, every exempt URL, lock and unlock through the API, the redirect target with an open-redirect fallback, a lock change seen by the next request without a signal, zero extra queries, the beat-task skip, and the banner.
  • The perf, caching, middleware, system settings and Celery suites pass with unchanged query counts. Full suite: 8222 tests with 2 order-dependent failures in the ZAP query baselines. They pass on their own and do not touch this change.
  • A second reviewer ran 39 bypass attempts against a live stack (odd paths, method-override headers, bad Host and Referer, SQL toggles, parallel requests across 4 uwsgi processes). None got through.
  • makemigrations --check, spectacular --fail-on-warn and ruff are clean. Checked by hand in the browser: lock on, an edit is rejected and not saved, sign-out and sign-in work, lock off, the edit saves.

Documentation

The cutover section of migrating_from_open_source.md now says to turn on read-only mode and wait for running Celery tasks before the final dump. The restore step turns the mode off again in the restored database, because the dump keeps it on.

Checklist

  • Make sure to rebase your PR against the very latest dev.
  • Submit all PRs, features and bug fixes alike, against the dev branch.
  • Give a meaningful name to your PR, as it may end up being used in the release notes.
  • Your code is Ruff compliant (see ruff.toml).
  • Your code is python 3.13 compliant.
  • If this is a new feature and not a bug fix, you've included the proper documentation in the docs at https://github.com/DefectDojo/django-DefectDojo/tree/dev/docs as part of this PR.
  • Model changes must include the necessary migrations in the dojo/db_migrations folder.
  • Add applicable tests to the unit tests.
  • Add the proper label to categorize your PR.

@svader0 svader0 added this to the 3.4.200 milestone Oct 16, 2026
@github-actions github-actions Bot added New Migration Adding a new migration file. Take care when merging. settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR docs unittests labels Oct 16, 2026
@dryrunsecurity

dryrunsecurity Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

DryRun Security

This pull request contains multiple low-severity findings where user 'svader0' modified sensitive codepaths, including database migrations, middleware, and templates, without being on the allowed authors list. These issues are non-blocking and do not prevent the merge.

Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/db_migrations/0301_system_settings_read_only_mode.py (drs_284c0c1a)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/db_migrations/0301_system_settings_read_only_mode.py' matches configured sensitive codepath pattern 'dojo/db_migrations/*.py' and was modified by 'svader0' (commit 1e2caf2) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/middleware.py (drs_31d3a7bd)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/middleware.py' matches configured sensitive codepath pattern 'dojo/middleware.py' and was modified by 'svader0' (commit 8102418) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/celery.py (drs_b952195b)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/celery.py' matches configured sensitive codepath pattern 'dojo/celery.py' and was modified by 'svader0' (commit 7653f3f) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/context_processors.py (drs_e30d21fe)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/context_processors.py' matches configured sensitive codepath pattern 'dojo/context_processors.py' and was modified by 'svader0' (commit 990c052) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/api_v2/exception_handler.py (drs_17be5e0d)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/api_v2/exception_handler.py' matches configured sensitive codepath pattern 'dojo/api_v2/*.py' and was modified by 'svader0' (commit 20ca5ba) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/importers/base_importer.py (drs_cf7a3c5b)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/importers/base_importer.py' matches configured sensitive codepath pattern 'dojo/importers/*.py' and was modified by 'svader0' (commit 20ca5ba) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/importers/default_reimporter.py (drs_3ad2b3a1)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/importers/default_reimporter.py' matches configured sensitive codepath pattern 'dojo/importers/*.py' and was modified by 'svader0' (commit 20ca5ba) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/importers/import_lock.py (drs_f5e01bf7)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/importers/import_lock.py' matches configured sensitive codepath pattern 'dojo/importers/*.py' and was modified by 'svader0' (commit 20ca5ba) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/tasks.py (drs_14ca810d)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/tasks.py' matches configured sensitive codepath pattern 'dojo/tasks.py' and was modified by 'svader0' (commit 20ca5ba) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/templates/dojo/filter_js_snippet.html (drs_9b0c9603)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/templates/dojo/filter_js_snippet.html' matches configured sensitive codepath pattern 'dojo/templates/**/*.html' and was modified by 'svader0' (commit 20ca5ba) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/templates/dojo/findings_list_snippet.html (drs_e9b78bb4)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/templates/dojo/findings_list_snippet.html' matches configured sensitive codepath pattern 'dojo/templates/**/*.html' and was modified by 'svader0' (commit 20ca5ba) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/templates/dojo/view_test.html (drs_2fdcb2a1)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/templates/dojo/view_test.html' matches configured sensitive codepath pattern 'dojo/templates/**/*.html' and was modified by 'svader0' (commit 20ca5ba) who is not in the allowed authors list.

Comment to provide feedback on these findings.

Report false positive: @dryrunsecurity fp [FINDING ID] [FEEDBACK]
Report low-impact: @dryrunsecurity nit [FINDING ID] [FEEDBACK]

Example: @dryrunsecurity fp drs_90eda195 This code is not user-facing

All finding details can be found in the DryRun Security Dashboard.

@svader0
svader0 force-pushed the feat/read-only-mode branch from ae7aa72 to 5911c02 Compare October 16, 2026 23:07

This branch has not been deployed

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

Labels

docs enhancement New Migration Adding a new migration file. Take care when merging. settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR unittests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant