Skip to content

feat(filtering): Filter findings by host operating system reported by scanners - #16339

Open
cvas22 wants to merge 5 commits into
DefectDojo:devfrom
cvas22:feature/host-os-filter
Open

cvas22 wants to merge 5 commits into
DefectDojo:devfrom
cvas22:feature/host-os-filter

Conversation

@cvas22

@cvas22 cvas22 commented Oct 14, 2026

Copy link
Copy Markdown

Closes #16281

Description

Infrastructure scanners often report each host's operating system, but DefectDojo dropped it (or buried it in the description), so there was no way to narrow an imported scan to e.g. "findings on Windows hosts". This PR keeps the host OS from the report and adds a filter for it.

Where the OS is stored: on each finding↔host reference, in the existing LocationFindingReference.relationship_data JSON field ({"os": "..."}). No migration is needed.

This placement makes the value per scan, which is what filtering an imported scan needs:

  • A host-level value (on Location / location_meta) would be shared by every product, and the last import would win. Importing an Nmap scan ("Linux 3.X") and then a Qualys scan ("Ubuntu 22.04") would silently change what the Nmap test's filter matches.
  • A per-reference value always matches the report the finding came from. It also answers "which hosts of this finding match?" directly, from the same rows.

If maintainers would rather have a dedicated column than a key in relationship_data, the plumbing below stays the same.

Changes

  • Parser → importer:
    • LocationData gets an optional association (LocationAssociationData), plus a LocationAssociationData.host_os(...) helper.
    • AbstractLocation.from_location_data applies it, so any parser can attach per-host data to the locations it emits.
  • LocationManager._persist_locations:
    • New finding refs take their association data from the finding's own location object. Before, it came from the deduplicated saved location, which carried only one duplicate's data.
    • On reimport, association data on existing refs is merged and bulk-updated. Keys the parser supplies overwrite stored ones; keys it omits are kept, so a report without an OS doesn't erase a stored one. If nothing changed, nothing is written.
  • Parsers:
    • Qualys and Qualys Infrascan WebGUI: the OS they already read.
    • Nmap: the highest-accuracy osmatch.
    • Nexpose: now actually parses node fingerprints/os, picking the most certain fingerprint. It previously always set host["os"] = "".
  • Filters:
    • "Host OS" filter (location_os, case-insensitive contains) on the UI finding filters. It matches together with the host and location-status filters on the same host, and uses Exists() so findings aren't duplicated.
    • location_os on /api/v2/findings/.
    • host_os_* filters on the location finding reference API.
  • UI:
    • The hosts popover in the test view and findings list shows each host's OS, and bolds hosts that match the active Host OS filter.
    • The OS text is escaped twice because the popover renders its content as HTML (data-html="true").
  • Legacy endpoints (V3_FEATURE_LOCATIONS off) are unchanged; there the OS isn't stored and the filter isn't offered.

Test results

  • New unittests/test_location_host_os.py (12 tests):
    • the OS is stored per finding (including two findings sharing a host);
    • reimport updates a changed OS, keeps the stored OS when the report has none, merges with other stored data, and issues no UPDATE when nothing changed;
    • the filter is case-insensitive, returns each finding once, and matches host/status on the same host;
    • the API filter and the highlight helper.
  • Parser tests for Nmap (new sample nmap_os_detection.xml, since no existing sample had OS detection), Nexpose (including fingerprint selection), Qualys and Qualys WebGUI.
  • Every new test fails without the change. With only location_manager.py reverted, the per-finding, reimport-update and merge tests fail.
  • Ran in Docker (unit-test image built from this branch):
    • the new tests, plus the existing test_bulk_locations, location filter/authz/prefetch, API finding filter, filter tags and the four parser modules: 176 tests OK (1 legacy-endpoint test skipped);
    • makemigrations --check: no changes;
    • spectacular --fail-on-warn: OK.
  • The full suite was not run to completion locally.

Documentation

Added a "Host Operating System" section to docs/content/asset_modelling/engagements_tests/OS__findings.md (English only).

Checklist

  • Make sure to rebase your PR against the very latest dev.
  • Features/Changes should be submitted against the dev.
  • Bugfixes should be submitted against the bugfix branch. (n/a, feature)
  • 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. (no schema change)
  • Add applicable tests to the unit tests.
  • Add the proper label to categorize your PR. (I can't set labels or a milestone from a fork; the next open milestone is 3.4.200.)

Store the host OS a scanner reports on each finding/location reference
(LocationFindingReference.relationship_data["os"]) so a scan's findings can
be filtered by the operating system of the affected hosts.

- LocationData gains an optional association; AbstractLocation.from_location_data
  applies it, so parsers can attach host data to the locations they emit.
- LocationManager builds finding refs from each finding's own association data
  and, on reimport, merges changed association data into existing refs
  (supplied keys overwrite, omitted keys are kept).
- Qualys, Qualys Infrascan WebGUI, Nmap (best osmatch) and Nexpose (most certain
  fingerprint) parsers attach the host OS.
- "Host OS" filter on the UI finding filters and `location_os` on the findings
  API; host_os_* filters on the location finding reference API.
- Hosts popover shows each host's OS and highlights hosts matching the filter.

Refs DefectDojo#16281
@cvas22 cvas22 changed the title Filter findings by host operating system reported by scanners (feat) filtering: Filter findings by host operating system reported by scanners Oct 14, 2026
@dryrunsecurity

dryrunsecurity Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

DryRun Security

This pull request contains multiple low-severity findings where the author 'cvas22' modified several sensitive codepaths, including filters, templates, and models, 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/filters.py (drs_90cd455f)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/filters.py' matches configured sensitive codepath pattern 'dojo/filters.py' and was modified by 'cvas22' (commit 73ea562) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/importers/location_manager.py (drs_a83b51ec)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/importers/location_manager.py' matches configured sensitive codepath pattern 'dojo/importers/*.py' and was modified by 'cvas22' (commit 73ea562) 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_27da6976)
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 'cvas22' (commit 73ea562) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/templates/dojo/view_test.html (drs_3e4f2881)
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 'cvas22' (commit 73ea562) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/templatetags/display_tags.py (drs_a0595bda)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/templatetags/display_tags.py' matches configured sensitive codepath pattern 'dojo/templatetags/*.py' and was modified by 'cvas22' (commit 73ea562) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/templatetags/filter_tags.py (drs_05511ae0)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/templatetags/filter_tags.py' matches configured sensitive codepath pattern 'dojo/templatetags/*.py' and was modified by 'cvas22' (commit 73ea562) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/db_migrations/0299_finding_test_numsev_index.py (drs_ecd69bb0)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/db_migrations/0299_finding_test_numsev_index.py' matches configured sensitive codepath pattern 'dojo/db_migrations/*.py' and was modified by 'cvas22' (commit 6c5b178) who is not in the allowed authors list.
Configured Sensitive Codepath Modified by Non-Allowed Author in dojo/finding/models.py (drs_2efbee0b)
Vulnerability Configured Sensitive Codepath Modified by Non-Allowed Author
Description File 'dojo/finding/models.py' matches configured sensitive codepath pattern 'dojo/finding/*.py' and was modified by 'cvas22' (commit 6c5b178) 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.

@cvas22 cvas22 changed the title (feat) filtering: Filter findings by host operating system reported by scanners feat(filtering): Filter findings by host operating system reported by scanners Oct 14, 2026

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant