Repository navigation
Release: Merge release into master from: release/merge-dev-into-master-3.5.103 - #16876
Merged
defectdojo-release-tracker[bot] merged 62 commits intoNov 13, 2026
Merged
defectdojo-release-tracker[bot] merged 62 commits into
defectdojo-release-tracker[bot] merged 62 commits into
Conversation
…ev-3.5.102 Release: Merge back 3.5.102 into dev from: release/merge-master-into-dev-3.5.102
#16802) * docs(rules-engine): say a rule close mitigates the finding's endpoints Set Status (false_positive, mitigated), Copy Status from Matched Finding and the classic Rules Engine's False Positive / Mitigated fields mitigate the closed Finding's open Endpoints (or Locations), as closing it by hand does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJqD5GHgqGFiHWpR4JYfWm * docs(rules-engine): say a rule reopen opens the endpoints again A rule reopening a Finding sets its Endpoints (or Locations) open again; the close names the rule owner and the run's time. Folds the classic Rules Engine bullet into one sentence and adds the sentence to the ticket sync node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJqD5GHgqGFiHWpR4JYfWm --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…nding records on upgrade (#16808) * docs(risk-acceptance): say acceptances from before 3.3.0 get their finding records on upgrade Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GLL1WfyvvMFAmudbcCyaZK * docs(risk-acceptance): an expiry does not sever an acceptance's membership Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…wn options (#16806) Claude-Session: https://claude.ai/code/session_01HJqD5HCezZb93pC6XgZHcT Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…es (#16790) * fix(product-attributes): refuse a comma in a new attribute option value The findings filters over Asset attribute values (product_lifecycle on /api/v2/findings/) take a comma-separated list, so an option whose value contains a comma could never be matched. Creating a Platform, Lifecycle or Origin option through /api/v2/ or the classic UI form now refuses a value with a comma. Only a create is checked: an update ignores the value, and an existing row keeps its own, so a legacy row stays editable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJqD5F8fqQRckGxJ6sobkn * fix(product-attributes): translate the comma refusal and check it on the model - The message is gettext_lazy, so /api/v2/ and the classic form show it in the user's language. - The create-only check moves from the classic form to the model's clean(), so every ModelForm, Django admin included, refuses a comma in a new value; an existing row keeps its own. The API serializers keep their own check. - The docs say a derived value also collapses repeated spaces. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJqD5HBSaAhHF6FQrzAbmo * fix(findings): match a lifecycle value that contains a comma, in quotes Replaces the comma refusal on Asset attribute option values with a filter that can match them. An option's value may contain a comma, but product_lifecycle on /api/v2/findings/ split its parameter on every comma, so such an option could never be matched. product_lifecycle now reads a value in double quotes as one value, CSV-style ("beta, ga",production); a list without quotes splits exactly as before. The create-time refusal, its model check and their test are reverted, and the attribute options docs say how to quote such a value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJqD5F8fqQRckGxJ6sobkn --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(parsers): add Early Light JSON parser Adds the "Early Light Scan" scan type for `earlylight scan <fs|image|repo|host> --format json` reports from DefectDojo's emerging-vulnerability scanner. - vulnerable findings are imported tagged "earlylight"; unknown findings are imported tagged "earlylight" and "needs-review" with the reason in the description; fixed, inactive and managed findings are skipped - vuln_id_from_tool is "<detector>/<kind>"; vulnerability IDs are the finding's own CVEs only - severity is the finding's own when set, else the kind's severity from the detector catalog, else High (vulnerable) or Medium (unknown) - unique_id_from_tool is a stable hash of detector, kind, target, path and the certificate or image facts; deduplication uses unique_id_from_tool - sample reports are real Early Light output, trimmed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(parsers): prefer the kind severities newer Early Light reports carry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Tag fields are case-insensitive, so tagulous finds each tag it adds with
get_or_create(name__iexact=...), which compiles to UPPER("name"::text) =
UPPER(%s). The unique index on name cannot serve that, so every tag added to
an object read the whole tag table. Tag rows pile up on an instance whose
pipelines create, tag and delete findings, because a tag row is not deleted
when its last finding is. On a 3,000,000-row finding tag table one lookup
took 1.6 s, and a finding PATCH that set 12 tags spent 19 s in SQL.
dojo.0308 adds a text_pattern_ops btree on UPPER(name) to each of the 14 tag
tables, so the lookup is an index scan (0.03 ms) and the istartswith tag
search can use it too. The migration builds CONCURRENTLY outside a
transaction (plainly inside one), drops an INVALID leftover of an
interrupted build first, and ANALYZEs each table. It changes no migration
state: the tag models are generated by tagulous and declare no indexes.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…to build fast (#16823) 0307 built each index on a large event table CONCURRENTLY under the database's default maintenance_work_mem. On an instance with about 2.9M findings that held an upgrade for about two hours, almost all of it three builds on the Finding event table. At the 64 MB default each build's sort spills to disk, and since Postgres gives a build one parallel worker per 32 MB of maintenance_work_mem, each build also ran with one worker. Each concurrent build now runs with maintenance_work_mem = 512MB and max_parallel_maintenance_workers = 4 in its own session, never lowering a session that already has more, and the session's settings are restored after the build. Indexes are built smallest table first, so a run that fails on a large table leaves every small one built. Migration state is unchanged. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…osed while it waited (#16811) Claude-Session: https://claude.ai/code/session_01HJqD5Cv3VzGrZWHeaGqoU4 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…t previews count (#16809) * docs(triage-engine): say which matching passes the import and reimport previews count Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GLL1Wc7eenQgvZJnGkx7Qe * docs(triage-engine): Global Component is previewed when Locations is off Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GLL1Wc7eenQgvZJnGkx7Qe --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…rows need (#16815) * docs(page-layouts): say a narrowed simple table keeps the height its rows need Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJqD5Ez7PB1xE6VT3N39Ci * docs(page-layouts): say the row rises with a narrowed simple table, and other widgets keep their height Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJqD5Ez7PB1xE6VT3N39Ci --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) * docs(login-settings): describe the warning before a session ends Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1AbucwijBnH3k7TSpF * docs(login-settings): say the session expiry warning is the Pro UI's Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1AbucwijBnH3k7TSpF --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…#16814) The Insights filter bar narrows every dashboard to findings from chosen test types or test type categories (SCA, DAST, Container, Secrets ...). Claude-Session: https://claude.ai/code/session_018B4x1AmvtKPP7BqHYS8Bwu Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…the Pro UI (#16812) * docs(notifications): say where to set notifications for one asset in the Pro UI Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GLL1WbzJ8Ut9h66RhUqM1d * docs(notifications): list the Pro events an asset's notification settings offer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GLL1WbzJ8Ut9h66RhUqM1d --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(triage-engine): document the Merge Findings node Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x19GRapP5jCLo2KZaTk * docs(triage-engine): say Merge Findings groups the findings that reach it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x19GRapP5jCLo2KZaTk --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#16759) * docs(custom-fields): document computed custom fields and rule formulas Computed custom fields: what a formula reads (built-in numbers, number custom fields, finding counts and aggregates), computed fields reading each other, when values recompute, and the Triage Engine event a moved value raises. Triage Engine: the Findings Changed asset trigger, the Write To target on the custom field nodes, and formulas over finding counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(custom-fields): scoped recompute, the compute confirmation and the sweep lock Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(custom-fields): empty results, recompute triggers and rule chains Describe what the review changed: a record the formula has no result for is emptied, a label-only edit recomputes nothing, the row offers Insert Number too, and a recompute a rule set off stays in that rule's chain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(custom-fields): a computed field with no result is empty, and a new formula announces no Finding updates Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…close pass (#16798) Reimport loaded every finding of the to-mitigate set as a full instance, with its JIRA relations, before close_old_findings() looked at it. That set is every finding of the test the report no longer carries, closed ones included, and the chunked load appended every chunk to one list. On a test whose findings are nearly all closed, a reimport that closed nothing held all of them in memory at once, about 8 KiB each, and ran the worker out of memory on tests with a few hundred thousand closed findings. Reported via a customer support ticket. _hydrate_findings_for_close_old() now loads only the findings close_old_findings() can close (mitigated unset, or is_mitigated false: the same test it already applied) and keeps the other ids in already_closed_to_mitigate. The one thing close_old_findings() still did with an already-closed finding, pushing its finding group to JIRA, now reads those groups by id. Which findings close, reopen and match is unchanged. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…16800) * fix(locations): new importer references follow the finding's status An import created every new location finding reference as Active, even for a finding the report already marks mitigated or inactive, and never reactivated an Asset reference that was Mitigated when a new Active finding reference joined it. The Locations list then counted closed findings as active on a location whose Asset reference read Mitigated. - New finding references take the status the UI add path already uses (status_from_finding, now a pure function in dojo.location.status). - A new Asset reference is Mitigated when every new finding reference to its location is closed; a location recorded for the product alone stays Active. - An existing Mitigated Asset reference becomes Active again when a new Active finding reference joins it (one UPDATE, only when that happens; the existing-reference query now also reads the status, so no query is added). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(locations): describe how references follow a finding's status An import now gives a new Finding Reference its finding's status, and a finding closed or reopened outside an import brings its references and the Location's Asset Reference along. The Locations overview said every new reference starts Active. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(locations): keep Active refs for inactive imported findings The importer gave every new finding reference its finding's full status, so an inactive or duplicate finding got a Mitigated reference. That changed the import contract test_import_reimport pins (findings imported with active=False keep Active references). A new finding reference is now Mitigated only when the report marks the finding mitigated (is_mitigated, excluding False Positive and Out Of Scope, which the save also marks mitigated, and Risk Accepted). Every other finding keeps the Active reference imports have always created. The Asset reference rule follows: Mitigated only when every new finding reference to its location is Mitigated. Location.status_from_finding is back to its dev form, since the importer no longer uses it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ound task (#16821) * fix(celery): give the outer task its cache back after a nested foreground task A task run in the foreground inside another one (dojo_dispatch_task with force_sync=True) went through DojoAsyncTask.__call__, which installed a fresh task cache and then set the thread's cache to None when it ended. The outer task ran on with no task cache, so every memoized read after that point went back to the database or the shared cache. begin_task_cache() now returns the cache it replaced and end_task_cache() restores it. A top-level task still starts with a fresh cache and leaves None behind; a nested one still gets a cache of its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(celery): say what a nested task does to invalidation; make the nested-task test rerunnable begin_task_cache and end_task_cache now say that an outer task keeps what it memoized for the whole task, and that an invalidation inside a nested foreground task clears only the nested task's cache. The test registered its two tasks on the global Celery app inside the test body. Celery hands back an already registered task for a name, so a second run in one process called the first run's closures. The test now drops both names before registering them and again when it ends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) * fix(jira): let a Jira project suppress SLA notification comments A Jira project's "Send SLA notifications as comment?" could only turn SLA comments on. The daily SLA job comments when the Jira instance's global setting or the project's setting is on, so a project that unchecked it still got an overdue comment on every breached issue each day while the instance setting was on. Add JIRA_Project.suppress_sla_notification_comments (default False, also as a database default). When it is set the SLA job posts no Jira comment for that project; email, in-app and other SLA notifications still go out. Otherwise the rule is unchanged: comment when the instance or the project asks for it. product_jira_sla_notification keeps its type and meaning, and migration 0309 only adds the column, so no row is rewritten and API clients that never send the new field behave as before. Both set at once is rejected by the model's clean() and the API serializer. The classic form shows one select (Inherit from Jira instance / Always send / Never send) mapped onto the two booleans. The instance setting's help text now says how a project overrides it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(jira): describe the three SLA comment choices and the API fields Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(jira): a classic form post with the old SLA comment checkbox still sends The classic Jira project form replaced the "Send SLA notifications as comment?" checkbox with a three-choice select. A post that still sends the old product_jira_sla_notification=on and no choice (a script or a saved form) was saved as Inherit and the "on" was dropped. It now maps to Always send, and counts as a change. A post with neither keeps the stored setting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…eld pickers (#16813) * docs(ui): describe the grouped CSV export, rules engine and widget field pickers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x19EcwUC1yHLZXRZrvr * docs(ui): the rule insert menu, Set Field actions, integrator and connector pickers are grouped too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x19EcwUC1yHLZXRZrvr --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…connectors, ticket templates and the group API token (#16786) * docs(groups): group-owned receivers, notification webhooks, connectors, ticket templates and the group API token Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(groups): a group token acts as the group; flag ends its OAuth access tokens Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(groups): receiver moves keep rules listening, group test messages, token issue rule Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(groups): receiver URL tokens for editors only, group webhook private addresses, Service Users for group tokens Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#16816) * docs(findings): document the SLA Status filter and the due-soon window The SLA filter takes one condition, so Less Than or Equal To 7 also lists every overdue Finding. SLA Status (Breached / Within SLA) combines with it to list only Findings due within the week. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1B6U6wWEo2P2ZYHuB8 * docs(findings): make Status Active step 1 of the due-soon recipe and widen Breached Without Status Active the recipe also lists Mitigated Findings closed up to 7 days before their SLA date, so it is now the first step. Breached covers every Finding that is not Mitigated (Risk Accepted, False Positive and Out of Scope included), not only open ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1B6U6wWEo2P2ZYHuB8 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…6827) Claude-Session: https://claude.ai/code/session_018B4x18tCrYXzb2CdduNaMk Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…16831) The Test page's Finding Groups table now fits its tile: a fixed set of columns (severity, name, findings, SLA, status, tickets, creator) that drops by priority as the tile narrows, and a header tag counting the groups past their SLA. Claude-Session: https://claude.ai/code/session_018B4x19wWovdgzjtXK877AR Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…by product (#16828) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The Pro notes feed moves the raw-source toggle off the note text and into each note's row menu (View Source / View Formatted). Claude-Session: https://claude.ai/code/session_018B4x18J3XfNxMMqYYkqvkF Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(pro): describe the Findings table's tile on the Test page Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1Ad36PqVVT34YSs8W8 * docs(pro): say where the tile tables keep the saved page size Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1Ad36PqVVT34YSs8W8 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…page (#16849) * docs(pro): describe the Request / Response Pairs rows on the Finding page Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTCggquV2UhQbY9gSg1 * docs(pro): name the body size and the 100-pair cap of the Request / Response Pairs tab Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTCggquV2UhQbY9gSg1 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018B4x185nbDKhQpqFxEGgXB Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(prioritization): describe custom field priority factors * docs(prioritization): say which changes recalculate an Organization for a numeric factor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s in the Pro UI (#16844) * docs(questionnaires): link, answer and share engagement questionnaires in the Pro UI Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1AtjA2T1JZEbHRaTBZ * docs(questionnaires): say Link to a Different Engagement also needs edit access to both engagements Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1AtjA2T1JZEbHRaTBZ --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…e a still-reported suppressed finding (#16848) * fix(reimport): keep false-positive history to its host, and never close a still-reported suppressed finding False-positive history matched on the hash alone, so for scanners whose hash leaves the host out, a decision on one host reached every host that reported the same issue, on import and retroactively. It now also requires a shared location for hash_code and unique_id_from_tool_or_hash_code, compared on DEDUPE_ALGO_ENDPOINT_FIELDS as deduplication does, with each finding's locations loaded once per batch. Reimport closed a matched false-positive or out-of-scope finding whose incoming status differed: it was left out of the findings the report still contains, and close_old_findings mitigated it. Every matched special-status finding is now unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTGJPWSyyHzFb8RQv54 * perf(dedupe): compare locations only for pairs that can change false-positive history Locations were loaded and compared for every same-hash candidate, even when nothing was a false positive, which made an import with no false positives several times slower. Only a false-positive candidate, or with retroactive history an active candidate of a finding that is or becomes a false positive, can change the outcome; the others are dropped before any location is loaded. Also fix the docs' match table and the Open Source matching note. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTGJPWSyyHzFb8RQv54 * test(migrations): release the 0305 in-flight build from inside the wait, not on a timer test_build_still_running_is_waited_for_and_kept freed the concurrent index build on a one-second timer started before the operation ran. On a slow runner the build finished before the operation's first check, so nothing was waited for and no warning was logged. The snapshot is now released from the wait loop's first check, after the builder's transaction has ended, so the test no longer depends on how fast the runner is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTGJPWSyyHzFb8RQv54 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…16851) The Pro View Finding gear menu now offers Add Request/Response Pair, since the Request/Response Pairs tab stays hidden until a finding has one. Claude-Session: https://claude.ai/code/session_018B4x1APEsneSo3iBNsDE5y Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(pro): document whole-asset standing risk acceptances Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1BWN2LmqRTViYFPQL7 * docs(pro): say whole-asset standing acceptances cover new findings only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTEaMtiXEXEwDEfTUW2 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gets (#16854) * docs(pro): manage Organization members and groups from the page's widgets The Organization page's Members and Groups widgets add a user or group, change a role and remove access from their row menu, with the same permission checks as the Permissions window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTE55mFtCHpbAcBTAyb * docs(pro): bold the Role field like the paragraph's other labels Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTE55mFtCHpbAcBTAyb --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143hYTGRzuiVMjK1A4euYEJ Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…#16843) * fix(importers): run imports and reimports into one test one at a time A client that times out on a long synchronous reimport and retries it started a second reimport into the same test while the first was still running. The two matched and wrote the same finding rows and deadlocked (SQLSTATE 40P01) or had statements cancelled by statement_timeout (57014). An import now takes an exclusive PostgreSQL advisory lock on its test before it matches or writes the first finding, and holds it until the import ends. A second import into that test waits for the first to finish and then runs as before. Only a wait longer than DD_SERIALIZE_TEST_IMPORTS_WAIT_SECONDS (default 600) fails, with 409 Conflict and a message naming the test; 0 fails at once. DD_SERIALIZE_TEST_IMPORTS=False turns it off behind a pooler in transaction mode, and a lock whose every holder has been idle for DD_DUPE_DELETE_ABANDONED_IMPORT_LOCK_MINUTES holds nothing back. The lock uses its own key (0x44440002), separate from the shared per-test lock the excess-duplicate delete reads (0x44440001). That lock is shared by design: an import's deduplication batches take it while the import waits for them in async_wait mode, so the import cannot hold the same key exclusively. The delete is unchanged. The wait polls pg_try_advisory_lock rather than blocking in PostgreSQL, so a statement timeout cannot cancel it and the transaction stays usable. Each import issues two more queries (take and release), which the importer performance counts now include. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(importers): let a caller try for a test's import turn without waiting A background import that runs in a Celery worker must not hold the worker while another import into its test finishes: a burst of them would take the pool, including the deduplication tasks the running import waits on. lock_test_under_import and wait_for_test_import_turn now take wait_seconds, which overrides DD_SERIALIZE_TEST_IMPORTS_WAIT_SECONDS for that call; 0 only tries, and raises TestImportInProgress at once when the test is taken, so the caller can queue the import again instead. The turn is asked for once per import_lock_scope: a caller that took it up front is not made to wait again by process_scan, and neither is one that was let through because the lock is off or was left behind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(importers): never leave a test's import turn taken but unrecorded Review follow-ups for the one-import-at-a-time lock. - A time limit (SoftTimeLimitExceeded) or any other exception landing after pg_try_advisory_lock had taken the test's turn, but before the importer had recorded it for release, left a lock nothing released: on a persistent worker connection it held the test until the connection closed. wait_for_test_import_turn now records the turn through on_taken in the same guarded step, and gives the lock back if anything interrupts the take before it is recorded. lock_test_under_import records through it. - The tag-inheritance perf baselines pin exact query counts for a ZAP import and two reimports. Each now takes and releases its test's turn, two queries per path, in both Locations modes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: DefectDojo release bot <dojo-release-bot@users.noreply.github.com>
…its links go (#16863) * docs(psirt): describe the redesigned PSIRT Exposure widget and its links The share bar and legend, definitions on hover and focus, where each count, advisory and row-menu item leads, and that the four PSIRT widgets are offered only with the PSIRT Advisory Engine license and PSIRT read access. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x19xVrWYZ93rkDVHqJq * docs(psirt): wrap the widgets paragraph and say when Affected Components is offered Replaces the em dash left in "Adding the widgets individually", rewraps that paragraph at the file's width, and states that the row menu offers Affected Components only where the row names components, listing the version-verified ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x19xVrWYZ93rkDVHqJq --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…idgets (#16865) * docs(dashboards): describe chart order, Sankey and Sunburst colors, the Treemap tint and the KPI / Trend change color Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1CBpazy1TGCrg2LNX4 * docs(dashboards): say the Top-N Leaderboard ranks by count, and a Sunburst child slice is a muted shade Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1CBpazy1TGCrg2LNX4 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…oo (#16866) Claude-Session: https://claude.ai/code/session_018B4x17p8WJnbcBdmZJwrtR Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…16864) Claude-Session: https://claude.ai/code/session_018B4x1AH34fn2PB922v4dys Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s_for_all_findings (#16869) * perf(reimport): batch the finding group JIRA lookups in process_groups_for_all_findings With JIRA keep-in-sync on, process_groups_for_all_findings read each group of the reimport and its JIRA issue one query at a time, then read the JIRA issue of every reactivated or unchanged group one query at a time. A reimport touching 200 groups ran 784 statements instead of 241. The first finding of every group name is now loaded once, with its JIRA issue, its group and the group's JIRA issue. The reactivated/unchanged groups are read with their JIRA issue. Their ids now come from two id-list reads per chunk (open findings, then memberships) instead of a DISTINCT subquery under the group read. With planner statistics that saw the group tables as empty, that subquery ran once per group and probed dojo_finding with the whole id list for every membership: 94 s for 200 groups on a 10M-finding database. Which objects are pushed, and in which order, is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(reimport): pin the group_by JIRA keep-in-sync reimport at request level TestDojoReimportGroupJiraPerformance reimports through DefaultReImporter.process_scan with group_by and a keep-in-sync JIRA instance whose groups have issues, into 2 and into 10 groups with the same findings, and asserts the statement count does not grow with the groups (dev: 122 statements with 2 groups, 146 with 10) and that every group is pushed once per pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(reimport): clear the recorded pushes with list.clear() Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* docs(pro): dashboard tile title bar and Section Break behavior The Dashboards page now draws no refresh button or "updated" time on the widgets that read nothing that changes (Markdown, Section Break, Quick Actions, Favorites), lays a small tile's refresh button and menu over the end of its title until the tile is pointed at or tabbed to, and shows a Section Break's header once. A newly added list widget is sized to show every row it is set to show. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTGfYzneCXvjR6Ni7W1 * docs(pro): say the updated stamp shows on a wide enough tile Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x18QM3cTf69C2wfdf6o --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…nsaction commits (#16822) * fix(notifications): send "added" notifications after the creating transaction commits product_post_save, product_type_post_save and engagement_post_save dispatched async_create_notification straight from post_save. Inside a transaction a worker could run the task before the COMMIT, find no row by id and return without notifying anyone, while the task still reported success. dojo_dispatch_task_on_commit builds the signature at save time (acting user, pghistory context, foreground/background choice) and sends it from transaction.on_commit. In autocommit it dispatches at once, as before; a rolled-back create sends nothing. The three receivers use it. The new tests commit for real and check, from a second connection, that the row is visible at the moment the task is handed to the broker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(notifications): log a failed on-commit dispatch instead of raising dojo_dispatch_task_on_commit registered a plain on_commit hook. A foreground task that raised (a user with block_execution and a failing mail or webhook send) or a broker error then surfaced after the COMMIT: the row was saved but the caller got an error, and every on_commit hook registered after it in the same transaction was skipped. Register the hook with robust=True: Django logs the failure and runs the remaining hooks. The new tests force the foreground task to raise, inside a transaction and in autocommit, and check the row is committed, the caller sees no error, the failure is logged and a later hook still runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… check and the import (#16873) * fix(import): resolve the import target the same way in the permission check and the import The scan import permission checks read the raw request, while the import itself runs on the serializer's validated data. Two differences let them pick different targets: the serializer trims whitespace from the name fields and the raw read did not, and the import permission check read a response-only engagement field that the serializer drops. Trim the names when reading the raw request, and ignore that field in the check, so the check authorizes the same product and engagement the import writes to. * fix(import): ignore response-only ids in the reimport and meta import checks ReImportScanSerializer drops test_id and EndpointMetaImporterSerializer drops product_id, because both are response-only fields. The permission checks still read them from the raw request. Ignore them in the checks too, so each check resolves its target the same way as its serializer. Adds reimport tests, including one for a name with surrounding spaces, and a meta import test.
…ar Findings page (#16853) * docs(dedupe): describe the Duplicates tab's cluster view on the Similar Findings page The View Finding page's duplicate card now holds a Duplicates tab and a Linked Findings tab. The Duplicates tab shows the duplicate cluster as a tree, the similar findings that are not in it with the cluster each one already belongs to, a Why Is This a Duplicate toggle, and Open in Findings for search, filters, export and bulk actions. The page and its two screenshots describe that view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018B4x1BUZdWVtPdaWMZaGrK * docs(dedupe): match the similar findings rule and the first-100 note to the Duplicates tab Vulnerability IDs match when a Finding carries at least one of them, not all. Each part of the Duplicates tab shows up to 100 Findings and says how many it holds past that; Open in Findings covers the cluster only. An original whose duplicates cannot be viewed reads Original of another cluster. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143hYTEqcB7uGZJ5U42zWwJ --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…16857) Claude-Session: https://claude.ai/code/session_018B4x19LPCrWyqYz8SKpRyt Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
github-actions
Bot
requested review from
Maffooch and
blakeaowens
as code owners
November 13, 2026 21:13
defectdojo-release-tracker
Bot
deleted the
release/merge-dev-into-master-3.5.103
branch
November 13, 2026 21:13
|
This pull request modifies three files within configured sensitive codepaths, including importers, authorization logic, and templates. All changes were made by 'svader0', who is not on the allowed authors list for these specific paths.
Configured Sensitive Codepath Modified by Non-Allowed Author in
|
| Vulnerability | Configured Sensitive Codepath Modified by Non-Allowed Author |
|---|---|
| Description | File 'dojo/importers/auto_create_context.py' matches configured sensitive codepath pattern 'dojo/importers/*.py' and was modified by 'svader0' (commit 4844a0b) who is not in the allowed authors list. |
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/authorization/api_permissions.py (drs_4f7fb3c5)
| 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 'svader0' (commit 4844a0b) who is not in the allowed authors list. |
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/templates/dojo/calendar.html (drs_95b59323)
| Vulnerability | Configured Sensitive Codepath Modified by Non-Allowed Author |
|---|---|
| Description | File 'dojo/templates/dojo/calendar.html' matches configured sensitive codepath pattern 'dojo/templates/**/*.html' and was modified by 'svader0' (commit 86453d0) 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release triggered by
defectdojo-release-tracker[bot]