Skip to content

fix(api): return a clear 400 when a scan import exceeds upload limits - #15993

Merged
Maffooch merged 1 commit into
bugfixfrom
cmm/friendly-edison-q85g6t
Sep 17, 2026
Merged

Maffooch merged 1 commit into
bugfixfrom
cmm/friendly-edison-q85g6t

Conversation

@Maffooch

Copy link
Copy Markdown
Contributor

Description

The import-scan, reimport-scan, and endpoint/generic meta-import API permission checks parse request.data inside has_permission to resolve the target product / engagement / test before the serializer runs.

When a scan import submits more form fields than DATA_UPLOAD_MAX_NUMBER_FIELDS (or a body larger than DATA_UPLOAD_MAX_MEMORY_SIZE), Django's multipart parser raises a SuspiciousOperation (TooManyFieldsSent / RequestDataTooBig) while request.data is evaluated. The surrounding try only caught (ValueError, TypeError), so the exception escaped the permission check as an opaque error and generated error-reporting/on-call noise, giving the caller no actionable feedback.

This was observed in production on a POST /api/v2/reimport-scan/ request that exceeded the field limit.

Changes

  1. Clear client error — the three import/reimport permission classes (UserHasImportPermission, UserHasMetaImportPermission, UserHasReimportPermission) now catch TooManyFieldsSent / RequestDataTooBig and raise a DRF ValidationError (HTTP 400) with an actionable message, instead of letting the SuspiciousOperation escape.
  2. Tunable limitDATA_UPLOAD_MAX_NUMBER_FIELDS is now read from DD_DATA_UPLOAD_MAX_NUMBER_FIELDS (default 10240), mirroring the existing DD_DATA_UPLOAD_MAX_MEMORY_SIZE, so operators can raise the limit for instances that legitimately submit very large imports.

Pro impact

The Pro plugin does not override these permission classes or this setting, so it inherits the behavior unchanged; no companion Pro change is required.

Test results

Adds unittests/test_import_permission_upload_limits.py:

  • test_too_many_fields_raises_validation_error — with the field limit lowered via override_settings, an oversized multipart request to each of the three permission classes raises a DRF ValidationError (this fails before the fix, where TooManyFieldsSent escapes the permission check).
  • test_request_within_limit_parses_without_size_error — a request under the limit parses normally.
  • test_default_value — the setting default remains 10240.

Ruff clean on all changed files. The core parser behavior (field-count → TooManyFieldsSent → converted to ValidationError) was additionally verified against Django 5.2 / DRF 3.18 in isolation.

Documentation

No user-facing documentation change: this adds an admin/ops environment variable following the existing DD_DATA_UPLOAD_MAX_MEMORY_SIZE pattern and improves an error response.

Checklist

  • Bugfix submitted against the bugfix branch.
  • Ruff compliant.
  • Python 3.13 compliant.
  • No model changes / no DB migration.
  • Unit tests added.
  • Labels: bugfix, settings_changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EWbcF7wUybs9Z2bFCpEi49


Generated by Claude Code

The import, reimport, and metadata-import permission checks parse
request.data to resolve the target product/engagement/test before the
serializer runs. When a scan import submits more form fields than
DATA_UPLOAD_MAX_NUMBER_FIELDS (or a body larger than
DATA_UPLOAD_MAX_MEMORY_SIZE), Django's multipart parser raises a
SuspiciousOperation (TooManyFieldsSent / RequestDataTooBig) while
request.data is evaluated. That exception escaped the permission check
as an opaque error and generated error-reporting noise.

Catch those exceptions in the three import/reimport permission classes
and raise a DRF ValidationError with an actionable message instead.

Also make DATA_UPLOAD_MAX_NUMBER_FIELDS configurable via
DD_DATA_UPLOAD_MAX_NUMBER_FIELDS (default 10240), mirroring
DD_DATA_UPLOAD_MAX_MEMORY_SIZE, so operators can raise the limit for
instances that legitimately submit very large imports.

Adds unit tests covering all three permission classes and the setting
default.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWbcF7wUybs9Z2bFCpEi49
@Maffooch Maffooch added this to the 3.3.200 milestone Sep 17, 2026 — with Claude
@Maffooch Maffooch added bugfix settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR labels Sep 17, 2026 — with Claude
@dryrunsecurity

Copy link
Copy Markdown

DryRun Security

This pull request modifies a sensitive authorization file (dojo/authorization/api_permissions.py) using an author ('claude') who is not on the allowed list. Although the finding is marked as low severity and non-blocking, it indicates a policy violation regarding code ownership for critical security paths.

Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/authorization/api_permissions.py (drs_d760789d)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/authorization/api_permissions.py' matches configured sensitive codepath pattern 'dojo/authorization/*.py' and was modified by 'claude' (commit 255ccc8) 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.

@Maffooch
Maffooch added this pull request to the merge queue Sep 17, 2026
Merged via the queue into bugfix with commit 905460f Sep 17, 2026
48 checks passed
@Maffooch
Maffooch deleted the cmm/friendly-edison-q85g6t branch September 17, 2026 05:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix 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.

4 participants