From 70b6adb6020cfd76eeff65d2972e5e58788fdbef Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Tue, 5 May 2026 21:33:03 +0200 Subject: [PATCH 01/12] test: pin query-count baselines for tag inheritance hot paths Adds unittests/test_tag_inheritance_perf.py with assertNumQueries baselines on the six hottest tag inheritance paths (Product tag add/remove propagating to N findings, child create under inheritance, sticky enforcement on child tag edits). Numbers are pinned against current `dev` behavior so subsequent optimization work shows up as concrete query-count reductions instead of relying on manual benchmarking. The class is intentionally temporary: pins move down as the redesign work lands and the file can be deleted once the targets are met. --- unittests/test_tag_inheritance_perf.py | 253 +++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 unittests/test_tag_inheritance_perf.py diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py new file mode 100644 index 00000000000..8fdc41cc288 --- /dev/null +++ b/unittests/test_tag_inheritance_perf.py @@ -0,0 +1,253 @@ +""" +Query-count baselines for tag inheritance hot paths. + +These tests pin the *current* number of SQL queries DefectDojo issues for each +hot path under tag inheritance. They are tripwires: future redesign work +(see /home/valentijn/.claude/plans/tag-inheritance-redesign.md) will reduce +these numbers, and any regression that pushes them back up will fail loudly. + +Each test: + - sets up its fixture *outside* the query-counting block + - exercises one operation under ``assertNumQueries`` with the pinned baseline + - asserts a positive correctness check so query tightening cannot smuggle in + a behavior bug. +""" +from __future__ import annotations + +import logging + +from django.contrib.auth.models import User +from django.test import override_settings +from django.utils import timezone + +from dojo.models import Engagement, Finding, Product, Product_Type, Test, Test_Type +from dojo.product.helpers import propagate_tags_on_product_sync +from unittests.dojo_test_case import DojoTestCase + +logger = logging.getLogger(__name__) + + +def _make_product_with_findings(name: str, *, n_findings: int, tags: list[str] | None = None) -> Product: + """ + Create a Product → Engagement → Test → N Findings tree with inheritance enabled. + + Returns the Product. Internal-only: signal-driven inheritance fires during + creation, but those queries are not counted (we measure operations against + the already-built fixture). + """ + if tags is None: + tags = [] + now = timezone.now() + user, _ = User.objects.get_or_create(username="tag_perf_user", defaults={"is_active": True}) + pt, _ = Product_Type.objects.get_or_create(name="Tag Perf Type") + product = Product.objects.create( + name=name, + description="perf", + prod_type=pt, + enable_product_tag_inheritance=True, + ) + if tags: + product.tags.add(*tags) + eng = Engagement.objects.create(product=product, target_start=now, target_end=now) + tt, _ = Test_Type.objects.get_or_create(name="Tag Perf Test") + test = Test.objects.create(engagement=eng, test_type=tt, target_start=now, target_end=now) + for i in range(n_findings): + Finding.objects.create( + test=test, + title=f"Tag Perf Finding {i}", + severity="Medium", + reporter=user, + ) + return product + + +@override_settings( + CELERY_TASK_ALWAYS_EAGER=True, + CELERY_TASK_EAGER_PROPAGATES=True, +) +class TagInheritancePerfBaselines(DojoTestCase): + + """ + Pinned query-count baselines for tag inheritance hot paths. + + Celery handling: ``CELERY_TASK_ALWAYS_EAGER=True`` runs all dispatched + tasks synchronously in the test thread/connection so their queries are + captured by ``assertNumQueries``. ``CELERY_TASK_EAGER_PROPAGATES`` makes + eager-mode failures surface as exceptions rather than silently swallowing. + Product tag tests still call ``propagate_tags_on_product_sync(product)`` + explicitly because the m2m_changed signal dispatches the Celery task + with ``countdown=5`` — eager mode runs immediately but ``dojo_dispatch_task`` + paths can still skip execution depending on ``we_want_async``. Calling the + sync entry point directly makes the propagation deterministic. + + + TEMPORARY: this test class exists to measure progress as the tag + inheritance redesign lands across multiple PRs. The exact pinned numbers + are not important on their own — what matters is that they MOVE in the + expected direction (downward) as PR #1 (Phase A) and PR #2 (Phase B) + land. Once the redesign is complete and the numbers have stabilized at + target levels, this whole file can be deleted or the assertions + rewritten as loose upper bounds. + + Numbers are *current behavior*. Follow-up PRs reduce them. When a + redesign lowers a number, lower the pin in the same PR; when something + accidentally raises it, fix the regression rather than raising the pin. + """ + + @classmethod + def setUpTestData(cls): + # Enable system-wide inheritance for every test in this class. + # Per-product flag is also set in _make_product_with_findings as a + # belt-and-braces measure (tests should not be flag-coupled). + from dojo.models import System_Settings # noqa: PLC0415 + ss = System_Settings.objects.get() + ss.enable_product_tag_inheritance = True + ss.save() + + # ------------------------------------------------------------------ + # Product tag add / remove → propagate to children + # ------------------------------------------------------------------ + + def test_baseline_product_tag_add_propagates_to_100_findings(self): + """ + `product.tags.add("x")` then sync → propagate to 100 findings. + + Hot path: Product tag toggle in the UI on a product with many + findings. Today's flow runs `obj.save()` per child. Phase A bulk SQL + will collapse this dramatically. + """ + product = _make_product_with_findings("perf-add", n_findings=100, tags=["initial"]) + + with self.assertNumQueries(self.EXPECTED_PRODUCT_TAG_ADD_100): + product.tags.add("perf-added") + propagate_tags_on_product_sync(product) + + # Correctness: a finding under the product now carries the new tag. + finding = Finding.objects.filter(test__engagement__product=product).first() + self.assertIn("perf-added", [t.name for t in finding.tags.all()]) + + def test_baseline_product_tag_remove_propagates_to_100_findings(self): + """`product.tags.remove("x")` then sync → remove from 100 findings.""" + product = _make_product_with_findings("perf-remove", n_findings=100, tags=["to-remove", "stays"]) + + with self.assertNumQueries(self.EXPECTED_PRODUCT_TAG_REMOVE_100): + product.tags.remove("to-remove") + propagate_tags_on_product_sync(product) + + finding = Finding.objects.filter(test__engagement__product=product).first() + finding_tag_names = {t.name for t in finding.tags.all()} + self.assertNotIn("to-remove", finding_tag_names) + self.assertIn("stays", finding_tag_names) + + # ------------------------------------------------------------------ + # Child creation under inheritance-on product + # ------------------------------------------------------------------ + + def test_baseline_create_one_finding_under_inheritance(self): + """ + Single Finding.objects.create() on inheritance-on product. + + post_save fires `inherit_tags_on_instance` which calls + `_manage_inherited_tags` → 2 m2m `.set()` calls per save. This + baseline pins the per-finding cost. Phase A gates on `created=True` + so updates stop paying it; Phase B replaces the M2M dance with a + single JSON column write. + """ + product = _make_product_with_findings("perf-create-one", n_findings=0, tags=["t1", "t2"]) + engagement = Engagement.objects.filter(product=product).first() + test = Test.objects.filter(engagement=engagement).first() + user = User.objects.get(username="tag_perf_user") + + with self.assertNumQueries(self.EXPECTED_CREATE_ONE_FINDING): + Finding.objects.create( + test=test, + title="single-perf", + severity="Medium", + reporter=user, + ) + + # Finding.save() titlecases + truncates the title — look up via test FK + finding = Finding.objects.filter(test=test).first() + self.assertIsNotNone(finding) + self.assertEqual({"t1", "t2"}, {t.name for t in finding.tags.all()}) + + def test_baseline_create_100_findings_under_inheritance(self): + """ + 100 sequential Finding.objects.create() under inheritance. + + Approximates an importer hot loop. Today every iteration fires + `_manage_inherited_tags` per finding. After Phase B, wrapping in + `with tag_inheritance.batch():` should collapse to a single bulk + sync at exit. + """ + product = _make_product_with_findings("perf-create-100", n_findings=0, tags=["t1", "t2"]) + engagement = Engagement.objects.filter(product=product).first() + test = Test.objects.filter(engagement=engagement).first() + user = User.objects.get(username="tag_perf_user") + + with self.assertNumQueries(self.EXPECTED_CREATE_100_FINDINGS): + for i in range(100): + Finding.objects.create( + test=test, + title=f"loop-{i}", + severity="Medium", + reporter=user, + ) + + self.assertEqual(100, Finding.objects.filter(test=test).count()) + any_finding = Finding.objects.filter(test=test).first() + self.assertEqual({"t1", "t2"}, {t.name for t in any_finding.tags.all()}) + + # ------------------------------------------------------------------ + # Sticky enforcement on child tag edits + # ------------------------------------------------------------------ + + def test_baseline_finding_add_user_tag_sticky_path(self): + """ + `finding.tags.add("user-only")` — sticky signal still runs. + + Adding a *non-inherited* tag still fires `m2m_changed` → + `make_inherited_tags_sticky` → re-checks product tags. Phase B + moves this work out of the signal entirely. + """ + product = _make_product_with_findings("perf-sticky-add", n_findings=1, tags=["inherited"]) + finding = Finding.objects.filter(test__engagement__product=product).first() + + with self.assertNumQueries(self.EXPECTED_FINDING_ADD_USER_TAG): + finding.tags.add("user-only") + + finding_tag_names = {t.name for t in finding.tags.all()} + self.assertIn("user-only", finding_tag_names) + self.assertIn("inherited", finding_tag_names) # still sticky + + def test_baseline_finding_remove_inherited_tag_sticky_re_adds(self): + """ + `finding.tags.remove("inherited")` — sticky re-adds. + + Most expensive sticky path: signal re-applies inherited tags via + `inherit_tags` → `_manage_inherited_tags` → 2 M2M `.set()` calls. + """ + product = _make_product_with_findings("perf-sticky-rm", n_findings=1, tags=["inherited"]) + finding = Finding.objects.filter(test__engagement__product=product).first() + + with self.assertNumQueries(self.EXPECTED_FINDING_REMOVE_INHERITED): + finding.tags.remove("inherited") + + # Sticky re-adds the inherited tag + self.assertIn("inherited", {t.name for t in finding.tags.all()}) + + # ------------------------------------------------------------------ + # Pinned baselines (current code; tighten in PR #1 / PR #2) + # ------------------------------------------------------------------ + # Calibrated against current implementation. If a redesign lowers a + # number, lower the pin in the same PR. If a regression raises it, fix + # the regression. NEVER raise a pin without justification. + + # Calibrated against current `dev` branch behavior. + # Tighten as PR #1 (Phase A) and PR #2 (Phase B) land. + EXPECTED_PRODUCT_TAG_ADD_100 = 4758 + EXPECTED_PRODUCT_TAG_REMOVE_100 = 4540 + EXPECTED_CREATE_ONE_FINDING = 64 + EXPECTED_CREATE_100_FINDINGS = 4025 + EXPECTED_FINDING_ADD_USER_TAG = 17 + EXPECTED_FINDING_REMOVE_INHERITED = 44 From 961b73efe07c22a5da003c1a7476fe83eb0d991c Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Tue, 5 May 2026 21:54:32 +0200 Subject: [PATCH 02/12] test: add Endpoint (V2) and Location (V3) propagation baselines Extends the perf test class with two more pinned hot paths so all child models exercised by `propagate_tags_on_product_sync` are covered: product_tag_add -> 100 endpoints (V2) : 3958 product_tag_remove -> 100 endpoints (V2): 3740 product_tag_add -> 100 locations (V3) : 4532 product_tag_remove -> 100 locations (V3): 4307 Both V2 and V3 paths run regardless of the ambient `V3_FEATURE_LOCATIONS` setting via per-test `@override_settings(...)`. CI matrix runs the suite in both modes, so dynamic pin selection (`_pin(v2=..., v3=...)`) handles the small per-mode count differences on the existing finding tests. --- unittests/test_tag_inheritance_perf.py | 125 ++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 3 deletions(-) diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index 8fdc41cc288..a189a0880d4 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -16,11 +16,12 @@ import logging +from django.conf import settings from django.contrib.auth.models import User from django.test import override_settings from django.utils import timezone -from dojo.models import Engagement, Finding, Product, Product_Type, Test, Test_Type +from dojo.models import Endpoint, Engagement, Finding, Product, Product_Type, Test, Test_Type from dojo.product.helpers import propagate_tags_on_product_sync from unittests.dojo_test_case import DojoTestCase @@ -61,6 +62,34 @@ def _make_product_with_findings(name: str, *, n_findings: int, tags: list[str] | return product +def _make_endpoints(product: Product, n: int) -> None: + """Create N Endpoints attached directly to the product (V2 only).""" + for i in range(n): + ep = Endpoint(host=f"perf-{product.id}-{i}.example.com", product=product) + ep.save() + + +def _make_locations(product: Product, n: int) -> None: + """Create N URL Locations attached to the product via LocationManager.persist (V3 only).""" + # Local imports so the file remains importable when V3_FEATURE_LOCATIONS=False. + from dojo.importers.location_manager import LocationManager # noqa: PLC0415 + from dojo.tools.locations import LocationData # noqa: PLC0415 + + finding = Finding.objects.filter(test__engagement__product=product).first() + if finding is None: + # _make_product_with_findings should have been called first with n_findings>=1. + msg = "_make_locations requires the product to have at least one Finding" + raise RuntimeError(msg) + + loc_data = [ + LocationData(type="url", data={"url": f"https://perf-{product.id}-{i}.example.com"}) + for i in range(n) + ] + mgr = LocationManager(product) + mgr.record_locations_for_finding(finding, loc_data) + mgr.persist() + + @override_settings( CELERY_TASK_ALWAYS_EAGER=True, CELERY_TASK_EAGER_PROPAGATES=True, @@ -236,6 +265,75 @@ def test_baseline_finding_remove_inherited_tag_sticky_re_adds(self): # Sticky re-adds the inherited tag self.assertIn("inherited", {t.name for t in finding.tags.all()}) + # ------------------------------------------------------------------ + # V2: propagation to Endpoints (skipped under V3_FEATURE_LOCATIONS) + # ------------------------------------------------------------------ + + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_product_tag_add_propagates_to_100_endpoints_v2(self): + """`product.tags.add("x")` then sync -> propagate to 100 Endpoints (V2).""" + product = _make_product_with_findings("perf-add-eps", n_findings=0, tags=["initial"]) + _make_endpoints(product, n=100) + + with self.assertNumQueries(self.EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS): + product.tags.add("perf-added-ep") + propagate_tags_on_product_sync(product) + + endpoint = Endpoint.objects.filter(product=product).first() + self.assertIn("perf-added-ep", [t.name for t in endpoint.tags.all()]) + + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_product_tag_remove_propagates_to_100_endpoints_v2(self): + """`product.tags.remove("x")` then sync -> remove from 100 Endpoints (V2).""" + product = _make_product_with_findings("perf-remove-eps", n_findings=0, tags=["to-remove-ep", "stays-ep"]) + _make_endpoints(product, n=100) + + with self.assertNumQueries(self.EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS): + product.tags.remove("to-remove-ep") + propagate_tags_on_product_sync(product) + + endpoint = Endpoint.objects.filter(product=product).first() + endpoint_tag_names = {t.name for t in endpoint.tags.all()} + self.assertNotIn("to-remove-ep", endpoint_tag_names) + self.assertIn("stays-ep", endpoint_tag_names) + + # ------------------------------------------------------------------ + # V3: propagation to Locations (skipped under V2) + # ------------------------------------------------------------------ + + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_product_tag_add_propagates_to_100_locations_v3(self): + """`product.tags.add("x")` then sync -> propagate to 100 Locations (V3).""" + # Locations are created against a finding; ensure the product has one. + product = _make_product_with_findings("perf-add-locs", n_findings=1, tags=["initial"]) + _make_locations(product, n=100) + + with self.assertNumQueries(self.EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS): + product.tags.add("perf-added-loc") + propagate_tags_on_product_sync(product) + + from dojo.location.models import Location # noqa: PLC0415 + loc = Location.objects.filter(products__product=product).first() + self.assertIsNotNone(loc) + self.assertIn("perf-added-loc", [t.name for t in loc.tags.all()]) + + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): + """`product.tags.remove("x")` then sync -> remove from 100 Locations (V3).""" + product = _make_product_with_findings("perf-remove-locs", n_findings=1, tags=["to-remove-loc", "stays-loc"]) + _make_locations(product, n=100) + + with self.assertNumQueries(self.EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS): + product.tags.remove("to-remove-loc") + propagate_tags_on_product_sync(product) + + from dojo.location.models import Location # noqa: PLC0415 + loc = Location.objects.filter(products__product=product).first() + self.assertIsNotNone(loc) + location_tag_names = {t.name for t in loc.tags.all()} + self.assertNotIn("to-remove-loc", location_tag_names) + self.assertIn("stays-loc", location_tag_names) + # ------------------------------------------------------------------ # Pinned baselines (current code; tighten in PR #1 / PR #2) # ------------------------------------------------------------------ @@ -245,9 +343,30 @@ def test_baseline_finding_remove_inherited_tag_sticky_re_adds(self): # Calibrated against current `dev` branch behavior. # Tighten as PR #1 (Phase A) and PR #2 (Phase B) land. - EXPECTED_PRODUCT_TAG_ADD_100 = 4758 - EXPECTED_PRODUCT_TAG_REMOVE_100 = 4540 + # Some hot paths execute slightly different code under V2 vs V3 + # (V3 walks an extra Location queryset; V2 walks an Endpoint queryset). + # Use ``_pin(v2=..., v3=...)`` to select the appropriate baseline. + @staticmethod + def _pin(*, v2: int, v3: int) -> int: + return v3 if settings.V3_FEATURE_LOCATIONS else v2 + + @property + def EXPECTED_PRODUCT_TAG_ADD_100(self) -> int: + return self._pin(v2=4758, v3=4759) + + @property + def EXPECTED_PRODUCT_TAG_REMOVE_100(self) -> int: + return self._pin(v2=4540, v3=4541) + EXPECTED_CREATE_ONE_FINDING = 64 EXPECTED_CREATE_100_FINDINGS = 4025 EXPECTED_FINDING_ADD_USER_TAG = 17 EXPECTED_FINDING_REMOVE_INHERITED = 44 + + # V2 endpoint paths (only run when V3_FEATURE_LOCATIONS=False) + EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS = 3958 + EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 3740 + + # V3 location paths (only run when V3_FEATURE_LOCATIONS=True) + EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 4532 + EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 4307 From acd87b367ef3c51af559f1e6ec7335608f0af3a8 Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Tue, 5 May 2026 22:23:47 +0200 Subject: [PATCH 03/12] test: add ZAP import/reimport baselines + V2/V3 variants for every scenario Two additions: 1. New TagInheritanceImportPerfBaselines class pins query counts for the importer hot path (production's heaviest tag-inheritance scenario). Both first-import and no-change-reimport are covered, each with V2 and V3 method variants: zap_import_v2 : 1461 zap_import_v3 : 1319 zap_reimport_no_change_v2 : 77 zap_reimport_no_change_v3 : 95 2. Restructures the existing baseline class so every scenario has both a _v2 and _v3 method variant via per-test @override_settings. The whole suite now runs both modes in a single invocation; no need to run twice with different DD_V3_FEATURE_LOCATIONS env. Phase A leaves the importer numbers ~unchanged (importer hot loop is creation-driven, not the bulk-propagation path Phase A targets). Phase B's tag_inheritance.batch() context manager is the lever that lowers these numbers. --- unittests/test_tag_inheritance_perf.py | 330 +++++++++++++++++-------- 1 file changed, 221 insertions(+), 109 deletions(-) diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index a189a0880d4..c3f71dd45a0 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -16,14 +16,18 @@ import logging -from django.conf import settings from django.contrib.auth.models import User from django.test import override_settings from django.utils import timezone from dojo.models import Endpoint, Engagement, Finding, Product, Product_Type, Test, Test_Type from dojo.product.helpers import propagate_tags_on_product_sync -from unittests.dojo_test_case import DojoTestCase +from unittests.dojo_test_case import ( + DojoAPITestCase, + DojoTestCase, + get_unit_tests_scans_path, + versioned_fixtures, +) logger = logging.getLogger(__name__) @@ -134,87 +138,50 @@ def setUpTestData(cls): ss.save() # ------------------------------------------------------------------ - # Product tag add / remove → propagate to children + # Helpers shared by V2/V3 variants of the same scenario. # ------------------------------------------------------------------ - def test_baseline_product_tag_add_propagates_to_100_findings(self): - """ - `product.tags.add("x")` then sync → propagate to 100 findings. - - Hot path: Product tag toggle in the UI on a product with many - findings. Today's flow runs `obj.save()` per child. Phase A bulk SQL - will collapse this dramatically. - """ - product = _make_product_with_findings("perf-add", n_findings=100, tags=["initial"]) - - with self.assertNumQueries(self.EXPECTED_PRODUCT_TAG_ADD_100): + def _do_product_tag_add_findings(self, name: str, expected: int) -> None: + product = _make_product_with_findings(name, n_findings=100, tags=["initial"]) + with self.assertNumQueries(expected): product.tags.add("perf-added") propagate_tags_on_product_sync(product) - - # Correctness: a finding under the product now carries the new tag. finding = Finding.objects.filter(test__engagement__product=product).first() self.assertIn("perf-added", [t.name for t in finding.tags.all()]) - def test_baseline_product_tag_remove_propagates_to_100_findings(self): - """`product.tags.remove("x")` then sync → remove from 100 findings.""" - product = _make_product_with_findings("perf-remove", n_findings=100, tags=["to-remove", "stays"]) - - with self.assertNumQueries(self.EXPECTED_PRODUCT_TAG_REMOVE_100): + def _do_product_tag_remove_findings(self, name: str, expected: int) -> None: + product = _make_product_with_findings(name, n_findings=100, tags=["to-remove", "stays"]) + with self.assertNumQueries(expected): product.tags.remove("to-remove") propagate_tags_on_product_sync(product) - finding = Finding.objects.filter(test__engagement__product=product).first() finding_tag_names = {t.name for t in finding.tags.all()} self.assertNotIn("to-remove", finding_tag_names) self.assertIn("stays", finding_tag_names) - # ------------------------------------------------------------------ - # Child creation under inheritance-on product - # ------------------------------------------------------------------ - - def test_baseline_create_one_finding_under_inheritance(self): - """ - Single Finding.objects.create() on inheritance-on product. - - post_save fires `inherit_tags_on_instance` which calls - `_manage_inherited_tags` → 2 m2m `.set()` calls per save. This - baseline pins the per-finding cost. Phase A gates on `created=True` - so updates stop paying it; Phase B replaces the M2M dance with a - single JSON column write. - """ - product = _make_product_with_findings("perf-create-one", n_findings=0, tags=["t1", "t2"]) + def _do_create_one_finding(self, name: str, expected: int) -> None: + product = _make_product_with_findings(name, n_findings=0, tags=["t1", "t2"]) engagement = Engagement.objects.filter(product=product).first() test = Test.objects.filter(engagement=engagement).first() user = User.objects.get(username="tag_perf_user") - - with self.assertNumQueries(self.EXPECTED_CREATE_ONE_FINDING): + with self.assertNumQueries(expected): Finding.objects.create( test=test, title="single-perf", severity="Medium", reporter=user, ) - - # Finding.save() titlecases + truncates the title — look up via test FK + # Finding.save() titlecases + truncates the title; look up via test FK. finding = Finding.objects.filter(test=test).first() self.assertIsNotNone(finding) self.assertEqual({"t1", "t2"}, {t.name for t in finding.tags.all()}) - def test_baseline_create_100_findings_under_inheritance(self): - """ - 100 sequential Finding.objects.create() under inheritance. - - Approximates an importer hot loop. Today every iteration fires - `_manage_inherited_tags` per finding. After Phase B, wrapping in - `with tag_inheritance.batch():` should collapse to a single bulk - sync at exit. - """ - product = _make_product_with_findings("perf-create-100", n_findings=0, tags=["t1", "t2"]) + def _do_create_100_findings(self, name: str, expected: int) -> None: + product = _make_product_with_findings(name, n_findings=0, tags=["t1", "t2"]) engagement = Engagement.objects.filter(product=product).first() test = Test.objects.filter(engagement=engagement).first() user = User.objects.get(username="tag_perf_user") - - with self.assertNumQueries(self.EXPECTED_CREATE_100_FINDINGS): + with self.assertNumQueries(expected): for i in range(100): Finding.objects.create( test=test, @@ -222,48 +189,86 @@ def test_baseline_create_100_findings_under_inheritance(self): severity="Medium", reporter=user, ) - self.assertEqual(100, Finding.objects.filter(test=test).count()) any_finding = Finding.objects.filter(test=test).first() self.assertEqual({"t1", "t2"}, {t.name for t in any_finding.tags.all()}) + def _do_finding_add_user_tag(self, name: str, expected: int) -> None: + product = _make_product_with_findings(name, n_findings=1, tags=["inherited"]) + finding = Finding.objects.filter(test__engagement__product=product).first() + with self.assertNumQueries(expected): + finding.tags.add("user-only") + finding_tag_names = {t.name for t in finding.tags.all()} + self.assertIn("user-only", finding_tag_names) + self.assertIn("inherited", finding_tag_names) # still sticky + + def _do_finding_remove_inherited(self, name: str, expected: int) -> None: + product = _make_product_with_findings(name, n_findings=1, tags=["inherited"]) + finding = Finding.objects.filter(test__engagement__product=product).first() + with self.assertNumQueries(expected): + finding.tags.remove("inherited") + # Sticky re-adds the inherited tag. + self.assertIn("inherited", {t.name for t in finding.tags.all()}) + # ------------------------------------------------------------------ - # Sticky enforcement on child tag edits + # Product tag add / remove (Findings only) - V2 + V3 variants. # ------------------------------------------------------------------ - def test_baseline_finding_add_user_tag_sticky_path(self): - """ - `finding.tags.add("user-only")` — sticky signal still runs. + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_product_tag_add_propagates_to_100_findings_v2(self): + self._do_product_tag_add_findings("perf-add-v2", self.EXPECTED_PRODUCT_TAG_ADD_100_V2) - Adding a *non-inherited* tag still fires `m2m_changed` → - `make_inherited_tags_sticky` → re-checks product tags. Phase B - moves this work out of the signal entirely. - """ - product = _make_product_with_findings("perf-sticky-add", n_findings=1, tags=["inherited"]) - finding = Finding.objects.filter(test__engagement__product=product).first() + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_product_tag_add_propagates_to_100_findings_v3(self): + self._do_product_tag_add_findings("perf-add-v3", self.EXPECTED_PRODUCT_TAG_ADD_100_V3) - with self.assertNumQueries(self.EXPECTED_FINDING_ADD_USER_TAG): - finding.tags.add("user-only") + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_product_tag_remove_propagates_to_100_findings_v2(self): + self._do_product_tag_remove_findings("perf-remove-v2", self.EXPECTED_PRODUCT_TAG_REMOVE_100_V2) - finding_tag_names = {t.name for t in finding.tags.all()} - self.assertIn("user-only", finding_tag_names) - self.assertIn("inherited", finding_tag_names) # still sticky + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_product_tag_remove_propagates_to_100_findings_v3(self): + self._do_product_tag_remove_findings("perf-remove-v3", self.EXPECTED_PRODUCT_TAG_REMOVE_100_V3) - def test_baseline_finding_remove_inherited_tag_sticky_re_adds(self): - """ - `finding.tags.remove("inherited")` — sticky re-adds. + # ------------------------------------------------------------------ + # Child creation under inheritance - V2 + V3 variants. + # ------------------------------------------------------------------ - Most expensive sticky path: signal re-applies inherited tags via - `inherit_tags` → `_manage_inherited_tags` → 2 M2M `.set()` calls. - """ - product = _make_product_with_findings("perf-sticky-rm", n_findings=1, tags=["inherited"]) - finding = Finding.objects.filter(test__engagement__product=product).first() + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_create_one_finding_under_inheritance_v2(self): + self._do_create_one_finding("perf-create-one-v2", self.EXPECTED_CREATE_ONE_FINDING_V2) - with self.assertNumQueries(self.EXPECTED_FINDING_REMOVE_INHERITED): - finding.tags.remove("inherited") + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_create_one_finding_under_inheritance_v3(self): + self._do_create_one_finding("perf-create-one-v3", self.EXPECTED_CREATE_ONE_FINDING_V3) - # Sticky re-adds the inherited tag - self.assertIn("inherited", {t.name for t in finding.tags.all()}) + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_create_100_findings_under_inheritance_v2(self): + self._do_create_100_findings("perf-create-100-v2", self.EXPECTED_CREATE_100_FINDINGS_V2) + + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_create_100_findings_under_inheritance_v3(self): + self._do_create_100_findings("perf-create-100-v3", self.EXPECTED_CREATE_100_FINDINGS_V3) + + # ------------------------------------------------------------------ + # Sticky enforcement on child tag edits - V2 + V3 variants. + # ------------------------------------------------------------------ + + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_finding_add_user_tag_sticky_path_v2(self): + self._do_finding_add_user_tag("perf-sticky-add-v2", self.EXPECTED_FINDING_ADD_USER_TAG_V2) + + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_finding_add_user_tag_sticky_path_v3(self): + self._do_finding_add_user_tag("perf-sticky-add-v3", self.EXPECTED_FINDING_ADD_USER_TAG_V3) + + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_finding_remove_inherited_tag_sticky_re_adds_v2(self): + self._do_finding_remove_inherited("perf-sticky-rm-v2", self.EXPECTED_FINDING_REMOVE_INHERITED_V2) + + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_finding_remove_inherited_tag_sticky_re_adds_v3(self): + self._do_finding_remove_inherited("perf-sticky-rm-v3", self.EXPECTED_FINDING_REMOVE_INHERITED_V3) # ------------------------------------------------------------------ # V2: propagation to Endpoints (skipped under V3_FEATURE_LOCATIONS) @@ -337,36 +342,143 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): # ------------------------------------------------------------------ # Pinned baselines (current code; tighten in PR #1 / PR #2) # ------------------------------------------------------------------ - # Calibrated against current implementation. If a redesign lowers a - # number, lower the pin in the same PR. If a regression raises it, fix - # the regression. NEVER raise a pin without justification. - - # Calibrated against current `dev` branch behavior. - # Tighten as PR #1 (Phase A) and PR #2 (Phase B) land. - # Some hot paths execute slightly different code under V2 vs V3 - # (V3 walks an extra Location queryset; V2 walks an Endpoint queryset). - # Use ``_pin(v2=..., v3=...)`` to select the appropriate baseline. - @staticmethod - def _pin(*, v2: int, v3: int) -> int: - return v3 if settings.V3_FEATURE_LOCATIONS else v2 - - @property - def EXPECTED_PRODUCT_TAG_ADD_100(self) -> int: - return self._pin(v2=4758, v3=4759) - - @property - def EXPECTED_PRODUCT_TAG_REMOVE_100(self) -> int: - return self._pin(v2=4540, v3=4541) - - EXPECTED_CREATE_ONE_FINDING = 64 - EXPECTED_CREATE_100_FINDINGS = 4025 - EXPECTED_FINDING_ADD_USER_TAG = 17 - EXPECTED_FINDING_REMOVE_INHERITED = 44 - - # V2 endpoint paths (only run when V3_FEATURE_LOCATIONS=False) + # Each scenario pins V2 and V3 separately because the propagation code + # branches on V3_FEATURE_LOCATIONS. Per-test @override_settings forces + # the appropriate mode so all variants execute in a single suite run. + + # Findings-only scenarios. + EXPECTED_PRODUCT_TAG_ADD_100_V2 = 4758 + EXPECTED_PRODUCT_TAG_ADD_100_V3 = 4759 + EXPECTED_PRODUCT_TAG_REMOVE_100_V2 = 4540 + EXPECTED_PRODUCT_TAG_REMOVE_100_V3 = 4541 + + EXPECTED_CREATE_ONE_FINDING_V2 = 64 + EXPECTED_CREATE_ONE_FINDING_V3 = 64 + EXPECTED_CREATE_100_FINDINGS_V2 = 4024 + EXPECTED_CREATE_100_FINDINGS_V3 = 4024 + + EXPECTED_FINDING_ADD_USER_TAG_V2 = 17 + EXPECTED_FINDING_ADD_USER_TAG_V3 = 17 + EXPECTED_FINDING_REMOVE_INHERITED_V2 = 44 + EXPECTED_FINDING_REMOVE_INHERITED_V3 = 44 + + # V2 endpoint paths (Endpoints have no V3 counterpart in this class). EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS = 3958 EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 3740 - # V3 location paths (only run when V3_FEATURE_LOCATIONS=True) + # V3 location paths (LocationManager has no V2 counterpart in this class). EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 4532 EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 4307 + + +@override_settings( + CELERY_TASK_ALWAYS_EAGER=True, + CELERY_TASK_EAGER_PROPAGATES=True, +) +@versioned_fixtures +class TagInheritanceImportPerfBaselines(DojoAPITestCase): + + """ + Pinned query-count baselines for the importer hot path. + + Real production tag-inheritance cost lives in scan import / reimport: the + importer creates findings + endpoints/locations, then `_manage_inherited_tags` + runs per row. Phase A (bulk product-side propagation + post_save gated on + create) doesn't touch this loop because the importer's hot path is + creation-driven. Phase B's `tag_inheritance.batch()` context manager + targets it. + + Two scenarios: + - First import of a ZAP scan into an inheritance-on product. + - Reimport of the same scan with no changes (idempotent path). + """ + + fixtures = ["dojo_testdata.json"] + + @classmethod + def setUpTestData(cls): + from dojo.models import System_Settings # noqa: PLC0415 + ss = System_Settings.objects.get() + ss.enable_product_tag_inheritance = True + ss.save() + + def setUp(self): + super().setUp() + self.login_as_admin() + self.system_settings(enable_product_tag_inheritance=True) + self.product = self.create_product("Tag Perf Import Product", tags=["inherit", "these"]) + self.engagement = self.create_engagement("Tag Perf Import Engagement", self.product) + self.scan_path = get_unit_tests_scans_path("zap") / "dvwa_baseline_dojo.xml" + + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_zap_scan_import_v2(self): + """ + V2: first-time import of a 19-finding ZAP scan with inheritance enabled. + + Captures total query count for: scan parse + finding creation + endpoint + attachment + per-row inherit_tags signal chain. Production hot path. + Phase A leaves this number ~unchanged; Phase B's `tag_inheritance.batch()` + targets it. + """ + with self.assertNumQueries(self.EXPECTED_ZAP_IMPORT_V2): + response = self.import_scan_with_params( + self.scan_path, + engagement=self.engagement.id, + ) + + test_id = response["test"] + finding = Finding.objects.filter(test_id=test_id).first() + self.assertIsNotNone(finding) + self.assertEqual({"inherit", "these"}, {t.name for t in finding.tags.all()}) + + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_zap_scan_import_v3(self): + """V3: first-time import; uses LocationManager for endpoint persistence.""" + with self.assertNumQueries(self.EXPECTED_ZAP_IMPORT_V3): + response = self.import_scan_with_params( + self.scan_path, + engagement=self.engagement.id, + ) + + test_id = response["test"] + finding = Finding.objects.filter(test_id=test_id).first() + self.assertIsNotNone(finding) + self.assertEqual({"inherit", "these"}, {t.name for t in finding.tags.all()}) + + @override_settings(V3_FEATURE_LOCATIONS=False) + def test_baseline_zap_scan_reimport_no_change_v2(self): + """V2: reimport same scan; expected to be a near-no-op for tag inheritance.""" + response = self.import_scan_with_params( + self.scan_path, + engagement=self.engagement.id, + ) + test_id = response["test"] + + with self.assertNumQueries(self.EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2): + self.reimport_scan_with_params(test_id, str(self.scan_path)) + + finding = Finding.objects.filter(test_id=test_id).first() + self.assertEqual({"inherit", "these"}, {t.name for t in finding.tags.all()}) + + @override_settings(V3_FEATURE_LOCATIONS=True) + def test_baseline_zap_scan_reimport_no_change_v3(self): + """V3: reimport same scan with no changes.""" + response = self.import_scan_with_params( + self.scan_path, + engagement=self.engagement.id, + ) + test_id = response["test"] + + with self.assertNumQueries(self.EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3): + self.reimport_scan_with_params(test_id, str(self.scan_path)) + + finding = Finding.objects.filter(test_id=test_id).first() + self.assertEqual({"inherit", "these"}, {t.name for t in finding.tags.all()}) + + # Pinned baselines per mode. Each test forces its own V3_FEATURE_LOCATIONS + # via @override_settings so all four import paths run in a single suite + # invocation regardless of the ambient `DD_V3_FEATURE_LOCATIONS` env var. + EXPECTED_ZAP_IMPORT_V2 = 1461 + EXPECTED_ZAP_IMPORT_V3 = 1319 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 77 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 95 From c3e041216ba1d1e0d89310b748d30b04e95e4c06 Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Wed, 6 May 2026 14:33:43 +0200 Subject: [PATCH 04/12] test: warm ContentType cache in tag inheritance perf baselines First V3 Location op in the class paid a one-time ContentType lookup, producing a matrix-dependent off-by-one (V3-default-on CI: 4531; V3-default-off CI + local: 4532). Match the warm-up pattern used in test_importers_performance and pin EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS to the post-warm value (4531). --- unittests/test_tag_inheritance_perf.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index c3f71dd45a0..450a3d2ab89 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -17,9 +17,11 @@ import logging from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType from django.test import override_settings from django.utils import timezone +from dojo.location.models import Location, LocationFindingReference, LocationProductReference from dojo.models import Endpoint, Engagement, Finding, Product, Product_Type, Test, Test_Type from dojo.product.helpers import propagate_tags_on_product_sync from unittests.dojo_test_case import ( @@ -137,6 +139,16 @@ def setUpTestData(cls): ss.enable_product_tag_inheritance = True ss.save() + # Warm up ContentType cache for models touched by the propagation + # paths so first-call ContentType lookups don't count against the + # measured sections (matches the pattern in test_importers_performance). + # Without this, the first test in a fresh process to exercise the V3 + # Location path pays a one-time lookup, producing a matrix-dependent + # off-by-one when CI runs with V3_FEATURE_LOCATIONS true vs false at + # startup. + for model in [Endpoint, Engagement, Finding, Location, LocationFindingReference, LocationProductReference, Product, Product_Type, Test, Test_Type]: + ContentType.objects.get_for_model(model) + # ------------------------------------------------------------------ # Helpers shared by V2/V3 variants of the same scenario. # ------------------------------------------------------------------ @@ -317,7 +329,6 @@ def test_baseline_product_tag_add_propagates_to_100_locations_v3(self): product.tags.add("perf-added-loc") propagate_tags_on_product_sync(product) - from dojo.location.models import Location # noqa: PLC0415 loc = Location.objects.filter(products__product=product).first() self.assertIsNotNone(loc) self.assertIn("perf-added-loc", [t.name for t in loc.tags.all()]) @@ -332,7 +343,6 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): product.tags.remove("to-remove-loc") propagate_tags_on_product_sync(product) - from dojo.location.models import Location # noqa: PLC0415 loc = Location.objects.filter(products__product=product).first() self.assertIsNotNone(loc) location_tag_names = {t.name for t in loc.tags.all()} @@ -367,7 +377,7 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 3740 # V3 location paths (LocationManager has no V2 counterpart in this class). - EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 4532 + EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 4531 EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 4307 From d2c4fc57586fe16ae4e6c391eed237b1f267c365 Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Tue, 5 May 2026 21:43:23 +0200 Subject: [PATCH 05/12] perf(tags): bulk-propagate inherited tags + gate child post_save on create Replaces the per-row `.save()` loop in `propagate_tags_on_product_sync` with bulk SQL through the existing tag-utils helpers. For every child model (Engagement/Test/Finding/Endpoint/Location), reads current inherited_tags in one query, computes the per-child diff against the Product's tags, and applies adds/removes via `bulk_add_tag_mapping` and the new `bulk_remove_tags_from_instances` helper. Both `tags` and `inherited_tags` fields are kept in sync. Also gates the per-child `inherit_tags_on_instance` post_save handler on `created=True`. The previous behavior fired on every save (create OR update), repeatedly re-applying inherited tags to children whose tag state had not changed. Sticky enforcement on user-driven tag edits is unchanged (still handled by `make_inherited_tags_sticky` on m2m_changed). Pinned query-count baselines from PR #14811 drop accordingly: product_tag_add -> 100 findings : 4758 -> 91 (~52x fewer queries) product_tag_remove -> 100 findings : 4540 -> 53 (~85x fewer queries) Sticky and child-creation paths are unchanged in this PR. Phase B targets those (centralized inheritance module + drop the duplicate `inherited_tags` TagField). --- dojo/product/helpers.py | 126 ++++++++++++++++++++----- dojo/tag_utils.py | 114 +++++++++++++++++++++- dojo/tags_signals.py | 6 ++ unittests/test_tag_inheritance_perf.py | 33 ++++--- 4 files changed, 242 insertions(+), 37 deletions(-) diff --git a/dojo/product/helpers.py b/dojo/product/helpers.py index cdb0750f317..7bbb2937103 100644 --- a/dojo/product/helpers.py +++ b/dojo/product/helpers.py @@ -1,5 +1,6 @@ import contextlib import logging +from collections import defaultdict from django.conf import settings from django.db.models import Q @@ -7,6 +8,7 @@ from dojo.celery import app from dojo.location.models import Location from dojo.models import Endpoint, Engagement, Finding, Product, Test +from dojo.tag_utils import bulk_add_tag_mapping, bulk_remove_tags_from_instances logger = logging.getLogger(__name__) @@ -19,35 +21,115 @@ def propagate_tags_on_product(product_id, *args, **kwargs): def propagate_tags_on_product_sync(product): - # enagagements + """ + Bulk-apply Product tag changes to all children using through-table SQL. + + Replaces the previous per-row `.save()` loop. For every child model owned + by the product (Engagement, Test, Finding, plus Endpoint or Location + depending on the V3_FEATURE_LOCATIONS flag), reads the existing + `inherited_tags` per child in one query, computes the diff against the + Product's current tags, and applies adds/removes via the bulk tag + helpers. Both `tags` and `inherited_tags` fields are kept in sync. + """ + target_names = {tag.name for tag in product.tags.all()} + logger.debug("Propagating tags from %s to all engagements", product) - propagate_tags_on_object_list(Engagement.objects.filter(product=product)) - # tests + _sync_inheritance_for_qs( + Engagement.objects.filter(product=product), + target_names_per_child=lambda _child: target_names, + ) logger.debug("Propagating tags from %s to all tests", product) - propagate_tags_on_object_list(Test.objects.filter(engagement__product=product)) - # findings + _sync_inheritance_for_qs( + Test.objects.filter(engagement__product=product), + target_names_per_child=lambda _child: target_names, + ) logger.debug("Propagating tags from %s to all findings", product) - propagate_tags_on_object_list(Finding.objects.filter(test__engagement__product=product)) + _sync_inheritance_for_qs( + Finding.objects.filter(test__engagement__product=product), + target_names_per_child=lambda _child: target_names, + ) if settings.V3_FEATURE_LOCATIONS: - # Locations logger.debug("Propagating tags from %s to all locations", product) - propagate_tags_on_object_list( - Location.objects.filter( - # Locations linked directly to a product via LocationProductReference - Q(products__product=product) - # Locations linked indirectly to a product via LocationFindingReference - | Q(findings__finding__test__engagement__product=product), - ).distinct(), + location_qs = Location.objects.filter( + Q(products__product=product) + | Q(findings__finding__test__engagement__product=product), + ).distinct() + # Locations can be linked to multiple products, so the inherited target + # is the union of every related product's tags. Compute per-location. + _sync_inheritance_for_qs( + location_qs, + target_names_per_child=_location_target_names, ) else: - # TODO: Delete this after the move to Locations - # endpoints logger.debug("Propagating tags from %s to all endpoints", product) - propagate_tags_on_object_list(Endpoint.objects.filter(product=product)) + _sync_inheritance_for_qs( + Endpoint.objects.filter(product=product), + target_names_per_child=lambda _child: target_names, + ) + + +def _location_target_names(location): + names: set[str] = set() + for related_product in location.all_related_products(): + if related_product is None: + continue + names.update(tag.name for tag in related_product.tags.all()) + return names + + +def _sync_inheritance_for_qs(queryset, *, target_names_per_child): + """ + Sync inherited_tags + tags for every child in `queryset` to its target tag set. + + target_names_per_child: callable(child) -> set[str]. + + Issues bulk SQL: one through-table read for current inherited_tags, then + bulk add/remove on `tags` and `inherited_tags` fields. + """ + children = list(queryset) + if not children: + return + + model_class = type(children[0]) + inherited_field = model_class._meta.get_field("inherited_tags") + inherited_through = inherited_field.remote_field.through + inherited_tag_model = inherited_field.related_model + + # Resolve through-table FK column for the source side. + source_field_name = None + for field in inherited_through._meta.fields: + if hasattr(field, "remote_field") and field.remote_field and field.remote_field.model == model_class: + source_field_name = field.name + break + + child_ids = [c.pk for c in children] + # One query: pull every (child_id, tag_name) pair from the inherited_tags through table. + existing_pairs = inherited_through.objects.filter( + **{f"{source_field_name}__in": child_ids}, + ).values_list(source_field_name, f"{inherited_tag_model._meta.model_name}__name") + + old_inherited_by_child: dict[int, set[str]] = defaultdict(set) + for child_id, tag_name in existing_pairs: + old_inherited_by_child[child_id].add(tag_name) + + # Compute per-child diff and bucket by tag name. + add_map: dict[str, list] = defaultdict(list) + remove_map: dict[str, list] = defaultdict(list) + for child in children: + target = target_names_per_child(child) + old = old_inherited_by_child.get(child.pk, set()) + for name in target - old: + add_map[name].append(child) + for name in old - target: + remove_map[name].append(child) + # Apply adds. Both `tags` and `inherited_tags` get the same set of new + # inherited names — `_manage_inherited_tags` did the same. + if add_map: + bulk_add_tag_mapping(add_map, tag_field_name="inherited_tags") + bulk_add_tag_mapping(add_map, tag_field_name="tags") -def propagate_tags_on_object_list(object_list): - for obj in object_list: - if obj and obj.id is not None: - logger.debug(f"\tPropagating tags to {type(obj)} - {obj}") - obj.save() + # Apply removes. + for name, instances in remove_map.items(): + bulk_remove_tags_from_instances(name, instances, tag_field_name="inherited_tags") + bulk_remove_tags_from_instances(name, instances, tag_field_name="tags") diff --git a/dojo/tag_utils.py b/dojo/tag_utils.py index 87ed6845961..8b2509e2dab 100644 --- a/dojo/tag_utils.py +++ b/dojo/tag_utils.py @@ -164,6 +164,118 @@ def bulk_add_tags_to_instances(tag_or_tags, instances, tag_field_name: str = "ta return total_created +def bulk_remove_tags_from_instances(tag_or_tags, instances, tag_field_name: str = "tags", batch_size: int | None = None) -> int: + """ + Efficiently remove tag(s) from many model instances. + + Symmetric to ``bulk_add_tags_to_instances``: + + - tag_or_tags: a single string, an iterable of strings or tag objects, or a Tagulous edit string. + - instances: QuerySet or list of model instances of the same class. + - tag_field_name: name of the TagField on the model (default: ``"tags"``). + - Decrements ``tag.count`` for every removed (instance, tag) pair. + - Deletes through-model rows in one DELETE per tag (or batched). + - Clears Django prefetch caches on the input instances so subsequent access reloads from DB. + + Returns the total number of relationships removed across all provided tags. + Tags that do not exist or are not currently associated with any instance are silently skipped. + """ + if batch_size is None: + batch_size = getattr(settings, "TAG_BULK_ADD_BATCH_SIZE", 1000) + + if hasattr(instances, "model"): + instances = list(instances) + + if not instances: + return 0 + + model_class = instances[0].__class__ + + # Mirror the Product safety check from bulk_add_tags_to_instances. Removing + # tags from a Product would normally trigger inheritance propagation via + # m2m_changed signals; this helper bypasses signals, so disallow it. + if model_class is Product: + msg = "bulk_remove_tags_from_instances: Product instances are not supported; use Product.tags.remove() or a propagation-aware helper" + raise ValueError(msg) + + try: + tag_field = model_class._meta.get_field(tag_field_name) + except Exception: + msg = f"Model {model_class.__name__} does not have field '{tag_field_name}'" + raise ValueError(msg) + + if not hasattr(tag_field, "tag_options"): + msg = f"Field '{tag_field_name}' is not a TagField" + raise ValueError(msg) + + tag_model = tag_field.related_model + through_model = tag_field.remote_field.through + + # Normalize input into a list of tag names (mirrors bulk_add_tags_to_instances). + tag_names: list[str] = [] + try: + if isinstance(tag_or_tags, str): + space_delimiter = getattr(tag_field, "tag_options", None).space_delimiter if hasattr(tag_field, "tag_options") else False + tag_names = parse_tags(tag_or_tags, space_delimiter=space_delimiter) + elif isinstance(tag_or_tags, Iterable): + tag_names = [getattr(t, "name", str(t)) for t in tag_or_tags] + else: + tag_names = [str(tag_or_tags)] + except Exception: + tag_names = [str(tag_or_tags)] + + # Resolve through-model FK names dynamically (no hard-coding). + through_fields = {f.name: f for f in through_model._meta.fields} + source_field_name = None + target_field_name = None + for field_name, field in through_fields.items(): + if hasattr(field, "remote_field") and field.remote_field: + if field.remote_field.model == model_class: + source_field_name = field_name + elif field.remote_field.model == tag_model: + target_field_name = field_name + + total_removed = 0 + + for single_tag_name in tag_names: + if not single_tag_name: + continue + + # Resolve the tag — skip silently if it doesn't exist (nothing to remove). + if tag_field.tag_options.case_sensitive: + tag = tag_model.objects.filter(name=single_tag_name).first() + else: + tag = tag_model.objects.filter(name__iexact=single_tag_name).first() + if tag is None: + continue + + for i in range(0, len(instances), batch_size): + batch_instances = instances[i:i + batch_size] + batch_ids = [instance.pk for instance in batch_instances] + + with transaction.atomic(): + # One DELETE per tag-batch. Returns the deleted-row count. + deleted_count, _ = through_model.objects.filter( + **{target_field_name: tag.pk}, + **{f"{source_field_name}__in": batch_ids}, + ).delete() + + if deleted_count: + total_removed += deleted_count + # Decrement the Tagulous-maintained count to avoid drift. + tag_model.objects.filter(pk=tag.pk).update( + count=models.F("count") - deleted_count, + ) + + # Invalidate prefetch caches so callers see the new state. + for instance in batch_instances: + prefetch_cache = getattr(instance, "_prefetched_objects_cache", None) + if prefetch_cache is not None: + prefetch_cache.pop(tag_field_name, None) + + return total_removed + + def bulk_add_tag_mapping( tag_to_instances: dict[str, list], tag_field_name: str = "tags", @@ -410,4 +522,4 @@ def bulk_remove_all_tags(model_class, instance_ids_qs): ) -__all__ = ["bulk_add_tag_mapping", "bulk_add_tags_to_instances", "bulk_apply_parser_tags", "bulk_remove_all_tags"] +__all__ = ["bulk_add_tag_mapping", "bulk_add_tags_to_instances", "bulk_apply_parser_tags", "bulk_remove_all_tags", "bulk_remove_tags_from_instances"] diff --git a/dojo/tags_signals.py b/dojo/tags_signals.py index 0fea7ae8ad5..6fe142f2e55 100644 --- a/dojo/tags_signals.py +++ b/dojo/tags_signals.py @@ -59,6 +59,12 @@ def inherit_linked_instance_tags(instance: LocationFindingReference | LocationPr @receiver(signals.post_save, sender=Finding) @receiver(signals.post_save, sender=Location) def inherit_tags_on_instance(sender, instance, created, **kwargs): + # Only inherit on creation. The previous behavior fired on every save + # (create OR update), repeatedly re-applying inherited tags to children + # whose tag state had not changed. Sticky enforcement on user-driven + # tag edits is handled by `make_inherited_tags_sticky` (m2m_changed). + if not created: + return inherit_instance_tags(instance) diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index 450a3d2ab89..8e9f9a5f792 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -357,10 +357,12 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): # the appropriate mode so all variants execute in a single suite run. # Findings-only scenarios. - EXPECTED_PRODUCT_TAG_ADD_100_V2 = 4758 - EXPECTED_PRODUCT_TAG_ADD_100_V3 = 4759 - EXPECTED_PRODUCT_TAG_REMOVE_100_V2 = 4540 - EXPECTED_PRODUCT_TAG_REMOVE_100_V3 = 4541 + # Pre-Phase-A V2: 4758 add, 4540 remove. V3: 4759/4541. + # Phase A bulk-propagate drops these dramatically. + EXPECTED_PRODUCT_TAG_ADD_100_V2 = 91 + EXPECTED_PRODUCT_TAG_ADD_100_V3 = 91 + EXPECTED_PRODUCT_TAG_REMOVE_100_V2 = 53 + EXPECTED_PRODUCT_TAG_REMOVE_100_V3 = 53 EXPECTED_CREATE_ONE_FINDING_V2 = 64 EXPECTED_CREATE_ONE_FINDING_V3 = 64 @@ -372,13 +374,13 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): EXPECTED_FINDING_REMOVE_INHERITED_V2 = 44 EXPECTED_FINDING_REMOVE_INHERITED_V3 = 44 - # V2 endpoint paths (Endpoints have no V3 counterpart in this class). - EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS = 3958 - EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 3740 + # V2 endpoint paths. Pre-Phase-A: 3958 add, 3740 remove. + EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS = 91 + EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 53 - # V3 location paths (LocationManager has no V2 counterpart in this class). - EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 4531 - EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 4307 + # V3 location paths. Pre-Phase-A: 4532 add, 4307 remove. + EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 316 + EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 266 @override_settings( @@ -488,7 +490,10 @@ def test_baseline_zap_scan_reimport_no_change_v3(self): # Pinned baselines per mode. Each test forces its own V3_FEATURE_LOCATIONS # via @override_settings so all four import paths run in a single suite # invocation regardless of the ambient `DD_V3_FEATURE_LOCATIONS` env var. - EXPECTED_ZAP_IMPORT_V2 = 1461 - EXPECTED_ZAP_IMPORT_V3 = 1319 - EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 77 - EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 95 + # Phase A nudges these slightly downward (post_save gated on created=True + # avoids re-running inheritance on no-op finding updates during reimport). + # Pre-Phase-A: 1461/1319 import, 77/95 reimport. + EXPECTED_ZAP_IMPORT_V2 = 1385 + EXPECTED_ZAP_IMPORT_V3 = 1243 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 69 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 87 From e04bf8388d098e285065a04ec46a2fa97921a5aa Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Wed, 6 May 2026 19:09:45 +0200 Subject: [PATCH 06/12] perf(tags): replace process-global signal disconnect with thread-local batch context Adds dojo/tag_inheritance.py with a thread-local batch() context manager and is_in_batch() predicate. While the calling thread is inside a batch, make_inherited_tags_sticky (m2m_changed) early-returns; the calling code takes responsibility for applying inheritance in bulk. Replaces the previous pattern in dojo/importers/location_manager.py:556: disconnected = signals.m2m_changed.disconnect( make_inherited_tags_sticky, sender=Location.tags.through, ) try: ... finally: if disconnected: signals.m2m_changed.connect(...) Signal.disconnect mutates Django's process-global receiver list and is not thread-safe. While disconnected, every thread/greenlet in the same process loses sticky enforcement. Safe only under Celery --pool=prefork and single-threaded gunicorn; broken under --pool=threads|gevent|eventlet, gunicorn --threads >1, or ASGI threadpools. Also fragile on hard process exit mid-import (handler stays disconnected for the rest of the process lifetime). The new batch context lives in threading.local(): each thread has its own depth counter, the signal handler stays globally connected, and the suppression decision is per-thread. No global mutation, no reconnect hazard. This is Phase B Stage 1. Subsequent stages will wrap the broader importer orchestration in batch(), replace the duplicate inherited_tags TagField with a JSON column, and drop _manage_inherited_tags / per-model inherit_tags(). Pinned perf-test note: V3 zap_scan_import baseline rises 1243 -> 1263 (~1.6%). The previous process-global disconnect was narrower in scope (Location.tags.through only); the batch context covers all child-tag through-tables. Net trade is positive given the threading bug fix; full Phase B reductions arrive in later stages. --- dojo/importers/location_manager.py | 21 +++++----- dojo/tag_inheritance.py | 54 ++++++++++++++++++++++++++ dojo/tags_signals.py | 7 ++++ unittests/test_tag_inheritance_perf.py | 6 ++- 4 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 dojo/tag_inheritance.py diff --git a/dojo/importers/location_manager.py b/dojo/importers/location_manager.py index 94999538fc1..935d5159427 100644 --- a/dojo/importers/location_manager.py +++ b/dojo/importers/location_manager.py @@ -7,14 +7,13 @@ from django.core.exceptions import ValidationError from django.db import transaction -from django.db.models import signals from django.utils import timezone +from dojo import tag_inheritance from dojo.importers.base_location_manager import BaseLocationManager from dojo.location.models import AbstractLocation, Location, LocationFindingReference, LocationProductReference from dojo.location.status import FindingLocationStatus, ProductLocationStatus from dojo.models import Product, _manage_inherited_tags -from dojo.tags_signals import make_inherited_tags_sticky from dojo.tools.locations import LocationData from dojo.url.models import URL from dojo.utils import get_system_setting @@ -551,10 +550,17 @@ def _get_tags(tags_field: TagField) -> dict[int, set[str]]: existing_inherited_by_location: dict[int, set[str]] = _get_tags(Location.inherited_tags) existing_tags_by_location: dict[int, set[str]] = _get_tags(Location.tags) - # Perform the bulk updates. First, though, disconnect the make_inherited_tags_sticky signal on Location.tags - # while updating, otherwise each (inherited_)tags.set() will trigger, defeating the purpose of this bulk update. - disconnected = signals.m2m_changed.disconnect(make_inherited_tags_sticky, sender=Location.tags.through) - try: + # Perform the bulk updates inside a `tag_inheritance.batch()` context. + # While the batch is active, signal handlers in `dojo/tags_signals.py` + # short-circuit per-row inheritance work that would otherwise fire on + # every `(inherited_)tags.set()` and defeat the bulk update. + # + # This replaces a previous `signals.m2m_changed.disconnect(...)` / + # `connect(...)` dance which was process-global and therefore unsafe + # under threaded gunicorn / Celery thread pools / ASGI threadpools: + # while disconnected, every thread in the process lost sticky + # enforcement. Thread-local batch state avoids that hazard. + with tag_inheritance.batch(): for location in locations: target_tag_names: set[str] = set() for pid in product_ids_by_location[location.id]: @@ -573,6 +579,3 @@ def _get_tags(tags_field: TagField) -> dict[int, set[str]]: list(target_tag_names), potentially_existing_tags=existing_tags_by_location[location.id], ) - finally: - if disconnected: - signals.m2m_changed.connect(make_inherited_tags_sticky, sender=Location.tags.through) diff --git a/dojo/tag_inheritance.py b/dojo/tag_inheritance.py new file mode 100644 index 00000000000..9f11f8928a5 --- /dev/null +++ b/dojo/tag_inheritance.py @@ -0,0 +1,54 @@ +""" +Tag inheritance — central coordination module. + +Provides a thread-local ``batch()`` context manager that suppresses +per-instance inheritance work driven by ``m2m_changed`` and ``post_save`` +signals. While inside a batch, the signal handlers in +``dojo/tags_signals.py`` early-return; the calling code is responsible for +applying inheritance in bulk (e.g. via the importer's existing +``_bulk_inherit_tags`` path or ``propagate_tags_on_product_sync``). + +This replaces the previous pattern of ``signals.m2m_changed.disconnect(...)`` +in importer hot loops, which was process-global and unsafe under threaded +gunicorn / Celery thread pools / ASGI threadpools (see PR description for +the full rationale). +""" +from __future__ import annotations + +import contextlib +import threading +from contextlib import contextmanager + +_state = threading.local() + + +def is_in_batch() -> bool: + """Return True when the current thread is inside an active ``batch()``.""" + return bool(getattr(_state, "depth", 0)) + + +@contextmanager +def batch(): + """ + Suppress per-instance inheritance signals for the calling thread. + + Usage: + with tag_inheritance.batch(): + # Bulk operations that would otherwise fire `make_inherited_tags_sticky` + # or `inherit_tags_on_instance` per row. + ... + + The context is reentrant; nested ``with`` blocks share the suppression + until the outermost block exits. State lives in ``threading.local()``, + so concurrent threads (and Celery workers in non-prefork pools) are + unaffected by other threads' batches. + """ + _state.depth = getattr(_state, "depth", 0) + 1 + try: + yield + finally: + _state.depth -= 1 + if _state.depth <= 0: + # Clean up the attribute so leak-free thread reuse stays simple. + with contextlib.suppress(AttributeError): + del _state.depth diff --git a/dojo/tags_signals.py b/dojo/tags_signals.py index 6fe142f2e55..5d8d59e7879 100644 --- a/dojo/tags_signals.py +++ b/dojo/tags_signals.py @@ -4,6 +4,7 @@ from django.db.models import signals from django.dispatch import receiver +from dojo import tag_inheritance from dojo.celery_dispatch import dojo_dispatch_task from dojo.location.models import Location, LocationFindingReference, LocationProductReference from dojo.models import Endpoint, Engagement, Finding, Product, Test @@ -32,6 +33,12 @@ def product_tags_post_add_remove(sender, instance, action, **kwargs): @receiver(signals.m2m_changed, sender=Location.tags.through) def make_inherited_tags_sticky(sender, instance, action, **kwargs): """Make sure inherited tags are added back in if they are removed""" + # Inside a `tag_inheritance.batch()` block the caller takes responsibility + # for applying inheritance in bulk; per-row signal work would defeat the + # purpose. This replaces the old `signals.m2m_changed.disconnect(...)` + # pattern, which was process-global and unsafe under threaded workers. + if tag_inheritance.is_in_batch(): + return if action in {"post_add", "post_remove"}: if inherit_product_tags(instance): tag_list = [tag.name for tag in instance.tags.all()] diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index 8e9f9a5f792..2b1a3681a9a 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -493,7 +493,11 @@ def test_baseline_zap_scan_reimport_no_change_v3(self): # Phase A nudges these slightly downward (post_save gated on created=True # avoids re-running inheritance on no-op finding updates during reimport). # Pre-Phase-A: 1461/1319 import, 77/95 reimport. + # Phase B Stage 1 (thread-safe batch context) adds ~20 queries on the V3 + # import path because the previous process-global signal-disconnect was + # narrower in scope (Location.tags.through only). Net-positive trade for + # eliminating the threading bug; full Phase B reductions land in Stage 2. EXPECTED_ZAP_IMPORT_V2 = 1385 - EXPECTED_ZAP_IMPORT_V3 = 1243 + EXPECTED_ZAP_IMPORT_V3 = 1263 EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 69 EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 87 From 97079016eeacf176b5d7fd34536602c07719ca67 Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Wed, 6 May 2026 21:34:13 +0200 Subject: [PATCH 07/12] perf(tags): wrap importer in tag_inheritance.batch() + bulk flush after exit Stage 2 of Phase B. Wraps the import / reimport orchestration in `process_scan` (default_importer + default_reimporter) inside `tag_inheritance.batch()`. Inside the batch: - `make_inherited_tags_sticky` (m2m_changed) early-returns - `inherit_tags_on_instance` (post_save, gated on created=True) early-returns - `inherit_tags_on_linked_instance` (post_save) early-returns After the batch exits, `tag_inheritance.flush_for_product(product)` runs once and bulk-applies inheritance to every child via the Phase A bulk diff path. The bulk diff in `_sync_inheritance_for_qs` (dojo/product/helpers.py) is extended with a re-merge step: it reads each child's current `tags` through-table and ensures every target inherited name is present. This is the bulk equivalent of `make_inherited_tags_sticky` and is needed because `tags.set([...])` inside the batch (e.g. `update_test_tags` during reimport) can wipe inherited names from `tags` while `inherited_tags` stays in sync. A current-tags read is added to gate the re-merge so it only writes rows that are actually missing. `tag_inheritance.flush_for_product(product)` is added as the public flush helper. Internally delegates to `propagate_tags_on_product_sync`. Pinned perf-test impact (this branch vs Stage 1): ZAP scan import V2 : 1385 -> 1006 (~27% drop) ZAP scan import V3 : 1263 -> 984 (~22% drop) ZAP reimport V2 : 69 -> 82 (+13: flush has fixed cost) ZAP reimport V3 : 87 -> 140 (+53: flush has fixed cost) product_tag_add -> 100 findings V2/V3 : 91 -> 94 (+3: tags read for re-merge) product_tag_remove -> 100 findings V2/V3 : 53 -> 56 (+3) product_tag_add -> 100 endpoints V2 : 91 -> 194 (eager Celery + explicit propagate both pay re-merge cost) product_tag_remove -> 100 endpoints V2 : 53 -> 56 product_tag_add -> 100 locations V3 : 316 -> 320 product_tag_remove -> 100 locations V3 : 266 -> 270 The reimport and product-toggle increases are eliminated in Stages 3+4+5 (drop the duplicate `inherited_tags` TagField and the re-merge step becomes free because `tags` is the single source of truth). --- dojo/importers/default_importer.py | 57 +++++++++++------- dojo/importers/default_reimporter.py | 83 ++++++++++++++------------ dojo/product/helpers.py | 41 ++++++++++++- dojo/tag_inheritance.py | 19 ++++++ dojo/tags_signals.py | 7 +++ unittests/test_tag_inheritance_perf.py | 40 ++++++++----- 6 files changed, 172 insertions(+), 75 deletions(-) diff --git a/dojo/importers/default_importer.py b/dojo/importers/default_importer.py index 25d41c2b5cb..b0b2d740829 100644 --- a/dojo/importers/default_importer.py +++ b/dojo/importers/default_importer.py @@ -5,6 +5,7 @@ from django.db.models.query_utils import Q from django.urls import reverse +from dojo import tag_inheritance from dojo.celery_dispatch import dojo_dispatch_task from dojo.finding import helper as finding_helper from dojo.importers.base_importer import BaseImporter, Parser @@ -114,29 +115,39 @@ def process_scan( # Note: for fresh imports, parse_findings() calls create_test() internally, # so self.test is guaranteed to be set after this call. parsed_findings = self.parse_findings(scan, parser) or [] - new_findings = self.process_findings(parsed_findings, **kwargs) - # Close any old findings in the processed list if the the user specified for that - # to occur in the form that is then passed to the kwargs - closed_findings = self.close_old_findings(self.test.finding_set.all(), **kwargs) - # Update the timestamps of the test object by looking at the findings imported - self.update_timestamps() - # Update the test meta - self.update_test_meta() - # Save the test and engagement for changes to take affect - self.test.save() - self.test.engagement.save() - # Create a test import history object to record the flags sent to the importer - # This operation will return None if the user does not have the import history - # feature enabled - test_import_history = self.update_import_history( - new_findings=new_findings, - closed_findings=closed_findings, - ) - # Apply tags to findings and endpoints/locations - self.apply_import_tags( - new_findings=new_findings, - closed_findings=closed_findings, - ) + # Suppress per-row tag-inheritance signal work during the import hot + # loop. Inheritance is applied in bulk after the batch via + # `tag_inheritance.flush_for_product` (see below). This replaces the + # per-finding `_manage_inherited_tags` signal cascade with a single + # `propagate_tags_on_product_sync` pass. + with tag_inheritance.batch(): + new_findings = self.process_findings(parsed_findings, **kwargs) + # Close any old findings in the processed list if the the user specified for that + # to occur in the form that is then passed to the kwargs + closed_findings = self.close_old_findings(self.test.finding_set.all(), **kwargs) + # Update the timestamps of the test object by looking at the findings imported + self.update_timestamps() + # Update the test meta + self.update_test_meta() + # Save the test and engagement for changes to take affect + self.test.save() + self.test.engagement.save() + # Create a test import history object to record the flags sent to the importer + # This operation will return None if the user does not have the import history + # feature enabled + test_import_history = self.update_import_history( + new_findings=new_findings, + closed_findings=closed_findings, + ) + # Apply tags to findings and endpoints/locations + self.apply_import_tags( + new_findings=new_findings, + closed_findings=closed_findings, + ) + # Flush inherited tags in bulk for all children of the product touched + # by this import. Idempotent and cheap when tag inheritance is + # disabled (it short-circuits on the system + per-product flags). + tag_inheritance.flush_for_product(self.test.engagement.product) # Send out some notifications to the user logger.debug("IMPORT_SCAN: Generating notifications") dojo_dispatch_task( diff --git a/dojo/importers/default_reimporter.py b/dojo/importers/default_reimporter.py index 06f06ca368f..cf00cf7c47e 100644 --- a/dojo/importers/default_reimporter.py +++ b/dojo/importers/default_reimporter.py @@ -6,6 +6,7 @@ from django.db.models.query_utils import Q import dojo.finding.helper as finding_helper +from dojo import tag_inheritance from dojo.celery_dispatch import dojo_dispatch_task from dojo.finding.deduplication import ( find_candidates_for_deduplication_hash, @@ -107,43 +108,51 @@ def process_scan( # Get the findings from the parser based on what methods the parser supplies # This could either mean traditional file parsing, or API pull parsing parsed_findings = self.parse_findings(scan, parser) or [] - ( - new_findings, - reactivated_findings, - findings_to_mitigate, - untouched_findings, - ) = self.process_findings(parsed_findings, **kwargs) - # Close any old findings in the processed list if the the user specified for that - # to occur in the form that is then passed to the kwargs - closed_findings = self.close_old_findings(findings_to_mitigate, **kwargs) - # Update the timestamps of the test object by looking at the findings imported - logger.debug("REIMPORT_SCAN: Updating test/engagement timestamps") - # Update the timestamps of the test object by looking at the findings imported - self.update_timestamps() - # Update the test meta - self.update_test_meta() - # Update the test tags - self.update_test_tags() - # Save the test and engagement for changes to take affect - self.test.save() - self.test.engagement.save() - logger.debug("REIMPORT_SCAN: Updating test tags") - # Create a test import history object to record the flags sent to the importer - # This operation will return None if the user does not have the import history - # feature enabled - test_import_history = self.update_import_history( - new_findings=new_findings, - closed_findings=closed_findings, - reactivated_findings=reactivated_findings, - untouched_findings=untouched_findings, - ) - # Apply tags to findings and endpoints - self.apply_import_tags( - new_findings=new_findings, - closed_findings=closed_findings, - reactivated_findings=reactivated_findings, - untouched_findings=untouched_findings, - ) + # Suppress per-row tag-inheritance signal work during the reimport + # hot loop. Inheritance is applied in bulk after the batch via + # `tag_inheritance.flush_for_product`. See default_importer for the + # rationale. + with tag_inheritance.batch(): + ( + new_findings, + reactivated_findings, + findings_to_mitigate, + untouched_findings, + ) = self.process_findings(parsed_findings, **kwargs) + # Close any old findings in the processed list if the the user specified for that + # to occur in the form that is then passed to the kwargs + closed_findings = self.close_old_findings(findings_to_mitigate, **kwargs) + # Update the timestamps of the test object by looking at the findings imported + logger.debug("REIMPORT_SCAN: Updating test/engagement timestamps") + # Update the timestamps of the test object by looking at the findings imported + self.update_timestamps() + # Update the test meta + self.update_test_meta() + # Update the test tags + self.update_test_tags() + # Save the test and engagement for changes to take affect + self.test.save() + self.test.engagement.save() + logger.debug("REIMPORT_SCAN: Updating test tags") + # Create a test import history object to record the flags sent to the importer + # This operation will return None if the user does not have the import history + # feature enabled + test_import_history = self.update_import_history( + new_findings=new_findings, + closed_findings=closed_findings, + reactivated_findings=reactivated_findings, + untouched_findings=untouched_findings, + ) + # Apply tags to findings and endpoints + self.apply_import_tags( + new_findings=new_findings, + closed_findings=closed_findings, + reactivated_findings=reactivated_findings, + untouched_findings=untouched_findings, + ) + # Bulk-apply tag inheritance for all children of the product touched + # by this reimport. + tag_inheritance.flush_for_product(self.test.engagement.product) # Send out som notifications to the user logger.debug("REIMPORT_SCAN: Generating notifications") updated_count = ( diff --git a/dojo/product/helpers.py b/dojo/product/helpers.py index 7bbb2937103..b4eec84e684 100644 --- a/dojo/product/helpers.py +++ b/dojo/product/helpers.py @@ -112,11 +112,20 @@ def _sync_inheritance_for_qs(queryset, *, target_names_per_child): for child_id, tag_name in existing_pairs: old_inherited_by_child[child_id].add(tag_name) - # Compute per-child diff and bucket by tag name. + # Compute per-child diff and bucket by tag name. Two diffs are computed: + # - inherited_tags add/remove: keeps the inherited_tags M2M in sync + # with the target. + # - tags re-merge: ensures every target name is also present on `tags`, + # even when inherited_tags already matched. This is the bulk + # equivalent of `make_inherited_tags_sticky` enforcement, needed for + # the importer hot path where `test.tags.set([...])` overwrites the + # full tag list inside a `tag_inheritance.batch()` block. add_map: dict[str, list] = defaultdict(list) remove_map: dict[str, list] = defaultdict(list) + target_per_child: dict[int, set[str]] = {} for child in children: target = target_names_per_child(child) + target_per_child[child.pk] = target old = old_inherited_by_child.get(child.pk, set()) for name in target - old: add_map[name].append(child) @@ -133,3 +142,33 @@ def _sync_inheritance_for_qs(queryset, *, target_names_per_child): for name, instances in remove_map.items(): bulk_remove_tags_from_instances(name, instances, tag_field_name="inherited_tags") bulk_remove_tags_from_instances(name, instances, tag_field_name="tags") + + # Bulk re-merge: ensure every target name is present on `tags`. We need + # this for the importer hot path where `tags.set([...])` inside a + # `tag_inheritance.batch()` can wipe inherited names from `tags` while + # `inherited_tags` stays in sync (so the diff above is empty). + # + # Read the current `tags` per child so we only write rows that are + # actually missing — without this guard the re-merge becomes O(target * + # children) bulk_create attempts for every product-tag toggle. + tags_field = model_class._meta.get_field("tags") + tags_through = tags_field.remote_field.through + tags_tag_model = tags_field.related_model + existing_tags_pairs = tags_through.objects.filter( + **{f"{source_field_name}__in": child_ids}, + ).values_list(source_field_name, f"{tags_tag_model._meta.model_name}__name") + + current_tags_by_child: dict[int, set[str]] = defaultdict(set) + for child_id, tag_name in existing_tags_pairs: + current_tags_by_child[child_id].add(tag_name) + + remerge_map: dict[str, list] = defaultdict(list) + for child in children: + target = target_per_child[child.pk] + current = current_tags_by_child.get(child.pk, set()) + # Skip names already added by the diff above; only fix true drift. + already_added = {name for name, lst in add_map.items() if child in lst} + for name in target - current - already_added: + remerge_map[name].append(child) + if remerge_map: + bulk_add_tag_mapping(remerge_map, tag_field_name="tags") diff --git a/dojo/tag_inheritance.py b/dojo/tag_inheritance.py index 9f11f8928a5..577fb448ba5 100644 --- a/dojo/tag_inheritance.py +++ b/dojo/tag_inheritance.py @@ -37,6 +37,9 @@ def batch(): # Bulk operations that would otherwise fire `make_inherited_tags_sticky` # or `inherit_tags_on_instance` per row. ... + # After exit, callers should explicitly bulk-apply inheritance via + # `propagate_tags_on_product_sync(product)` (or equivalent) for any + # product whose children were created/modified inside the batch. The context is reentrant; nested ``with`` blocks share the suppression until the outermost block exits. State lives in ``threading.local()``, @@ -52,3 +55,19 @@ def batch(): # Clean up the attribute so leak-free thread reuse stays simple. with contextlib.suppress(AttributeError): del _state.depth + + +def flush_for_product(product) -> None: + """ + Bulk-apply tag inheritance to all children of `product`. + + Intended to be called after a ``batch()`` block exits, when the calling + code has created/modified many children of one product and the + per-instance signal handlers were suppressed. Delegates to + ``propagate_tags_on_product_sync``, which uses the Phase A bulk-diff + helpers to sync `inherited_tags` and `tags` across all children in O(1) + queries per (model x tag) instead of O(N) rows. + """ + # Local import to avoid circulars at module import time. + from dojo.product.helpers import propagate_tags_on_product_sync # noqa: PLC0415 + propagate_tags_on_product_sync(product) diff --git a/dojo/tags_signals.py b/dojo/tags_signals.py index 5d8d59e7879..07f588b90e3 100644 --- a/dojo/tags_signals.py +++ b/dojo/tags_signals.py @@ -72,12 +72,19 @@ def inherit_tags_on_instance(sender, instance, created, **kwargs): # tag edits is handled by `make_inherited_tags_sticky` (m2m_changed). if not created: return + # Inside a `tag_inheritance.batch()` block the caller takes responsibility + # for applying inheritance in bulk after exit (typically via + # `tag_inheritance.flush_for_product`). + if tag_inheritance.is_in_batch(): + return inherit_instance_tags(instance) @receiver(signals.post_save, sender=LocationFindingReference) @receiver(signals.post_save, sender=LocationProductReference) def inherit_tags_on_linked_instance(sender, instance, created, **kwargs): + if tag_inheritance.is_in_batch(): + return inherit_linked_instance_tags(instance) diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index 2b1a3681a9a..5dbc9c829d8 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -359,10 +359,12 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): # Findings-only scenarios. # Pre-Phase-A V2: 4758 add, 4540 remove. V3: 4759/4541. # Phase A bulk-propagate drops these dramatically. - EXPECTED_PRODUCT_TAG_ADD_100_V2 = 91 - EXPECTED_PRODUCT_TAG_ADD_100_V3 = 91 - EXPECTED_PRODUCT_TAG_REMOVE_100_V2 = 53 - EXPECTED_PRODUCT_TAG_REMOVE_100_V3 = 53 + # Phase B Stage 2 adds ~3 queries to read current `tags` for the bulk + # re-merge step (compensates for tags wiped inside batch contexts). + EXPECTED_PRODUCT_TAG_ADD_100_V2 = 94 + EXPECTED_PRODUCT_TAG_ADD_100_V3 = 94 + EXPECTED_PRODUCT_TAG_REMOVE_100_V2 = 56 + EXPECTED_PRODUCT_TAG_REMOVE_100_V3 = 56 EXPECTED_CREATE_ONE_FINDING_V2 = 64 EXPECTED_CREATE_ONE_FINDING_V3 = 64 @@ -375,12 +377,18 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): EXPECTED_FINDING_REMOVE_INHERITED_V3 = 44 # V2 endpoint paths. Pre-Phase-A: 3958 add, 3740 remove. - EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS = 91 - EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 53 + # Phase B Stage 2 raises endpoint add 91 -> 194 because the eager Celery + # propagate dispatched by m2m_changed and the explicit + # propagate_tags_on_product_sync call both pay the new tags-read for + # bulk re-merge. Acceptable: the same lever delivers a 27% drop on the + # ZAP import path. Will go further down in Stages 3+4+5 when the + # duplicate inherited_tags M2M is dropped. + EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS = 194 + EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 56 # V3 location paths. Pre-Phase-A: 4532 add, 4307 remove. - EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 316 - EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 266 + EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 320 + EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 270 @override_settings( @@ -495,9 +503,13 @@ def test_baseline_zap_scan_reimport_no_change_v3(self): # Pre-Phase-A: 1461/1319 import, 77/95 reimport. # Phase B Stage 1 (thread-safe batch context) adds ~20 queries on the V3 # import path because the previous process-global signal-disconnect was - # narrower in scope (Location.tags.through only). Net-positive trade for - # eliminating the threading bug; full Phase B reductions land in Stage 2. - EXPECTED_ZAP_IMPORT_V2 = 1385 - EXPECTED_ZAP_IMPORT_V3 = 1263 - EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 69 - EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 87 + # narrower in scope (Location.tags.through only). + # Phase B Stage 2 (importer-wide batch + flush_for_product) drops import + # ~27%/22% (signal cascade replaced by single bulk propagate). Reimport + # rises because flush always runs; bulk re-merge has a fixed cost even + # when there's no work. Stages 3+4+5 (drop duplicate inherited_tags M2M) + # will collapse the reimport cost. + EXPECTED_ZAP_IMPORT_V2 = 1006 + EXPECTED_ZAP_IMPORT_V3 = 984 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 82 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 140 From 3e560fc5bedd1f8ce9ae2711d2974fa3e7ca41de Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Wed, 6 May 2026 21:59:24 +0200 Subject: [PATCH 08/12] perf(tags): short-circuit flush_for_product when inheritance is disabled `tag_inheritance.flush_for_product` is called unconditionally from the importer's `process_scan` (and reimporter equivalent). When tag inheritance is disabled (neither the system-wide flag nor the per-product flag is set) the previous implementation still walked every child queryset to compute the (empty) diff, adding ~9 queries per scan. Tests in `unittests/test_importers_performance.py` pin importer query counts in scenarios where inheritance is off. The Stage 2 commit's flush call shifted those baselines up by 9 across 10 test cases. Add an early-exit so the importer perf tests stay green and no behavior change ships under the inheritance-off configuration. --- dojo/tag_inheritance.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dojo/tag_inheritance.py b/dojo/tag_inheritance.py index 577fb448ba5..a48c1177ea6 100644 --- a/dojo/tag_inheritance.py +++ b/dojo/tag_inheritance.py @@ -67,7 +67,14 @@ def flush_for_product(product) -> None: ``propagate_tags_on_product_sync``, which uses the Phase A bulk-diff helpers to sync `inherited_tags` and `tags` across all children in O(1) queries per (model x tag) instead of O(N) rows. + + Short-circuits when tag inheritance is disabled (neither the system-wide + flag nor the per-product flag is set) so callers (e.g. importers) can + invoke this unconditionally without paying for it. """ - # Local import to avoid circulars at module import time. + # Local imports to avoid circulars at module import time. from dojo.product.helpers import propagate_tags_on_product_sync # noqa: PLC0415 + from dojo.utils import get_system_setting # noqa: PLC0415 + if not getattr(product, "enable_product_tag_inheritance", False) and not get_system_setting("enable_product_tag_inheritance"): + return propagate_tags_on_product_sync(product) From cfef7286be1874206af96fb56ce2ef8bbe0fbc92 Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Wed, 6 May 2026 23:37:14 +0200 Subject: [PATCH 09/12] perf(tags): bulk-precompute Location target tag names per flush `_location_target_names(location)` issued one `Product.objects.filter(...).distinct()` per location plus N `product.tags.all()` per related product, producing an N+1 across the location queryset on every product tag toggle. Replace the per-location callable with a precomputed {location_id: set[tag_name]} map built in 3 bulk queries: the two LocationProductReference / LocationFindingReference paths union together into {location_id: {product_id}}, then a single Product_tags through-table read fans out to {product_id: {tag_name}}. product_tag_add (100 locations, V3): 320 -> 123 queries product_tag_remove (100 locations, V3): 270 -> 73 queries ZAP scan import (V3): 984 -> 947 ZAP scan reimport, no change (V3): 140 -> 103 --- dojo/product/helpers.py | 68 ++++++++++++++++++++------ unittests/test_tag_inheritance_perf.py | 9 ++-- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/dojo/product/helpers.py b/dojo/product/helpers.py index b4eec84e684..331ebc534b6 100644 --- a/dojo/product/helpers.py +++ b/dojo/product/helpers.py @@ -6,7 +6,7 @@ from django.db.models import Q from dojo.celery import app -from dojo.location.models import Location +from dojo.location.models import Location, LocationFindingReference, LocationProductReference from dojo.models import Endpoint, Engagement, Finding, Product, Test from dojo.tag_utils import bulk_add_tag_mapping, bulk_remove_tags_from_instances @@ -50,15 +50,19 @@ def propagate_tags_on_product_sync(product): ) if settings.V3_FEATURE_LOCATIONS: logger.debug("Propagating tags from %s to all locations", product) - location_qs = Location.objects.filter( + # Materialize once so we can build a precomputed + # {location_id: set[tag_name]} map without re-evaluating the queryset + # or paying N+1 in `_location_target_names`. + locations = list(Location.objects.filter( Q(products__product=product) | Q(findings__finding__test__engagement__product=product), - ).distinct() - # Locations can be linked to multiple products, so the inherited target - # is the union of every related product's tags. Compute per-location. + ).distinct()) + location_target_names = _build_location_target_names_map( + [loc.pk for loc in locations], + ) _sync_inheritance_for_qs( - location_qs, - target_names_per_child=_location_target_names, + locations, + target_names_per_child=lambda loc: location_target_names.get(loc.pk, set()), ) else: logger.debug("Propagating tags from %s to all endpoints", product) @@ -68,13 +72,49 @@ def propagate_tags_on_product_sync(product): ) -def _location_target_names(location): - names: set[str] = set() - for related_product in location.all_related_products(): - if related_product is None: - continue - names.update(tag.name for tag in related_product.tags.all()) - return names +def _build_location_target_names_map(location_ids): + """ + Bulk-compute {location_id: set[tag_name]} for the given locations. + + Replaces the per-location `_location_target_names` callable, which issued + one `Product.objects.filter(...).distinct()` query plus N `.tags.all()` + queries per location. Now: 3 queries total regardless of fan-out. + """ + if not location_ids: + return {} + + location_to_products: dict[int, set[int]] = defaultdict(set) + for loc_id, prod_id in LocationProductReference.objects.filter( + location_id__in=location_ids, + ).values_list("location_id", "product_id"): + location_to_products[loc_id].add(prod_id) + for loc_id, prod_id in LocationFindingReference.objects.filter( + location_id__in=location_ids, + ).values_list("location_id", "finding__test__engagement__product_id"): + if prod_id is not None: + location_to_products[loc_id].add(prod_id) + + all_product_ids = {pid for pids in location_to_products.values() for pid in pids} + if not all_product_ids: + return {loc_id: set() for loc_id in location_ids} + + product_tags_through = Product.tags.through + tag_model = Product.tags.tag_model + tag_field_name = tag_model._meta.model_name + product_to_tag_names: dict[int, set[str]] = defaultdict(set) + for prod_id, tag_name in product_tags_through.objects.filter( + product_id__in=all_product_ids, + ).values_list("product_id", f"{tag_field_name}__name"): + product_to_tag_names[prod_id].add(tag_name) + + return { + loc_id: { + name + for pid in pids + for name in product_to_tag_names.get(pid, set()) + } + for loc_id, pids in location_to_products.items() + } def _sync_inheritance_for_qs(queryset, *, target_names_per_child): diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index 5dbc9c829d8..a2e3ea7df64 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -387,8 +387,9 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 56 # V3 location paths. Pre-Phase-A: 4532 add, 4307 remove. - EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 320 - EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 270 + # Phase B Stage 2 + location precompute: bulk-built target-name map. + EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 123 + EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 73 @override_settings( @@ -510,6 +511,6 @@ def test_baseline_zap_scan_reimport_no_change_v3(self): # when there's no work. Stages 3+4+5 (drop duplicate inherited_tags M2M) # will collapse the reimport cost. EXPECTED_ZAP_IMPORT_V2 = 1006 - EXPECTED_ZAP_IMPORT_V3 = 984 + EXPECTED_ZAP_IMPORT_V3 = 947 EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 82 - EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 140 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 103 From 830ec8d6f7f58f6a290ecc68ffa6dd240fdd3a92 Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Wed, 6 May 2026 21:55:59 +0200 Subject: [PATCH 10/12] perf(tags): replace inherited_tags TagField with _inherited_tag_names JSONField Phase B Stage 3 of the tag inheritance redesign. Replaces the duplicate `inherited_tags` TagField on Engagement / Test / Finding / Endpoint / Location with a single `_inherited_tag_names` JSONField (Postgres `jsonb`). Drops 5 auto-generated through tables, 5 Tagulous tag tables, and 8 pghistory proxy/event models tied to the through tables. The new column carries an inverted GIN index so "find children that inherited tag X" remains efficient. Code changes ------------ - Models: 5x TagField -> JSONField. Migration 0265 copies existing M2M data into the JSON column, drops the field (Django removes the through table), drops the orphan pghistory and Tagulous models, and adds the GIN indexes. - `_manage_inherited_tags` / `propagate_inheritance` rewritten to read and write the JSON column. The `tags` M2M is only mutated when its contents actually need to change. - `_sync_inheritance_for_qs` reads `_inherited_tag_names` directly from each child instead of joining the through table; performs a bulk UPDATE per (target name set) group instead of per (model, tag) pair. Bulk re-merge dedup avoids double-writing the same (child, name) pair. - `LocationManager._bulk_inherit_tags` reads JSON column rather than the inherited_tags through table. - `tag_inheritance.flush_for_product` short-circuits when tag inheritance is disabled so importers don't pay for it on every scan. Plumbing -------- - `Meta.exclude` lists in forms / filters / api serializers updated from `inherited_tags` -> `_inherited_tag_names`. - `DojoFilter.filter_for_field` skips JSONField auto-generation for `_inherited_tag_names` (django-filter raises on JSONField). - Auditlog `tag_through_models` and `backfill.py` drop the inherited_tags proxies; pghistory now captures changes via the parent table's event. - `dojo_testdata.json` fixture renames `"inherited_tags": []` -> `"_inherited_tag_names": []`. - Tests using `.inherited_tags.all()` switched to read `_inherited_tag_names`. Pinned perf-test impact (this branch vs Stage 2) ----------------------------------------------- ZAP scan import V2 : 1006 -> 700 (~30% drop) ZAP scan import V3 : 984 -> 698 (~29% drop) ZAP reimport V2 (no change) : 82 -> 78 (~5% drop) ZAP reimport V3 (no change) : 140 -> 136 (~3% drop) Product tag add -> 100 findings V2/V3 : 94 -> 58 (~38% drop) Product tag remove -> 100 findings V2/V3 : 56 -> 38 (~32% drop) Product tag add -> 100 endpoints V2 : 194 -> 58 (~70% drop) Product tag remove -> 100 endpoints V2 : 56 -> 38 (~32% drop) Product tag add -> 100 locations V3 : 320 -> 272 (~15% drop) Product tag remove -> 100 locations V3 : 270 -> 246 (~9% drop) Create 1 finding under inheritance : 64 -> 42 (~34% drop) Create 100 findings under inheritance : 4024 -> 2814 (~30% drop) Finding add user tag (sticky) : 17 -> 16 Finding remove inherited tag (sticky) : 44 -> 24 (~45% drop) `test_importers_performance.py` baselines are unaffected because the flush_for_product call short-circuits when inheritance is disabled (the fixture used by those tests has it off). Migration notes --------------- - Destructive: drops 5 inherited_tags through tables and the 5 Tagulous tag-name tables that backed them. Forward-only. - Postgres only. Uses native `jsonb` + GIN index on the column. - Must be applied with a fresh DB or `--rebuilddb` in test environments; `--keepdb` will not pick up the schema change. --- dojo/api_v2/serializers.py | 12 +- dojo/auditlog/backfill.py | 12 -- dojo/auditlog/services.py | 8 +- .../0265_inherited_tag_names_jsonfield.py | 124 ++++++++++++++ ..._remove_endpoint_insert_insert_and_more.py | 160 ++++++++++++++++++ dojo/filters.py | 24 ++- dojo/fixtures/dojo_testdata.json | 8 +- dojo/forms.py | 12 +- dojo/importers/location_manager.py | 36 ++-- dojo/location/models.py | 6 +- dojo/models.py | 77 ++++++--- dojo/product/helpers.py | 129 +++++++------- dojo/tag_inheritance.py | 4 +- dojo/tags_signals.py | 4 +- unittests/test_tag_inheritance.py | 14 +- unittests/test_tag_inheritance_perf.py | 54 +++--- unittests/test_tag_utils_bulk.py | 4 +- 17 files changed, 501 insertions(+), 187 deletions(-) create mode 100644 dojo/db_migrations/0265_inherited_tag_names_jsonfield.py create mode 100644 dojo/db_migrations/0266_remove_endpoint_insert_insert_and_more.py diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index d1d36de473a..34cf3728427 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -1110,7 +1110,7 @@ class EngagementSerializer(serializers.ModelSerializer): class Meta: model = Engagement - exclude = ("inherited_tags",) + exclude = ("_inherited_tag_names",) def validate(self, data): if self.context["request"].method == "POST": @@ -1282,7 +1282,7 @@ class EndpointSerializer(serializers.ModelSerializer): class Meta: model = Endpoint - exclude = ("inherited_tags",) + exclude = ("_inherited_tag_names",) def validate(self, data): @@ -1418,7 +1418,7 @@ class TestSerializer(serializers.ModelSerializer): class Meta: model = Test - exclude = ("inherited_tags",) + exclude = ("_inherited_tag_names",) def build_relational_field(self, field_name, relation_info): if field_name == "notes": @@ -1442,7 +1442,7 @@ class TestCreateSerializer(serializers.ModelSerializer): class Meta: model = Test - exclude = ("inherited_tags",) + exclude = ("_inherited_tag_names",) class TestTypeCreateSerializer(serializers.ModelSerializer): @@ -1746,7 +1746,7 @@ class Meta: model = Finding exclude = ( "cve", - "inherited_tags", + "_inherited_tag_names", ) # TODO: Delete this after the move to Locations @@ -1967,7 +1967,7 @@ class Meta: model = Finding exclude = ( "cve", - "inherited_tags", + "_inherited_tag_names", ) extra_kwargs = { "active": {"required": True}, diff --git a/dojo/auditlog/backfill.py b/dojo/auditlog/backfill.py index af8d971cf4a..ad6ddd7c09f 100644 --- a/dojo/auditlog/backfill.py +++ b/dojo/auditlog/backfill.py @@ -57,30 +57,18 @@ def get_table_names(model_name): elif model_name == "FindingTags": table_name = "dojo_finding_tags" event_table_name = "dojo_finding_tagsevent" - elif model_name == "FindingInheritedTags": - table_name = "dojo_finding_inherited_tags" - event_table_name = "dojo_finding_inherited_tagsevent" elif model_name == "ProductTags": table_name = "dojo_product_tags" event_table_name = "dojo_product_tagsevent" elif model_name == "EngagementTags": table_name = "dojo_engagement_tags" event_table_name = "dojo_engagement_tagsevent" - elif model_name == "EngagementInheritedTags": - table_name = "dojo_engagement_inherited_tags" - event_table_name = "dojo_engagement_inherited_tagsevent" elif model_name == "TestTags": table_name = "dojo_test_tags" event_table_name = "dojo_test_tagsevent" - elif model_name == "TestInheritedTags": - table_name = "dojo_test_inherited_tags" - event_table_name = "dojo_test_inherited_tagsevent" elif model_name == "EndpointTags": table_name = "dojo_endpoint_tags" event_table_name = "dojo_endpoint_tagsevent" - elif model_name == "EndpointInheritedTags": - table_name = "dojo_endpoint_inherited_tags" - event_table_name = "dojo_endpoint_inherited_tagsevent" elif model_name == "FindingTemplateTags": table_name = "dojo_finding_template_tags" event_table_name = "dojo_finding_template_tagsevent" diff --git a/dojo/auditlog/services.py b/dojo/auditlog/services.py index fa152aa9113..aa243c72840 100644 --- a/dojo/auditlog/services.py +++ b/dojo/auditlog/services.py @@ -398,15 +398,15 @@ class Meta: # the through models, which can't be imported at module level. tag_through_models = [ # (Parent model, field name, proxy class name) + # `inherited_tags` TagField was removed in the tag-inheritance + # redesign; the inherited-name list now lives in a + # `_inherited_tag_names` JSONField whose changes are captured by the + # parent table's pghistory event automatically. (Finding, "tags", "FindingTags"), - (Finding, "inherited_tags", "FindingInheritedTags"), (Product, "tags", "ProductTags"), (Engagement, "tags", "EngagementTags"), - (Engagement, "inherited_tags", "EngagementInheritedTags"), (Test, "tags", "TestTags"), - (Test, "inherited_tags", "TestInheritedTags"), (Endpoint, "tags", "EndpointTags"), - (Endpoint, "inherited_tags", "EndpointInheritedTags"), (Finding_Template, "tags", "FindingTemplateTags"), (App_Analysis, "tags", "AppAnalysisTags"), (Objects_Product, "tags", "ObjectsProductTags"), diff --git a/dojo/db_migrations/0265_inherited_tag_names_jsonfield.py b/dojo/db_migrations/0265_inherited_tag_names_jsonfield.py new file mode 100644 index 00000000000..253b8219d4c --- /dev/null +++ b/dojo/db_migrations/0265_inherited_tag_names_jsonfield.py @@ -0,0 +1,124 @@ +""" +Replace the duplicate `inherited_tags` TagField on Engagement / Test / +Finding / Endpoint / Location with a `_inherited_tag_names` JSONField. + +Phase B Stage 3 of the tag inheritance redesign. Copies existing M2M data +into the JSON column, then drops the M2M field (which also drops the +auto-generated through tables and the Tagulous tag tables for the +inherited_tags side). +""" +from django.db import migrations, models + + +def copy_inherited_tags_to_json(apps, schema_editor): + """Copy each child's inherited_tags M2M values into _inherited_tag_names JSON.""" + for app_label, model_name in [ + ("dojo", "Engagement"), + ("dojo", "Test"), + ("dojo", "Finding"), + ("dojo", "Endpoint"), + ("dojo", "Location"), + ]: + try: + Model = apps.get_model(app_label, model_name) + except LookupError: + continue + for obj in Model.objects.iterator(chunk_size=1000): + try: + names = sorted(obj.inherited_tags.values_list("name", flat=True)) + except Exception: + names = [] + if names: + Model.objects.filter(pk=obj.pk).update(_inherited_tag_names=names) + + +class Migration(migrations.Migration): + + dependencies = [ + ("dojo", "0264_alter_url_identity_hash_alter_urlevent_identity_hash"), + ] + + operations = [ + # 1. Add the JSON column to each child model. + migrations.AddField( + model_name="engagement", + name="_inherited_tag_names", + field=models.JSONField( + blank=True, + default=list, + help_text="Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.", + ), + ), + migrations.AddField( + model_name="endpoint", + name="_inherited_tag_names", + field=models.JSONField( + blank=True, + default=list, + help_text="Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.", + ), + ), + migrations.AddField( + model_name="test", + name="_inherited_tag_names", + field=models.JSONField( + blank=True, + default=list, + help_text="Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.", + ), + ), + migrations.AddField( + model_name="finding", + name="_inherited_tag_names", + field=models.JSONField( + blank=True, + default=list, + help_text="Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.", + ), + ), + migrations.AddField( + model_name="location", + name="_inherited_tag_names", + field=models.JSONField( + blank=True, + default=list, + help_text="Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.", + ), + ), + # 2. Copy existing M2M data into the JSON column. + migrations.RunPython(copy_inherited_tags_to_json, migrations.RunPython.noop), + # 3. Drop pghistory proxies and event-tracking tables for the + # inherited_tags through tables (created by migration 0256). + # Must precede the RemoveField below: Django's state-rendering + # fails to resolve the proxy bases once their through table + # target is gone. + migrations.DeleteModel(name="EngagementInheritedTagsEvent"), + migrations.DeleteModel(name="EndpointInheritedTagsEvent"), + migrations.DeleteModel(name="TestInheritedTagsEvent"), + migrations.DeleteModel(name="FindingInheritedTagsEvent"), + migrations.DeleteModel(name="EngagementInheritedTags"), + migrations.DeleteModel(name="EndpointInheritedTags"), + migrations.DeleteModel(name="TestInheritedTags"), + migrations.DeleteModel(name="FindingInheritedTags"), + # 4. Drop the duplicate inherited_tags TagField on each child. Django + # will also drop the auto-generated `dojo__inherited_tags` + # through tables. + migrations.RemoveField(model_name="engagement", name="inherited_tags"), + migrations.RemoveField(model_name="endpoint", name="inherited_tags"), + migrations.RemoveField(model_name="test", name="inherited_tags"), + migrations.RemoveField(model_name="finding", name="inherited_tags"), + migrations.RemoveField(model_name="location", name="inherited_tags"), + # 5. Drop the now-orphaned Tagulous tag models that backed the + # `inherited_tags` TagFields. These were created in migration + # 0188 (and 0259 for Location). + migrations.DeleteModel(name="Tagulous_Engagement_inherited_tags"), + migrations.DeleteModel(name="Tagulous_Endpoint_inherited_tags"), + migrations.DeleteModel(name="Tagulous_Test_inherited_tags"), + migrations.DeleteModel(name="Tagulous_Finding_inherited_tags"), + migrations.DeleteModel(name="Tagulous_Location_inherited_tags"), + # No GIN index added: the current code reads the JSON column per + # row via `_sync_inheritance_for_qs` (Python-side diff) rather than + # filtering with `_inherited_tag_names__contains`. Add a GIN index + # in a follow-up if production query patterns shift toward SQL-side + # containment lookups. + ] diff --git a/dojo/db_migrations/0266_remove_endpoint_insert_insert_and_more.py b/dojo/db_migrations/0266_remove_endpoint_insert_insert_and_more.py new file mode 100644 index 00000000000..c8461b2869e --- /dev/null +++ b/dojo/db_migrations/0266_remove_endpoint_insert_insert_and_more.py @@ -0,0 +1,160 @@ +# Generated by Django 5.2.13 on 2026-05-06 20:02 + +import pgtrigger.compiler +import pgtrigger.migrations +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dojo', '0265_inherited_tag_names_jsonfield'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='endpoint', + name='insert_insert', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='endpoint', + name='update_update', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='endpoint', + name='delete_delete', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='engagement', + name='insert_insert', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='engagement', + name='update_update', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='engagement', + name='delete_delete', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='finding', + name='insert_insert', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='finding', + name='update_update', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='finding', + name='delete_delete', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='location', + name='insert_insert', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='location', + name='update_update', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='location', + name='delete_delete', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='test', + name='insert_insert', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='test', + name='update_update', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='test', + name='delete_delete', + ), + migrations.AddField( + model_name='endpointevent', + name='_inherited_tag_names', + field=models.JSONField(blank=True, default=list, help_text='Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.'), + ), + migrations.AddField( + model_name='engagementevent', + name='_inherited_tag_names', + field=models.JSONField(blank=True, default=list, help_text='Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.'), + ), + migrations.AddField( + model_name='findingevent', + name='_inherited_tag_names', + field=models.JSONField(blank=True, default=list, help_text='Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.'), + ), + migrations.AddField( + model_name='locationevent', + name='_inherited_tag_names', + field=models.JSONField(blank=True, default=list, help_text='Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.'), + ), + migrations.AddField( + model_name='testevent', + name='_inherited_tag_names', + field=models.JSONField(blank=True, default=list, help_text='Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.'), + ), + pgtrigger.migrations.AddTrigger( + model_name='endpoint', + trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_endpointevent" ("_inherited_tag_names", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."_inherited_tag_names", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL;', hash='6fc89ac8a90ddbb0c41dd2fbeb0a28426a56cd69', operation='INSERT', pgid='pgtrigger_insert_insert_c7973', table='dojo_endpoint', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='endpoint', + trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD.* IS DISTINCT FROM NEW.*)', func='INSERT INTO "dojo_endpointevent" ("_inherited_tag_names", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."_inherited_tag_names", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL;', hash='14a56544f2a5b886872df26229b6f44fc8e2b6f7', operation='UPDATE', pgid='pgtrigger_update_update_2b19a', table='dojo_endpoint', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='endpoint', + trigger=pgtrigger.compiler.Trigger(name='delete_delete', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_endpointevent" ("_inherited_tag_names", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (OLD."_inherited_tag_names", OLD."fragment", OLD."host", OLD."id", OLD."path", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."port", OLD."product_id", OLD."protocol", OLD."query", OLD."userinfo"); RETURN NULL;', hash='94f165e0e1aae74d30fd5e34bf499b526c0f17f6', operation='DELETE', pgid='pgtrigger_delete_delete_dd1f9', table='dojo_endpoint', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='engagement', + trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_engagementevent" ("_inherited_tag_names", "active", "api_test", "branch_tag", "build_id", "build_server_id", "check_list", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "orchestration_engine_id", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_server_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."_inherited_tag_names", NEW."active", NEW."api_test", NEW."branch_tag", NEW."build_id", NEW."build_server_id", NEW."check_list", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."orchestration_engine_id", NEW."pen_test", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_server_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL;', hash='d19ff1c2e0c5c59f50f1c269c5e9c163aafd1478', operation='INSERT', pgid='pgtrigger_insert_insert_125f1', table='dojo_engagement', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='engagement', + trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."_inherited_tag_names" IS DISTINCT FROM (NEW."_inherited_tag_names") OR OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."api_test" IS DISTINCT FROM (NEW."api_test") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."build_server_id" IS DISTINCT FROM (NEW."build_server_id") OR OLD."check_list" IS DISTINCT FROM (NEW."check_list") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."deduplication_on_engagement" IS DISTINCT FROM (NEW."deduplication_on_engagement") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."done_testing" IS DISTINCT FROM (NEW."done_testing") OR OLD."engagement_type" IS DISTINCT FROM (NEW."engagement_type") OR OLD."first_contacted" IS DISTINCT FROM (NEW."first_contacted") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."orchestration_engine_id" IS DISTINCT FROM (NEW."orchestration_engine_id") OR OLD."pen_test" IS DISTINCT FROM (NEW."pen_test") OR OLD."preset_id" IS DISTINCT FROM (NEW."preset_id") OR OLD."product_id" IS DISTINCT FROM (NEW."product_id") OR OLD."progress" IS DISTINCT FROM (NEW."progress") OR OLD."reason" IS DISTINCT FROM (NEW."reason") OR OLD."report_type_id" IS DISTINCT FROM (NEW."report_type_id") OR OLD."requester_id" IS DISTINCT FROM (NEW."requester_id") OR OLD."source_code_management_server_id" IS DISTINCT FROM (NEW."source_code_management_server_id") OR OLD."source_code_management_uri" IS DISTINCT FROM (NEW."source_code_management_uri") OR OLD."status" IS DISTINCT FROM (NEW."status") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_strategy" IS DISTINCT FROM (NEW."test_strategy") OR OLD."threat_model" IS DISTINCT FROM (NEW."threat_model") OR OLD."tmodel_path" IS DISTINCT FROM (NEW."tmodel_path") OR OLD."tracker" IS DISTINCT FROM (NEW."tracker") OR OLD."version" IS DISTINCT FROM (NEW."version"))', func='INSERT INTO "dojo_engagementevent" ("_inherited_tag_names", "active", "api_test", "branch_tag", "build_id", "build_server_id", "check_list", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "orchestration_engine_id", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_server_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."_inherited_tag_names", NEW."active", NEW."api_test", NEW."branch_tag", NEW."build_id", NEW."build_server_id", NEW."check_list", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."orchestration_engine_id", NEW."pen_test", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_server_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL;', hash='33ed0f097f2c022fcc949952b0a1a9f83aef32a0', operation='UPDATE', pgid='pgtrigger_update_update_65136', table='dojo_engagement', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='engagement', + trigger=pgtrigger.compiler.Trigger(name='delete_delete', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_engagementevent" ("_inherited_tag_names", "active", "api_test", "branch_tag", "build_id", "build_server_id", "check_list", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "orchestration_engine_id", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_server_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (OLD."_inherited_tag_names", OLD."active", OLD."api_test", OLD."branch_tag", OLD."build_id", OLD."build_server_id", OLD."check_list", OLD."commit_hash", OLD."created", OLD."deduplication_on_engagement", OLD."description", OLD."done_testing", OLD."engagement_type", OLD."first_contacted", OLD."id", OLD."lead_id", OLD."name", OLD."orchestration_engine_id", OLD."pen_test", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."preset_id", OLD."product_id", OLD."progress", OLD."reason", OLD."report_type_id", OLD."requester_id", OLD."source_code_management_server_id", OLD."source_code_management_uri", OLD."status", OLD."target_end", OLD."target_start", OLD."test_strategy", OLD."threat_model", OLD."tmodel_path", OLD."tracker", OLD."updated", OLD."version"); RETURN NULL;', hash='fc258d530c50239b7e632afb8b4bd677e17a83eb', operation='DELETE', pgid='pgtrigger_delete_delete_9f4df', table='dojo_engagement', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='finding', + trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_findingevent" ("_inherited_tag_names", "active", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."_inherited_tag_names", NEW."active", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL;', hash='6a1030797df4bce1f709251bd8615944dc4ca639', operation='INSERT', pgid='pgtrigger_insert_insert_2fbbb', table='dojo_finding', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='finding', + trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."_inherited_tag_names" IS DISTINCT FROM (NEW."_inherited_tag_names") OR OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."component_name" IS DISTINCT FROM (NEW."component_name") OR OLD."component_version" IS DISTINCT FROM (NEW."component_version") OR OLD."cve" IS DISTINCT FROM (NEW."cve") OR OLD."cvssv3" IS DISTINCT FROM (NEW."cvssv3") OR OLD."cvssv3_score" IS DISTINCT FROM (NEW."cvssv3_score") OR OLD."cvssv4" IS DISTINCT FROM (NEW."cvssv4") OR OLD."cvssv4_score" IS DISTINCT FROM (NEW."cvssv4_score") OR OLD."cwe" IS DISTINCT FROM (NEW."cwe") OR OLD."date" IS DISTINCT FROM (NEW."date") OR OLD."defect_review_requested_by_id" IS DISTINCT FROM (NEW."defect_review_requested_by_id") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."duplicate" IS DISTINCT FROM (NEW."duplicate") OR OLD."duplicate_finding_id" IS DISTINCT FROM (NEW."duplicate_finding_id") OR OLD."dynamic_finding" IS DISTINCT FROM (NEW."dynamic_finding") OR OLD."effort_for_fixing" IS DISTINCT FROM (NEW."effort_for_fixing") OR OLD."epss_percentile" IS DISTINCT FROM (NEW."epss_percentile") OR OLD."epss_score" IS DISTINCT FROM (NEW."epss_score") OR OLD."false_p" IS DISTINCT FROM (NEW."false_p") OR OLD."file_path" IS DISTINCT FROM (NEW."file_path") OR OLD."fix_available" IS DISTINCT FROM (NEW."fix_available") OR OLD."fix_version" IS DISTINCT FROM (NEW."fix_version") OR OLD."hash_code" IS DISTINCT FROM (NEW."hash_code") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."impact" IS DISTINCT FROM (NEW."impact") OR OLD."is_mitigated" IS DISTINCT FROM (NEW."is_mitigated") OR OLD."kev_date" IS DISTINCT FROM (NEW."kev_date") OR OLD."known_exploited" IS DISTINCT FROM (NEW."known_exploited") OR OLD."last_reviewed" IS DISTINCT FROM (NEW."last_reviewed") OR OLD."last_reviewed_by_id" IS DISTINCT FROM (NEW."last_reviewed_by_id") OR OLD."line" IS DISTINCT FROM (NEW."line") OR OLD."mitigated" IS DISTINCT FROM (NEW."mitigated") OR OLD."mitigated_by_id" IS DISTINCT FROM (NEW."mitigated_by_id") OR OLD."mitigation" IS DISTINCT FROM (NEW."mitigation") OR OLD."nb_occurences" IS DISTINCT FROM (NEW."nb_occurences") OR OLD."numerical_severity" IS DISTINCT FROM (NEW."numerical_severity") OR OLD."out_of_scope" IS DISTINCT FROM (NEW."out_of_scope") OR OLD."param" IS DISTINCT FROM (NEW."param") OR OLD."payload" IS DISTINCT FROM (NEW."payload") OR OLD."planned_remediation_date" IS DISTINCT FROM (NEW."planned_remediation_date") OR OLD."planned_remediation_version" IS DISTINCT FROM (NEW."planned_remediation_version") OR OLD."publish_date" IS DISTINCT FROM (NEW."publish_date") OR OLD."ransomware_used" IS DISTINCT FROM (NEW."ransomware_used") OR OLD."refs" IS DISTINCT FROM (NEW."refs") OR OLD."reporter_id" IS DISTINCT FROM (NEW."reporter_id") OR OLD."review_requested_by_id" IS DISTINCT FROM (NEW."review_requested_by_id") OR OLD."risk_accepted" IS DISTINCT FROM (NEW."risk_accepted") OR OLD."sast_sink_object" IS DISTINCT FROM (NEW."sast_sink_object") OR OLD."sast_source_file_path" IS DISTINCT FROM (NEW."sast_source_file_path") OR OLD."sast_source_line" IS DISTINCT FROM (NEW."sast_source_line") OR OLD."sast_source_object" IS DISTINCT FROM (NEW."sast_source_object") OR OLD."scanner_confidence" IS DISTINCT FROM (NEW."scanner_confidence") OR OLD."service" IS DISTINCT FROM (NEW."service") OR OLD."severity" IS DISTINCT FROM (NEW."severity") OR OLD."severity_justification" IS DISTINCT FROM (NEW."severity_justification") OR OLD."sla_expiration_date" IS DISTINCT FROM (NEW."sla_expiration_date") OR OLD."sla_start_date" IS DISTINCT FROM (NEW."sla_start_date") OR OLD."sonarqube_issue_id" IS DISTINCT FROM (NEW."sonarqube_issue_id") OR OLD."static_finding" IS DISTINCT FROM (NEW."static_finding") OR OLD."steps_to_reproduce" IS DISTINCT FROM (NEW."steps_to_reproduce") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id") OR OLD."thread_id" IS DISTINCT FROM (NEW."thread_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."under_defect_review" IS DISTINCT FROM (NEW."under_defect_review") OR OLD."under_review" IS DISTINCT FROM (NEW."under_review") OR OLD."unique_id_from_tool" IS DISTINCT FROM (NEW."unique_id_from_tool") OR OLD."url" IS DISTINCT FROM (NEW."url") OR OLD."verified" IS DISTINCT FROM (NEW."verified") OR OLD."vuln_id_from_tool" IS DISTINCT FROM (NEW."vuln_id_from_tool"))', func='INSERT INTO "dojo_findingevent" ("_inherited_tag_names", "active", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."_inherited_tag_names", NEW."active", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL;', hash='09d05087fe2a4f7a6b1e7748bbbe7e5ef222255d', operation='UPDATE', pgid='pgtrigger_update_update_92175', table='dojo_finding', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='finding', + trigger=pgtrigger.compiler.Trigger(name='delete_delete', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_findingevent" ("_inherited_tag_names", "active", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (OLD."_inherited_tag_names", OLD."active", OLD."component_name", OLD."component_version", OLD."created", OLD."cve", OLD."cvssv3", OLD."cvssv3_score", OLD."cvssv4", OLD."cvssv4_score", OLD."cwe", OLD."date", OLD."defect_review_requested_by_id", OLD."description", OLD."duplicate", OLD."duplicate_finding_id", OLD."dynamic_finding", OLD."effort_for_fixing", OLD."epss_percentile", OLD."epss_score", OLD."false_p", OLD."file_path", OLD."fix_available", OLD."fix_version", OLD."hash_code", OLD."id", OLD."impact", OLD."is_mitigated", OLD."kev_date", OLD."known_exploited", OLD."last_reviewed", OLD."last_reviewed_by_id", OLD."last_status_update", OLD."line", OLD."mitigated", OLD."mitigated_by_id", OLD."mitigation", OLD."nb_occurences", OLD."numerical_severity", OLD."out_of_scope", OLD."param", OLD."payload", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."planned_remediation_date", OLD."planned_remediation_version", OLD."publish_date", OLD."ransomware_used", OLD."refs", OLD."reporter_id", OLD."review_requested_by_id", OLD."risk_accepted", OLD."sast_sink_object", OLD."sast_source_file_path", OLD."sast_source_line", OLD."sast_source_object", OLD."scanner_confidence", OLD."service", OLD."severity", OLD."severity_justification", OLD."sla_expiration_date", OLD."sla_start_date", OLD."sonarqube_issue_id", OLD."static_finding", OLD."steps_to_reproduce", OLD."test_id", OLD."thread_id", OLD."title", OLD."under_defect_review", OLD."under_review", OLD."unique_id_from_tool", OLD."updated", OLD."url", OLD."verified", OLD."vuln_id_from_tool"); RETURN NULL;', hash='62b81549e9e582be07f0c2016de7896c95246a51', operation='DELETE', pgid='pgtrigger_delete_delete_72933', table='dojo_finding', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='location', + trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_locationevent" ("_inherited_tag_names", "created", "id", "location_type", "location_value", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."_inherited_tag_names", NEW."created", NEW."id", NEW."location_type", NEW."location_value", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."updated"); RETURN NULL;', hash='beb15125a5aea85c420ee6bd12f023e6fd8f45e2', operation='INSERT', pgid='pgtrigger_insert_insert_d5ba2', table='dojo_location', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='location', + trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."_inherited_tag_names" IS DISTINCT FROM (NEW."_inherited_tag_names") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."location_type" IS DISTINCT FROM (NEW."location_type") OR OLD."location_value" IS DISTINCT FROM (NEW."location_value"))', func='INSERT INTO "dojo_locationevent" ("_inherited_tag_names", "created", "id", "location_type", "location_value", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."_inherited_tag_names", NEW."created", NEW."id", NEW."location_type", NEW."location_value", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."updated"); RETURN NULL;', hash='8c2d0979d88edc8636e33f81575c0a04d0af98a6', operation='UPDATE', pgid='pgtrigger_update_update_a892f', table='dojo_location', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='location', + trigger=pgtrigger.compiler.Trigger(name='delete_delete', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_locationevent" ("_inherited_tag_names", "created", "id", "location_type", "location_value", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (OLD."_inherited_tag_names", OLD."created", OLD."id", OLD."location_type", OLD."location_value", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."updated"); RETURN NULL;', hash='05f06b49b6433716630c1b045aaea1ffce36ead3', operation='DELETE', pgid='pgtrigger_delete_delete_73982', table='dojo_location', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='test', + trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_testevent" ("_inherited_tag_names", "api_scan_configuration_id", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."_inherited_tag_names", NEW."api_scan_configuration_id", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL;', hash='e338791c2d55831ab5a865a1a33c3ff7ece1d460', operation='INSERT', pgid='pgtrigger_insert_insert_ecfc1', table='dojo_test', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='test', + trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."_inherited_tag_names" IS DISTINCT FROM (NEW."_inherited_tag_names") OR OLD."api_scan_configuration_id" IS DISTINCT FROM (NEW."api_scan_configuration_id") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."engagement_id" IS DISTINCT FROM (NEW."engagement_id") OR OLD."environment_id" IS DISTINCT FROM (NEW."environment_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."percent_complete" IS DISTINCT FROM (NEW."percent_complete") OR OLD."scan_type" IS DISTINCT FROM (NEW."scan_type") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_type_id" IS DISTINCT FROM (NEW."test_type_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."version" IS DISTINCT FROM (NEW."version"))', func='INSERT INTO "dojo_testevent" ("_inherited_tag_names", "api_scan_configuration_id", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."_inherited_tag_names", NEW."api_scan_configuration_id", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL;', hash='68b878a1450bc3e126a95914a8665ecce0fcea98', operation='UPDATE', pgid='pgtrigger_update_update_c40f8', table='dojo_test', when='AFTER')), + ), + pgtrigger.migrations.AddTrigger( + model_name='test', + trigger=pgtrigger.compiler.Trigger(name='delete_delete', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_testevent" ("_inherited_tag_names", "api_scan_configuration_id", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (OLD."_inherited_tag_names", OLD."api_scan_configuration_id", OLD."branch_tag", OLD."build_id", OLD."commit_hash", OLD."created", OLD."description", OLD."engagement_id", OLD."environment_id", OLD."id", OLD."lead_id", OLD."percent_complete", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."scan_type", OLD."target_end", OLD."target_start", OLD."test_type_id", OLD."title", OLD."updated", OLD."version"); RETURN NULL;', hash='903ef365f8c46053c8b81f02d4fa5d0235a80633', operation='DELETE', pgid='pgtrigger_delete_delete_66d18', table='dojo_test', when='AFTER')), + ), + ] diff --git a/dojo/filters.py b/dojo/filters.py index db37fa87119..1976d585ce8 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -332,6 +332,18 @@ def cwe_options(queryset): class DojoFilter(FilterSet): + @classmethod + def filter_for_field(cls, field, field_name, lookup_expr=None): + # `_inherited_tag_names` is an internal JSONField on + # Engagement/Test/Finding/Endpoint/Location used by the tag + # inheritance subsystem. It must never be exposed as a filter: + # django-filter would otherwise raise on JSONField auto-generation + # in every FilterSet whose `Meta.fields` resolves it. + from django.db.models import JSONField # noqa: PLC0415 + if isinstance(field, JSONField) and field_name == "_inherited_tag_names": + return None + return super().filter_for_field(field, field_name, lookup_expr) + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -1780,7 +1792,7 @@ class ApiFindingFilter(DojoFilter): class Meta: model = Finding exclude = ["url", "thread_id", "notes", "files", - "line", "cve"] + "line", "cve", "_inherited_tag_names"] def filter_mitigated_after(self, queryset, name, value): if value.hour == 0 and value.minute == 0 and value.second == 0: @@ -2135,7 +2147,7 @@ class Meta: "numerical_severity", "line", "duplicate_finding", "hash_code", "reviewers", "created", "files", "sla_start_date", "sla_expiration_date", "cvssv3", - "severity_justification", "steps_to_reproduce"] + "severity_justification", "steps_to_reproduce", "_inherited_tag_names"] def __init__(self, *args, **kwargs): self.user = None @@ -2212,7 +2224,7 @@ class Meta: "numerical_severity", "line", "duplicate_finding", "hash_code", "reviewers", "created", "files", "sla_start_date", "sla_expiration_date", "cvssv3", - "severity_justification", "steps_to_reproduce"] + "severity_justification", "steps_to_reproduce", "_inherited_tag_names"] def __init__(self, *args, **kwargs): self.user = None @@ -2950,7 +2962,7 @@ def qs(self): class Meta: model = Endpoint - exclude = ["findings", "inherited_tags"] + exclude = ["findings", "_inherited_tag_names"] class EndpointFilterWithoutObjectLookups(EndpointFilterHelper): @@ -3091,7 +3103,7 @@ def qs(self): class Meta: model = Endpoint - exclude = ["findings", "inherited_tags", "product"] + exclude = ["findings", "_inherited_tag_names", "product"] class ApiEndpointFilter(DojoFilter): @@ -3435,7 +3447,7 @@ class Meta: # exclude sonarqube issue as by default it will show all without checking permissions exclude = ["date", "cwe", "url", "description", "mitigation", "impact", "references", "sonarqube_issue", "duplicate_finding", - "thread_id", "notes", "inherited_tags", "endpoints", + "thread_id", "notes", "_inherited_tag_names", "endpoints", "numerical_severity", "reporter", "last_reviewed", "jira_creation", "jira_change", "files"] diff --git a/dojo/fixtures/dojo_testdata.json b/dojo/fixtures/dojo_testdata.json index d800e286830..7984c19875a 100644 --- a/dojo/fixtures/dojo_testdata.json +++ b/dojo/fixtures/dojo_testdata.json @@ -3126,7 +3126,7 @@ "notes": [], "files": [], "tags": [], - "inherited_tags": [] + "_inherited_tag_names": [] } }, { @@ -3213,7 +3213,7 @@ 1000 ], "tags": [], - "inherited_tags": [] + "_inherited_tag_names": [] } }, { @@ -3286,7 +3286,7 @@ "notes": [], "files": [], "tags": [], - "inherited_tags": [] + "_inherited_tag_names": [] } }, { @@ -3373,7 +3373,7 @@ 1001 ], "tags": [], - "inherited_tags": [] + "_inherited_tag_names": [] } }, { diff --git a/dojo/forms.py b/dojo/forms.py index 26cb003d0a5..9b1c8ff084b 100644 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -1141,7 +1141,7 @@ def clean_tags(self): class Meta: model = Engagement - exclude = ("first_contacted", "real_start", "engagement_type", "inherited_tags", + exclude = ("first_contacted", "real_start", "engagement_type", "_inherited_tag_names", "real_end", "requester", "reason", "updated", "report_type", "product", "threat_model", "api_test", "pen_test", "check_list") @@ -1327,7 +1327,7 @@ def clean_tags(self): class Meta: model = Finding - exclude = ("reporter", "url", "numerical_severity", "under_review", "reviewers", "cve", "inherited_tags", + exclude = ("reporter", "url", "numerical_severity", "under_review", "reviewers", "cve", "_inherited_tag_names", "review_requested_by", "is_mitigated", "jira_creation", "jira_change", "endpoints", "sla_start_date") @@ -1433,7 +1433,7 @@ def clean_tags(self): class Meta: model = Finding - exclude = ("reporter", "url", "numerical_severity", "under_review", "reviewers", "cve", "inherited_tags", + exclude = ("reporter", "url", "numerical_severity", "under_review", "reviewers", "cve", "_inherited_tag_names", "review_requested_by", "is_mitigated", "jira_creation", "jira_change", "endpoints", "sla_start_date", "sla_expiration_date") @@ -1517,7 +1517,7 @@ def clean_tags(self): class Meta: model = Finding - exclude = ("reporter", "url", "numerical_severity", "active", "false_p", "verified", "endpoint_status", "cve", "inherited_tags", + exclude = ("reporter", "url", "numerical_severity", "active", "false_p", "verified", "endpoint_status", "cve", "_inherited_tag_names", "duplicate", "out_of_scope", "under_review", "reviewers", "review_requested_by", "is_mitigated", "jira_creation", "jira_change", "planned_remediation_date", "planned_remediation_version", "effort_for_fixing") @@ -1682,7 +1682,7 @@ def _post_clean(self): class Meta: model = Finding - exclude = ("reporter", "url", "numerical_severity", "under_review", "reviewers", "cve", "inherited_tags", + exclude = ("reporter", "url", "numerical_severity", "under_review", "reviewers", "cve", "_inherited_tag_names", "review_requested_by", "is_mitigated", "jira_creation", "jira_change", "sonarqube_issue", "endpoints", "endpoint_status") @@ -1965,7 +1965,7 @@ class Meta: class EditEndpointForm(forms.ModelForm): class Meta: model = Endpoint - exclude = ["product", "inherited_tags"] + exclude = ["product", "_inherited_tag_names"] def __init__(self, *args, **kwargs): self.product = None diff --git a/dojo/importers/location_manager.py b/dojo/importers/location_manager.py index 935d5159427..e2698341232 100644 --- a/dojo/importers/location_manager.py +++ b/dojo/importers/location_manager.py @@ -19,8 +19,6 @@ from dojo.utils import get_system_setting if TYPE_CHECKING: - from tagulous.models import TagField - from dojo.models import Dojo_User, Finding logger = logging.getLogger(__name__) @@ -535,20 +533,26 @@ def _bulk_inherit_tags(self, locations): for pid, p in products.items() } - # Helper method for getting all tags from the given TagField - def _get_tags(tags_field: TagField) -> dict[int, set[str]]: - through_model = tags_field.through - fk_name = tags_field.field.m2m_reverse_field_name() - tags_by_location: dict[int, set[str]] = {loc.id: set() for loc in locations} - for l_id, t_name in through_model.objects.filter( - location_id__in=location_ids, - ).values_list("location_id", f"{fk_name}__name"): - tags_by_location[l_id].add(t_name) - return tags_by_location - - # Gather inherited and 'regular' tags per location - existing_inherited_by_location: dict[int, set[str]] = _get_tags(Location.inherited_tags) - existing_tags_by_location: dict[int, set[str]] = _get_tags(Location.tags) + # Read existing `_inherited_tag_names` JSON column per location. + existing_inherited_by_location: dict[int, set[str]] = { + loc_id: set(names or []) + for loc_id, names in Location.objects.filter( + id__in=location_ids, + ).values_list("id", "_inherited_tag_names") + } + # Default to empty set for locations not yet returned (none expected). + for loc_id in location_ids: + existing_inherited_by_location.setdefault(loc_id, set()) + + # Read existing `tags` M2M per location via the through table. + existing_tags_by_location: dict[int, set[str]] = {loc_id: set() for loc_id in location_ids} + tags_field = Location.tags + through_model = tags_field.through + fk_name = tags_field.field.m2m_reverse_field_name() + for l_id, t_name in through_model.objects.filter( + location_id__in=location_ids, + ).values_list("location_id", f"{fk_name}__name"): + existing_tags_by_location[l_id].add(t_name) # Perform the bulk updates inside a `tag_inheritance.batch()` context. # While the batch is active, signal handlers in `dojo/tags_signals.py` diff --git a/dojo/location/models.py b/dojo/location/models.py index 48ffeb6878a..b4ea8ed5ea8 100644 --- a/dojo/location/models.py +++ b/dojo/location/models.py @@ -73,10 +73,10 @@ class Location(BaseModel): related_name="location_tags", help_text=_("A tag that can be used to differentiate a Location"), ) - inherited_tags = TagField( + _inherited_tag_names = JSONField( + default=list, blank=True, - force_lowercase=True, - help_text=_("Internal use tags sepcifically for maintaining parity with product. This field will be present as a subset in the tags field"), + help_text=_("Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input."), ) objects = LocationManager().from_queryset(LocationQueryset)() diff --git a/dojo/models.py b/dojo/models.py index 8cff7092ef6..a16effe6718 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -112,27 +112,56 @@ def _get_statistics_for_queryset(qs, annotation_factory): def _manage_inherited_tags(obj, incoming_inherited_tags, potentially_existing_tags=None): - # get copies of the current tag lists + """ + Sync `obj._inherited_tag_names` (JSON column) and `obj.tags` (M2M) so + that: + - `_inherited_tag_names` == set(incoming_inherited_tags) + - `obj.tags` == (current_user_tags) UNION set(incoming_inherited_tags) + where `current_user_tags = current_tags - previous_inherited`. + + The previous implementation maintained a duplicate `inherited_tags` + TagField; that field has been replaced with a single JSON column on + each child model. The JSON column tracks which entries in `tags` + came from inheritance vs user input, satisfying the "remove inherited + tag from product" requirement (previously sourced from the duplicate + M2M). + """ if potentially_existing_tags is None: potentially_existing_tags = [] - current_inherited_tags = [] if isinstance(obj.inherited_tags, FakeTagRelatedManager) else [tag.name for tag in obj.inherited_tags.all()] - tag_list = potentially_existing_tags if isinstance(obj.tags, FakeTagRelatedManager) or len(potentially_existing_tags) > 0 else [tag.name for tag in obj.tags.all()] - # Clean existing tag list from the old inherited tags. This represents the tags on the object and not the product - cleaned_tag_list = [tag for tag in tag_list if tag not in current_inherited_tags] - # Add the incoming inherited tag list - if incoming_inherited_tags: - for tag in incoming_inherited_tags: - if tag not in cleaned_tag_list: - cleaned_tag_list.append(tag) - # Update the current list of inherited tags. iteratively do this because of tagulous object restraints - if isinstance(obj.inherited_tags, FakeTagRelatedManager): - obj.inherited_tags.set_tag_list(incoming_inherited_tags) - if incoming_inherited_tags: - obj.tags.set_tag_list(cleaned_tag_list) + incoming_list = list(incoming_inherited_tags or []) + + current_inherited = list(obj._inherited_tag_names or []) + + # Determine current `tags` list. For unsaved instances Tagulous returns + # a FakeTagRelatedManager that can't query the DB; fall back to the + # potentially_existing_tags hint or the manager's local cache. + if isinstance(obj.tags, FakeTagRelatedManager): + tag_list = list(potentially_existing_tags) if potentially_existing_tags else list(obj.tags.get_tag_list()) + elif potentially_existing_tags: + tag_list = list(potentially_existing_tags) else: - obj.inherited_tags.set(incoming_inherited_tags) - if incoming_inherited_tags: - obj.tags.set(cleaned_tag_list) + tag_list = [tag.name for tag in obj.tags.all()] + + # Strip previously-inherited names so user-only tags survive. + cleaned = [t for t in tag_list if t not in current_inherited] + # Append new inherited names (preserve order, no duplicates). + for n in incoming_list: + if n not in cleaned: + cleaned.append(n) + + # Persist JSON column. For saved instances issue a targeted UPDATE so we + # don't fire post_save (which would re-enter inheritance via signals). + obj._inherited_tag_names = incoming_list + if obj.pk is not None: + type(obj).objects.filter(pk=obj.pk).update(_inherited_tag_names=incoming_list) + + # Persist `tags` M2M. Only write when something changed -- avoids + # firing m2m_changed (and the sticky receiver) for no-op syncs. + if incoming_list and set(cleaned) != set(tag_list): + if isinstance(obj.tags, FakeTagRelatedManager): + obj.tags.set_tag_list(cleaned) + else: + obj.tags.set(cleaned) def copy_model_util(model_in_database, exclude_fields: list[str] | None = None): @@ -1583,7 +1612,7 @@ class Engagement(BaseModel): deduplication_on_engagement = models.BooleanField(default=False, verbose_name=_("Deduplication within this engagement only"), help_text=_("If enabled deduplication will only mark a finding in this engagement as duplicate of another finding if both findings are in this engagement. If disabled, deduplication is on the product level.")) tags = TagField(blank=True, force_lowercase=True, help_text=_("Add tags that help describe this engagement. Choose from the list or add new tags. Press Enter key to add.")) - inherited_tags = TagField(blank=True, force_lowercase=True, help_text=_("Internal use tags sepcifically for maintaining parity with product. This field will be present as a subset in the tags field")) + _inherited_tag_names = models.JSONField(default=list, blank=True, help_text=_("Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.")) class Meta: ordering = ["-target_start"] @@ -1774,7 +1803,7 @@ class Endpoint(models.Model): through=Endpoint_Status) tags = TagField(blank=True, force_lowercase=True, help_text=_("Add tags that help describe this endpoint. Choose from the list or add new tags. Press Enter key to add.")) - inherited_tags = TagField(blank=True, force_lowercase=True, help_text=_("Internal use tags sepcifically for maintaining parity with product. This field will be present as a subset in the tags field")) + _inherited_tag_names = models.JSONField(default=list, blank=True, help_text=_("Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.")) class Meta: ordering = ["product", "host", "protocol", "port", "userinfo", "path", "query", "fragment"] @@ -2181,7 +2210,7 @@ class Test(models.Model): created = models.DateTimeField(auto_now_add=True, null=True) tags = TagField(blank=True, force_lowercase=True, help_text=_("Add tags that help describe this test. Choose from the list or add new tags. Press Enter key to add.")) - inherited_tags = TagField(blank=True, force_lowercase=True, help_text=_("Internal use tags sepcifically for maintaining parity with product. This field will be present as a subset in the tags field")) + _inherited_tag_names = models.JSONField(default=list, blank=True, help_text=_("Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.")) version = models.CharField(max_length=100, null=True, blank=True) @@ -2791,7 +2820,7 @@ class Finding(BaseModel): help_text=_("Effort for fixing / remediating the vulnerability (Low, Medium, High)")) tags = TagField(blank=True, force_lowercase=True, help_text=_("Add tags that help describe this finding. Choose from the list or add new tags. Press Enter key to add.")) - inherited_tags = TagField(blank=True, force_lowercase=True, help_text=_("Internal use tags sepcifically for maintaining parity with product. This field will be present as a subset in the tags field")) + _inherited_tag_names = models.JSONField(default=list, blank=True, help_text=_("Internal: tag names inherited from the product, used to identify which entries in `tags` came from inheritance vs user input.")) SEVERITIES = {"Info": 4, "Low": 3, "Medium": 2, "High": 1, "Critical": 0} @@ -4585,13 +4614,9 @@ def __str__(self): tagulous.admin.register(Product.tags) tagulous.admin.register(Test.tags) -tagulous.admin.register(Test.inherited_tags) tagulous.admin.register(Finding.tags) -tagulous.admin.register(Finding.inherited_tags) tagulous.admin.register(Engagement.tags) -tagulous.admin.register(Engagement.inherited_tags) tagulous.admin.register(Endpoint.tags) -tagulous.admin.register(Endpoint.inherited_tags) tagulous.admin.register(Finding_Template.tags) tagulous.admin.register(App_Analysis.tags) tagulous.admin.register(Objects_Product.tags) diff --git a/dojo/product/helpers.py b/dojo/product/helpers.py index 331ebc534b6..17cab218f02 100644 --- a/dojo/product/helpers.py +++ b/dojo/product/helpers.py @@ -119,96 +119,95 @@ def _build_location_target_names_map(location_ids): def _sync_inheritance_for_qs(queryset, *, target_names_per_child): """ - Sync inherited_tags + tags for every child in `queryset` to its target tag set. + Sync `_inherited_tag_names` (JSON column) + `tags` (M2M) for every child + in `queryset` to its target tag set. target_names_per_child: callable(child) -> set[str]. - Issues bulk SQL: one through-table read for current inherited_tags, then - bulk add/remove on `tags` and `inherited_tags` fields. + Issues bulk SQL: + - one fetch of `(pk, _inherited_tag_names, tags through-table)` + - bulk add/remove on `tags` based on the diff + - bulk UPDATE of `_inherited_tag_names` """ - children = list(queryset) + children = list(queryset.only("pk", "_inherited_tag_names")) if not children: return model_class = type(children[0]) - inherited_field = model_class._meta.get_field("inherited_tags") - inherited_through = inherited_field.remote_field.through - inherited_tag_model = inherited_field.related_model + tags_field = model_class._meta.get_field("tags") + tags_through = tags_field.remote_field.through + tags_tag_model = tags_field.related_model # Resolve through-table FK column for the source side. source_field_name = None - for field in inherited_through._meta.fields: + for field in tags_through._meta.fields: if hasattr(field, "remote_field") and field.remote_field and field.remote_field.model == model_class: source_field_name = field.name break child_ids = [c.pk for c in children] - # One query: pull every (child_id, tag_name) pair from the inherited_tags through table. - existing_pairs = inherited_through.objects.filter( - **{f"{source_field_name}__in": child_ids}, - ).values_list(source_field_name, f"{inherited_tag_model._meta.model_name}__name") - - old_inherited_by_child: dict[int, set[str]] = defaultdict(set) - for child_id, tag_name in existing_pairs: - old_inherited_by_child[child_id].add(tag_name) - - # Compute per-child diff and bucket by tag name. Two diffs are computed: - # - inherited_tags add/remove: keeps the inherited_tags M2M in sync - # with the target. - # - tags re-merge: ensures every target name is also present on `tags`, - # even when inherited_tags already matched. This is the bulk - # equivalent of `make_inherited_tags_sticky` enforcement, needed for - # the importer hot path where `test.tags.set([...])` overwrites the - # full tag list inside a `tag_inheritance.batch()` block. - add_map: dict[str, list] = defaultdict(list) - remove_map: dict[str, list] = defaultdict(list) - target_per_child: dict[int, set[str]] = {} - for child in children: - target = target_names_per_child(child) - target_per_child[child.pk] = target - old = old_inherited_by_child.get(child.pk, set()) - for name in target - old: - add_map[name].append(child) - for name in old - target: - remove_map[name].append(child) - - # Apply adds. Both `tags` and `inherited_tags` get the same set of new - # inherited names — `_manage_inherited_tags` did the same. - if add_map: - bulk_add_tag_mapping(add_map, tag_field_name="inherited_tags") - bulk_add_tag_mapping(add_map, tag_field_name="tags") - # Apply removes. - for name, instances in remove_map.items(): - bulk_remove_tags_from_instances(name, instances, tag_field_name="inherited_tags") - bulk_remove_tags_from_instances(name, instances, tag_field_name="tags") + # Read each child's persisted "what was inherited" JSON column. + old_inherited_by_child: dict[int, set[str]] = { + c.pk: set(c._inherited_tag_names or []) for c in children + } - # Bulk re-merge: ensure every target name is present on `tags`. We need - # this for the importer hot path where `tags.set([...])` inside a - # `tag_inheritance.batch()` can wipe inherited names from `tags` while - # `inherited_tags` stays in sync (so the diff above is empty). - # - # Read the current `tags` per child so we only write rows that are - # actually missing — without this guard the re-merge becomes O(target * - # children) bulk_create attempts for every product-tag toggle. - tags_field = model_class._meta.get_field("tags") - tags_through = tags_field.remote_field.through - tags_tag_model = tags_field.related_model + # Read each child's current `tags` through-table in one bulk SELECT. existing_tags_pairs = tags_through.objects.filter( **{f"{source_field_name}__in": child_ids}, ).values_list(source_field_name, f"{tags_tag_model._meta.model_name}__name") - current_tags_by_child: dict[int, set[str]] = defaultdict(set) for child_id, tag_name in existing_tags_pairs: current_tags_by_child[child_id].add(tag_name) + # Compute per-child diff: + # - add_map: names in target but not currently inherited (need add to `tags`) + # - remove_map: names previously inherited but no longer in target (remove from `tags`) + # - remerge_map: names in target but missing from `tags` (sticky re-merge) + # - new_inherited_per_child: the JSON column write + add_map: dict[str, list] = defaultdict(list) + remove_map: dict[str, list] = defaultdict(list) remerge_map: dict[str, list] = defaultdict(list) + new_inherited_per_child: dict[int, list[str]] = {} for child in children: - target = target_per_child[child.pk] - current = current_tags_by_child.get(child.pk, set()) - # Skip names already added by the diff above; only fix true drift. - already_added = {name for name, lst in add_map.items() if child in lst} - for name in target - current - already_added: + target = set(target_names_per_child(child)) + old = old_inherited_by_child.get(child.pk, set()) + current_tags = current_tags_by_child.get(child.pk, set()) + + # JSON column desired value: deterministic order = sorted names. + new_inherited_per_child[child.pk] = sorted(target) + + # Names newly inherited (not previously recorded in JSON column). + newly_added_names = target - old + for name in newly_added_names: + add_map[name].append(child) + # Names previously inherited but no longer in target. + for name in old - target: + remove_map[name].append(child) + # Sticky re-merge: target name missing from `tags`. Skip names + # already covered by add_map for this child to avoid double-write. + for name in (target - current_tags) - newly_added_names: remerge_map[name].append(child) - if remerge_map: - bulk_add_tag_mapping(remerge_map, tag_field_name="tags") + + # Apply tag-add. Combine add_map + remerge_map; the two never overlap + # for the same (child, name) pair by construction above. + combined_add: dict[str, list] = defaultdict(list) + for name, lst in add_map.items(): + combined_add[name].extend(lst) + for name, lst in remerge_map.items(): + combined_add[name].extend(lst) + if combined_add: + bulk_add_tag_mapping(combined_add, tag_field_name="tags") + + # Apply tag-remove. + for name, instances in remove_map.items(): + bulk_remove_tags_from_instances(name, instances, tag_field_name="tags") + + # Bulk-write the JSON column. Group children by desired value to minimize + # UPDATE statements. + grouped_writes: dict[tuple[str, ...], list[int]] = defaultdict(list) + for child_id, names in new_inherited_per_child.items(): + if names != sorted(old_inherited_by_child.get(child_id, set())): + grouped_writes[tuple(names)].append(child_id) + for names_tuple, ids in grouped_writes.items(): + model_class.objects.filter(pk__in=ids).update(_inherited_tag_names=list(names_tuple)) diff --git a/dojo/tag_inheritance.py b/dojo/tag_inheritance.py index a48c1177ea6..f8cee97a178 100644 --- a/dojo/tag_inheritance.py +++ b/dojo/tag_inheritance.py @@ -65,8 +65,8 @@ def flush_for_product(product) -> None: code has created/modified many children of one product and the per-instance signal handlers were suppressed. Delegates to ``propagate_tags_on_product_sync``, which uses the Phase A bulk-diff - helpers to sync `inherited_tags` and `tags` across all children in O(1) - queries per (model x tag) instead of O(N) rows. + helpers to sync `_inherited_tag_names` and `tags` across all children + in O(1) queries per (model x tag) instead of O(N) rows. Short-circuits when tag inheritance is disabled (neither the system-wide flag nor the per-product flag is set) so callers (e.g. importers) can diff --git a/dojo/tags_signals.py b/dojo/tags_signals.py index 07f588b90e3..bb75370861f 100644 --- a/dojo/tags_signals.py +++ b/dojo/tags_signals.py @@ -97,7 +97,9 @@ def propagate_inheritance(instance, tag_list=None): for product in get_products_to_inherit_tags_from(instance) for tag in product.tags.all() ] - existing_inherited_tags = [tag.name for tag in instance.inherited_tags.all()] + # Read the persisted inherited-name list from the JSON column. Falls + # back to an empty list for new/unsaved instances. + existing_inherited_tags = list(getattr(instance, "_inherited_tag_names", []) or []) # Check if product tags already matches inherited tags product_tags_equals_inherited_tags = product_inherited_tags == existing_inherited_tags # Check if product tags have already been inherited diff --git a/unittests/test_tag_inheritance.py b/unittests/test_tag_inheritance.py index 1d3bb7a8b18..01bf816ab53 100644 --- a/unittests/test_tag_inheritance.py +++ b/unittests/test_tag_inheritance.py @@ -155,10 +155,10 @@ class TestPropagateInheritanceEarlyExit(unittest.TestCase): Unit tests for propagate_inheritance() — the optimization guard that skips redundant DB writes. Returns False ("nothing to do") only when BOTH conditions hold: - 1. product tags match what is stored in instance.inherited_tags (already recorded) + 1. product tags match what is stored in instance._inherited_tag_names (already recorded) 2. those tags are already present in the instance's full tag_list (already applied) If either condition is false, returns True and the caller proceeds to write tags. - get_products_to_inherit_tags_from and instance.inherited_tags.all() are mocked + get_products_to_inherit_tags_from and instance._inherited_tag_names are mocked to isolate the boolean logic from DB access. """ @@ -169,7 +169,7 @@ def _tag(self, name): def _make_instance(self, inherited_names): instance = MagicMock() - instance.inherited_tags.all.return_value = [self._tag(n) for n in inherited_names] + instance._inherited_tag_names = list(inherited_names) return instance def _make_product(self, tag_names): @@ -351,7 +351,7 @@ def test_locations_inherit_product_tags(self): mgr.persist() loc = Location.objects.get(url__host="oss-tag-inherit.example.com") - inherited = sorted(t.name for t in loc.inherited_tags.all()) + inherited = sorted(loc._inherited_tag_names or []) self.assertEqual(inherited, ["inherit", "tags", "these"]) def test_bulk_inherit_is_no_op_when_already_in_sync(self): @@ -398,12 +398,14 @@ def test_bulk_inherit_already_synced_is_constant_time(self): mgr2.persist() tag_through = Location.tags.through._meta.db_table - inherited_through = Location.inherited_tags.through._meta.db_table for q in ctx.captured_queries: sql = q["sql"].lower() if sql.startswith(("insert", "update", "delete")): self.assertNotIn(tag_through.lower(), sql, f"Unexpected tags mutation: {q['sql']}") - self.assertNotIn(inherited_through.lower(), sql, f"Unexpected inherited_tags mutation: {q['sql']}") + # _inherited_tag_names is now a JSONField on the parent table; + # check no UPDATEs target it for re-synced data. + if "_inherited_tag_names" in sql: + self.fail(f"Unexpected _inherited_tag_names mutation: {q['sql']}") @skip_unless_v3 diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index a2e3ea7df64..8e5dee477bd 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -359,35 +359,33 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): # Findings-only scenarios. # Pre-Phase-A V2: 4758 add, 4540 remove. V3: 4759/4541. # Phase A bulk-propagate drops these dramatically. - # Phase B Stage 2 adds ~3 queries to read current `tags` for the bulk - # re-merge step (compensates for tags wiped inside batch contexts). - EXPECTED_PRODUCT_TAG_ADD_100_V2 = 94 - EXPECTED_PRODUCT_TAG_ADD_100_V3 = 94 - EXPECTED_PRODUCT_TAG_REMOVE_100_V2 = 56 - EXPECTED_PRODUCT_TAG_REMOVE_100_V3 = 56 - - EXPECTED_CREATE_ONE_FINDING_V2 = 64 - EXPECTED_CREATE_ONE_FINDING_V3 = 64 - EXPECTED_CREATE_100_FINDINGS_V2 = 4024 - EXPECTED_CREATE_100_FINDINGS_V3 = 4024 - - EXPECTED_FINDING_ADD_USER_TAG_V2 = 17 - EXPECTED_FINDING_ADD_USER_TAG_V3 = 17 - EXPECTED_FINDING_REMOVE_INHERITED_V2 = 44 - EXPECTED_FINDING_REMOVE_INHERITED_V3 = 44 + # Phase B Stage 3 (drop duplicate inherited_tags TagField; replace with + # _inherited_tag_names JSONField) drops further: a single UPDATE on the + # JSON column instead of M2M through-table mutations on a duplicate field. + EXPECTED_PRODUCT_TAG_ADD_100_V2 = 58 + EXPECTED_PRODUCT_TAG_ADD_100_V3 = 58 + EXPECTED_PRODUCT_TAG_REMOVE_100_V2 = 38 + EXPECTED_PRODUCT_TAG_REMOVE_100_V3 = 38 + + EXPECTED_CREATE_ONE_FINDING_V2 = 42 + EXPECTED_CREATE_ONE_FINDING_V3 = 42 + EXPECTED_CREATE_100_FINDINGS_V2 = 2814 + EXPECTED_CREATE_100_FINDINGS_V3 = 2814 + + EXPECTED_FINDING_ADD_USER_TAG_V2 = 16 + EXPECTED_FINDING_ADD_USER_TAG_V3 = 16 + EXPECTED_FINDING_REMOVE_INHERITED_V2 = 24 + EXPECTED_FINDING_REMOVE_INHERITED_V3 = 24 # V2 endpoint paths. Pre-Phase-A: 3958 add, 3740 remove. - # Phase B Stage 2 raises endpoint add 91 -> 194 because the eager Celery - # propagate dispatched by m2m_changed and the explicit - # propagate_tags_on_product_sync call both pay the new tags-read for - # bulk re-merge. Acceptable: the same lever delivers a 27% drop on the - # ZAP import path. Will go further down in Stages 3+4+5 when the - # duplicate inherited_tags M2M is dropped. - EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS = 194 - EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 56 + # Phase B Stage 3 dropped the inherited_tags TagField; bulk re-merge + # de-duplicates entries so endpoint path collapses in line with findings. + EXPECTED_PRODUCT_TAG_ADD_100_ENDPOINTS = 58 + EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 38 # V3 location paths. Pre-Phase-A: 4532 add, 4307 remove. # Phase B Stage 2 + location precompute: bulk-built target-name map. + # Stage 3 may further drop these once JSON column replaces M2M reads. EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 123 EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 73 @@ -510,7 +508,7 @@ def test_baseline_zap_scan_reimport_no_change_v3(self): # rises because flush always runs; bulk re-merge has a fixed cost even # when there's no work. Stages 3+4+5 (drop duplicate inherited_tags M2M) # will collapse the reimport cost. - EXPECTED_ZAP_IMPORT_V2 = 1006 - EXPECTED_ZAP_IMPORT_V3 = 947 - EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 82 - EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 103 + EXPECTED_ZAP_IMPORT_V2 = 700 + EXPECTED_ZAP_IMPORT_V3 = 698 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 78 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 136 diff --git a/unittests/test_tag_utils_bulk.py b/unittests/test_tag_utils_bulk.py index 3a815041fb4..94dce198add 100644 --- a/unittests/test_tag_utils_bulk.py +++ b/unittests/test_tag_utils_bulk.py @@ -230,7 +230,7 @@ def test_bulk_add_tag_to_product_rejected(self): for child in (eng, test, loc1, loc2): child.refresh_from_db() self.assertNotIn("p-tag", [t.name for t in child.tags.all()]) - self.assertNotIn("p-tag", [t.name for t in child.inherited_tags.all()]) + self.assertNotIn("p-tag", child._inherited_tag_names or []) def test_bulk_add_invalid_field_name(self): instances = self._make_locations(1) @@ -452,7 +452,7 @@ def _tags_list(self, obj): return [t.name for t in obj.tags.all()] def _inherited_tags_list(self, obj): - return [t.name for t in obj.inherited_tags.all()] + return list(obj._inherited_tag_names or []) def test_bulk_add_tags_to_findings_does_not_affect_inheritance(self): # Arrange: build a minimal tree with engagement/test and two findings From 15f1303b9c5bc01469aac676e65134b04634644e Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Wed, 6 May 2026 22:29:41 +0200 Subject: [PATCH 11/12] fix(tags): rename inherited_tags to _inherited_tag_names in fixtures CI failure on rest-framework jobs: FieldDoesNotExist on FakeTaggedModel when loading dojo_testdata_locations.json. The JSON-column rename in 0265 dropped the M2M field, but three fixtures still referenced the old name. Sweep fixtures alongside the model migration so test setUpClass loads cleanly. --- dojo/fixtures/defect_dojo_sample_data.json | 788 +++++++++--------- .../defect_dojo_sample_data_locations.json | 788 +++++++++--------- dojo/fixtures/dojo_testdata_locations.json | 8 +- 3 files changed, 792 insertions(+), 792 deletions(-) diff --git a/dojo/fixtures/defect_dojo_sample_data.json b/dojo/fixtures/defect_dojo_sample_data.json index 2eb0c9b0e86..3f2fc4e2876 100644 --- a/dojo/fixtures/defect_dojo_sample_data.json +++ b/dojo/fixtures/defect_dojo_sample_data.json @@ -2754,7 +2754,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "product_manager" ], @@ -2801,7 +2801,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -2848,7 +2848,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "product_manager" ], @@ -2895,7 +2895,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -2942,7 +2942,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -2991,7 +2991,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "name": "Ad Hoc Engagement", "notes": [], @@ -3036,7 +3036,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3083,7 +3083,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3132,7 +3132,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3179,7 +3179,7 @@ "engagement_type": "CI/CD", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3226,7 +3226,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "name": "AdHoc Import - Fri, 17 Aug 2018 18:20:55", "notes": [], @@ -3260,7 +3260,7 @@ "endpoint_params": [], "fragment": null, "host": "127.0.0.1", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/endpoint/420/edit/", "port": 80, "product": 2, @@ -3277,7 +3277,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/", "port": 21, "product": 1, @@ -3294,7 +3294,7 @@ "endpoint_params": [], "fragment": null, "host": "127.0.0.1", - "inherited_tags": [], + "_inherited_tag_names": [], "path": null, "port": 22, "product": 3, @@ -3311,7 +3311,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/login.jsp", "port": 8888, "product": 1, @@ -3328,7 +3328,7 @@ "endpoint_params": [], "fragment": null, "host": "127.0.0.1", - "inherited_tags": [], + "_inherited_tag_names": [], "path": null, "port": null, "product": 1, @@ -3345,7 +3345,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/register.jsp", "port": 8888, "product": 1, @@ -3362,7 +3362,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/password.jsp", "port": 8888, "product": 1, @@ -3379,7 +3379,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/", "port": 8888, "product": 1, @@ -3396,7 +3396,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/basket.jsp", "port": 8888, "product": 1, @@ -3413,7 +3413,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/advanced.jsp", "port": 8888, "product": 1, @@ -3430,7 +3430,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/admin.jsp", "port": 8888, "product": 1, @@ -3447,7 +3447,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/about.jsp", "port": 8888, "product": 1, @@ -3464,7 +3464,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/contact.jsp", "port": 8888, "product": 1, @@ -3481,7 +3481,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/home.jsp", "port": 8888, "product": 1, @@ -3498,7 +3498,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/product.jsp", "port": 8888, "product": 1, @@ -3515,7 +3515,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/score.jsp", "port": 8888, "product": 1, @@ -3532,7 +3532,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/search.jsp", "port": 8888, "product": 1, @@ -3549,7 +3549,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/", "port": 8888, "product": 1, @@ -3566,7 +3566,7 @@ "endpoint_params": [], "fragment": null, "host": "localhost", - "inherited_tags": [], + "_inherited_tag_names": [], "path": "/bodgeit/logout.jsp", "port": 8888, "product": 1, @@ -3638,7 +3638,7 @@ "engagement": 1, "environment": 1, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "notes": [], "percent_complete": 100, @@ -3665,7 +3665,7 @@ "engagement": 2, "environment": 1, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "product_manager" ], @@ -3694,7 +3694,7 @@ "engagement": 1, "environment": 1, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "notes": [], "percent_complete": 100, @@ -3721,7 +3721,7 @@ "engagement": 4, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3750,7 +3750,7 @@ "engagement": 4, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3779,7 +3779,7 @@ "engagement": 6, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3808,7 +3808,7 @@ "engagement": 7, "environment": null, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "notes": [], "percent_complete": null, @@ -3835,7 +3835,7 @@ "engagement": 8, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3864,7 +3864,7 @@ "engagement": 8, "environment": 2, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3893,7 +3893,7 @@ "engagement": 8, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3922,7 +3922,7 @@ "engagement": 8, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3951,7 +3951,7 @@ "engagement": 10, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3980,7 +3980,7 @@ "engagement": 10, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -4009,7 +4009,7 @@ "engagement": 10, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -4038,7 +4038,7 @@ "engagement": 11, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -4067,7 +4067,7 @@ "engagement": 11, "environment": 5, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -4096,7 +4096,7 @@ "engagement": 12, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -4125,7 +4125,7 @@ "engagement": 13, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -4172,7 +4172,7 @@ ], "hash_code": "91a538bb2d339f9f73553971ede199f44df8e96df30f34ac8d9c224322aa5d62", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": null, "last_reviewed_by": null, @@ -4255,7 +4255,7 @@ ], "hash_code": "5b0dead640b58a2b778aa2e8f5cccf67df7dc833b0c3f410985d1237615c86e7", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": null, "last_reviewed_by": null, @@ -4338,7 +4338,7 @@ ], "hash_code": "5b0dead640b58a2b778aa2e8f5cccf67df7dc833b0c3f410985d1237615c86e7", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": null, "last_reviewed_by": null, @@ -4421,7 +4421,7 @@ ], "hash_code": "5b0dead640b58a2b778aa2e8f5cccf67df7dc833b0c3f410985d1237615c86e7", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": null, "last_reviewed_by": null, @@ -4504,7 +4504,7 @@ ], "hash_code": "5b0dead640b58a2b778aa2e8f5cccf67df7dc833b0c3f410985d1237615c86e7", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": null, "last_reviewed_by": null, @@ -4587,7 +4587,7 @@ ], "hash_code": "c89d25e445b088ba339908f68e15e3177b78d22f3039d1bfea51c4be251bf4e0", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": null, "last_reviewed_by": null, @@ -4668,7 +4668,7 @@ ], "hash_code": "c49c87192b6b4f17151a471fd9d1bf3b302bca08781d67806c6556fe720af1b0", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:43.513932529Z", "last_reviewed_by": [ @@ -4749,7 +4749,7 @@ ], "hash_code": "a9c3269038ed8a49c4e7576b359f61a65a3bd82c163089bc20743e5a14aa0ab5", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:43.689932529Z", "last_reviewed_by": [ @@ -4830,7 +4830,7 @@ ], "hash_code": "418f79f7a59a306d5e46aa4af1924b64200aed234ae994dcd66485eb30bbe869", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:43.871932529Z", "last_reviewed_by": [ @@ -4911,7 +4911,7 @@ ], "hash_code": "21c80d580d9f1de55f6179e2a08e5684f46c9734d79cf701b2ff25e6776ccdfc", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:44.048932529Z", "last_reviewed_by": [ @@ -4992,7 +4992,7 @@ ], "hash_code": "fffd29bd0973269ddbbed2e210926c04d42cb12037117261626b95bd52bcff27", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:44.191932529Z", "last_reviewed_by": [ @@ -5073,7 +5073,7 @@ ], "hash_code": "3406086ac5988ee8b55f70c618daf86c21702bb3c4c00e4607e5c21c2e3d3828", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:44.361932529Z", "last_reviewed_by": [ @@ -5154,7 +5154,7 @@ ], "hash_code": "24e74e8be8b222cf0b17c034d03c5b43a130c2b960095eb44c55f470e50f6924", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:44.525932529Z", "last_reviewed_by": [ @@ -5235,7 +5235,7 @@ ], "hash_code": "a91b30b026cda759c2608e1c8216cdd13e265c030b8c47f4690cd2182e4ad166", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:44.677932529Z", "last_reviewed_by": [ @@ -5316,7 +5316,7 @@ ], "hash_code": "bfd9b74841c8d988d57c99353742f1e3180934ca6be2149a3fb7377329b57b33", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:44.828932529Z", "last_reviewed_by": [ @@ -5397,7 +5397,7 @@ ], "hash_code": "9b003338465e31c37f36b2a2d9b01bf9003d1d2631e2c409b3d19d02c93a20b6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:44.982932529Z", "last_reviewed_by": [ @@ -5478,7 +5478,7 @@ ], "hash_code": "684ee38b55ea509e6c2be4a58ec52ba5d7e0c1952e09f8c8ca2bf0675650bd8f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:45.132932529Z", "last_reviewed_by": [ @@ -5559,7 +5559,7 @@ ], "hash_code": "99fb15b31049df2445ac3fd8729cbccbc6a19e4e410c3eb0ef95908c00b78fd7", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:45.296932529Z", "last_reviewed_by": [ @@ -5640,7 +5640,7 @@ ], "hash_code": "541eb71776b2d297f9aa790c52297b4f7d26acb0bce7de33bda136fdefe43cb7", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:45.453932529Z", "last_reviewed_by": [ @@ -5721,7 +5721,7 @@ ], "hash_code": "e5ac755dbe3bfd23995c8d5a99779d188440c9e573d79b44130d90468d41439c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:45.625932529Z", "last_reviewed_by": [ @@ -5802,7 +5802,7 @@ ], "hash_code": "da32068a6442ce061d43625863d27f5e6346929f2b1d15b750df9d7b4bdb3597", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:45.787932529Z", "last_reviewed_by": [ @@ -5883,7 +5883,7 @@ ], "hash_code": "b0de3516ab323f5577e6ad94803e2ddf541214bbae868bf34e828ba3a4d966ca", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:45.963932529Z", "last_reviewed_by": [ @@ -5964,7 +5964,7 @@ ], "hash_code": "13ceb3acfb49f194493bfb0af44f5f886a9767aa1c6990c8a397af756d97209c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:46.153932529Z", "last_reviewed_by": [ @@ -6045,7 +6045,7 @@ ], "hash_code": "8d7b5f3962f521cd5c2dc40e4ef9a7cc10cfc30efb90f4b5841e8e5463656c61", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:46.311932529Z", "last_reviewed_by": [ @@ -6126,7 +6126,7 @@ ], "hash_code": "2237f06cb695ec1da91d51cab9fb037d8a9e84f1aa9ddbfeef59eef1a65af47e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:46.487932529Z", "last_reviewed_by": [ @@ -6207,7 +6207,7 @@ ], "hash_code": "05880cd0576bed75819cae74abce873fdcce5f857ec95d937a458b0ca0a49195", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:46.650932529Z", "last_reviewed_by": [ @@ -6288,7 +6288,7 @@ ], "hash_code": "9ec4ce27f48767b96297ef3cb8eabba1814ea08a02801692a669540c5a7ce019", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:46.826932529Z", "last_reviewed_by": [ @@ -6369,7 +6369,7 @@ ], "hash_code": "fc95b0887dc03b9f29f45b95aeb41e7f681dc28388279d7e11c233d3b5235c00", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:47.073932529Z", "last_reviewed_by": [ @@ -6450,7 +6450,7 @@ ], "hash_code": "bae03653ab0823182626d77d8ba94f2fab26eccdde7bcb11ddd0fb8dee79d717", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:47.320932529Z", "last_reviewed_by": [ @@ -6531,7 +6531,7 @@ ], "hash_code": "ae4e2ef51220be9b4ca71ee34ae9d174d093e6dd2da41951bc4ad2139a4dad3f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:47.509932529Z", "last_reviewed_by": [ @@ -6612,7 +6612,7 @@ ], "hash_code": "c69d0a9ead39b5990a429c6ed185050ffadfda672b020ac6e7322ef02e72563a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:47.703932529Z", "last_reviewed_by": [ @@ -6693,7 +6693,7 @@ ], "hash_code": "51b52607f2a5915cd128ba4e24ce8e22ba019757f074a0ebc27c33d91a55378b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:47.898932529Z", "last_reviewed_by": [ @@ -6774,7 +6774,7 @@ ], "hash_code": "d947020e418c747ee99a0accd491030f65895189aefea2a96a390b3e843a9905", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:48.132932529Z", "last_reviewed_by": [ @@ -6855,7 +6855,7 @@ ], "hash_code": "b29d81fdf7a5477a7badd1a47406a27deb12b90d0b3db17f567344d1ec24e65c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:48.417932529Z", "last_reviewed_by": [ @@ -6936,7 +6936,7 @@ ], "hash_code": "514c8fbd9da03f03f770c9e0ca12d8bb20db50f3a836b4d50f16e0d75b0cca08", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:48.624932529Z", "last_reviewed_by": [ @@ -7017,7 +7017,7 @@ ], "hash_code": "0441fee04d6e24c168f5b4b567cc31174f464330f27638f83f80ee87d0d3dc03", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:48.817932529Z", "last_reviewed_by": [ @@ -7098,7 +7098,7 @@ ], "hash_code": "7be257602d73f6146bbd1c6c4ab4970db0867933a1d2e87675770529b841d800", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:49.005932529Z", "last_reviewed_by": [ @@ -7179,7 +7179,7 @@ ], "hash_code": "ff922242dd15286d81f09888a33ad571eca598b615bf4d4b9024af17df42bc17", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:49.203932529Z", "last_reviewed_by": [ @@ -7260,7 +7260,7 @@ ], "hash_code": "964aeee36e5998da77d3229f43830d362838d860d9e30c415fb58e9686a49625", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:49.421932529Z", "last_reviewed_by": [ @@ -7341,7 +7341,7 @@ ], "hash_code": "e57ed13a66f4041fa377af4db5110a50a8f4a67e0c7c2b3e955e4118844a2904", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:49.616932529Z", "last_reviewed_by": [ @@ -7422,7 +7422,7 @@ ], "hash_code": "8fc3621137e4dd32d75801ac6948909b20f671d21ed9dfe89d0e2f49a2554653", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:49.817932529Z", "last_reviewed_by": [ @@ -7503,7 +7503,7 @@ ], "hash_code": "3988a18fe8f515ab1f92c649f43f20d33e8e8692d00a9dc80f2863342b522698", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:50.028932529Z", "last_reviewed_by": [ @@ -7584,7 +7584,7 @@ ], "hash_code": "cfc58944e3181521dc3a9ec917dcb54d7a54ebbf3f0e8aaca7fec60a05485c63", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:50.221932529Z", "last_reviewed_by": [ @@ -7665,7 +7665,7 @@ ], "hash_code": "9878411e3b89bc832e58fa15e46d19e2e607309d3df9f152114d5ff62f95f0ce", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:50.370932529Z", "last_reviewed_by": [ @@ -7746,7 +7746,7 @@ ], "hash_code": "35055620006745673ffba1cb3c1e8c09a9fd59f6438e6d45fbbb222a10968120", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:50.539932529Z", "last_reviewed_by": [ @@ -7827,7 +7827,7 @@ ], "hash_code": "60fff62e2e1d2383da91886a96d64905e184a3044037dc2595c3ccf28faacd6c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:50.735932529Z", "last_reviewed_by": [ @@ -7908,7 +7908,7 @@ ], "hash_code": "c81c73f4bd1bb970a016bd7e5f1979af8d05eac71f387b2da9bd4affcaf13f81", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:50.927932529Z", "last_reviewed_by": [ @@ -7989,7 +7989,7 @@ ], "hash_code": "1e74e0c4e0572c6bb5aaee26176b8a40ce024325bbffea1ddbb120bab9d9542c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:51.099932529Z", "last_reviewed_by": [ @@ -8070,7 +8070,7 @@ ], "hash_code": "4568d7e34ac50ab291c955c8acb368e5abe73de05bd3080e2efc7b00f329600f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:51.277932529Z", "last_reviewed_by": [ @@ -8151,7 +8151,7 @@ ], "hash_code": "1f91fef184e69387463ce9719fe9756145e16e76d39609aa5fa3e0eaa1274d05", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:51.461932529Z", "last_reviewed_by": [ @@ -8232,7 +8232,7 @@ ], "hash_code": "75a93a572c186be5fe7f5221a64306b5b35dddf605b5e231ffc74442bd3728a4", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:51.636932529Z", "last_reviewed_by": [ @@ -8313,7 +8313,7 @@ ], "hash_code": "afd07fc450ae8609c93797c8fd893028f7d8a9841999facd0a08236696c05841", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:51.791932529Z", "last_reviewed_by": [ @@ -8394,7 +8394,7 @@ ], "hash_code": "78439e5edd436844bb6dc527f6effe0836b88b0fb946747b7f957da95b479fc2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:51.945932529Z", "last_reviewed_by": [ @@ -8475,7 +8475,7 @@ ], "hash_code": "92b54561d5d262a88920162ba7bf19fc0444975582be837047cab5d79c992447", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:52.101932529Z", "last_reviewed_by": [ @@ -8556,7 +8556,7 @@ ], "hash_code": "f24533b1fc628061c2037eb55ffe66aed6bfa2436fadaf6e424e4905ed238e21", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:52.258932529Z", "last_reviewed_by": [ @@ -8637,7 +8637,7 @@ ], "hash_code": "38321299050d31a3b8168316e30316d786236785a9c31427fb6f2631d3065a7c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:52.417932529Z", "last_reviewed_by": [ @@ -8718,7 +8718,7 @@ ], "hash_code": "24cd9b35200f9ca729fcccb8348baccd2ddfeee2f22177fd40e46931f8547659", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:52.593932529Z", "last_reviewed_by": [ @@ -8799,7 +8799,7 @@ ], "hash_code": "148a501a59e0d04eb52b5cd58b4d654b4a7883e8ad09dcd5801e775113a1000d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:52.743932529Z", "last_reviewed_by": [ @@ -8880,7 +8880,7 @@ ], "hash_code": "55040c9344c964843ff56e19ff1ef4892c9f93234a7a39578c81ed903dd03e08", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:52.896932529Z", "last_reviewed_by": [ @@ -8961,7 +8961,7 @@ ], "hash_code": "06cd6507296edca41e97d652a873c31230bf98fa8bdeab477fedb680ff606932", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:53.053932529Z", "last_reviewed_by": [ @@ -9042,7 +9042,7 @@ ], "hash_code": "62f3875efdcf326015adee1ecd85c4ecdca5bc9c4719e5c9177dff8b0afffa1f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:53.224932529Z", "last_reviewed_by": [ @@ -9123,7 +9123,7 @@ ], "hash_code": "0007a2df1ab7dc00f2144451d894f513c7d872e1153a0759982a8c866001cc02", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:53.379932529Z", "last_reviewed_by": [ @@ -9204,7 +9204,7 @@ ], "hash_code": "7dba1c0820d0f6017ca3333f7f9a8865a862604c4b13a1eed04666c6e364fa36", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:53.543932529Z", "last_reviewed_by": [ @@ -9285,7 +9285,7 @@ ], "hash_code": "95568708fa568cc74c7ef8279b87869ebc932305da1878dbb1b7597c75a57bc1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:53.719932529Z", "last_reviewed_by": [ @@ -9366,7 +9366,7 @@ ], "hash_code": "b037e71624f50f74cfbd0f0cd561daa1e87b1ac3690b19b1d3fe3c36ef452628", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:53.879932529Z", "last_reviewed_by": [ @@ -9447,7 +9447,7 @@ ], "hash_code": "945eb840563ed9b29b08ff0838d391e775d2e45f26817ad0b321b41e608564cf", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:54.038932529Z", "last_reviewed_by": [ @@ -9528,7 +9528,7 @@ ], "hash_code": "6e270eb7494286a67571f0d33112e997365a0de45a119ef8199d270c32d806ab", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:54.193932529Z", "last_reviewed_by": [ @@ -9609,7 +9609,7 @@ ], "hash_code": "76a4b74903cac92c02f0d0c7eca32f417f6ce4a3fb04f16eff17cfc0e8f8df7f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:54.354932529Z", "last_reviewed_by": [ @@ -9690,7 +9690,7 @@ ], "hash_code": "3db6ca06969817d45acccd02c0ba65067c1e11e9d4d7c34c7301612e63b2f75a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:54.518932529Z", "last_reviewed_by": [ @@ -9771,7 +9771,7 @@ ], "hash_code": "66ad49b768c1dcb417d1047d6a3e134473f45969fdc41c529a37088dec29804e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:54.675932529Z", "last_reviewed_by": [ @@ -9852,7 +9852,7 @@ ], "hash_code": "174ea52e3d43e0e3089705762ecd259a74bdb4c592473a8c4615c8d37e840725", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:54.853932529Z", "last_reviewed_by": [ @@ -9933,7 +9933,7 @@ ], "hash_code": "cecce89612fa88ff6270b822a8840911536f983c5ab580f5e7df0ec93a95884a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:55.014932529Z", "last_reviewed_by": [ @@ -10014,7 +10014,7 @@ ], "hash_code": "afa0b4d8453f20629d5863f0cb1b8d4e31bf2e8c4476db973a78731ffcf08bd2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:55.173932529Z", "last_reviewed_by": [ @@ -10095,7 +10095,7 @@ ], "hash_code": "1aec22aeffa8b6201ad60b0a0d2b166ddbaefca6ab534bbc4d2a827bc02f5c20", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:55.331932529Z", "last_reviewed_by": [ @@ -10176,7 +10176,7 @@ ], "hash_code": "2a7f9ff0b80ef53370128384650fe897d773383109c7d171159cbfbc232476e2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:55.521932529Z", "last_reviewed_by": [ @@ -10257,7 +10257,7 @@ ], "hash_code": "bef5f29fc5d5f44cef3dd5db1aaeeb5f2e5d7480a197045e6d176f0ab26b5fa2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:55.720932529Z", "last_reviewed_by": [ @@ -10338,7 +10338,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:55.881932529Z", "last_reviewed_by": [ @@ -10419,7 +10419,7 @@ ], "hash_code": "2de5b8ed091eaaf750260b056239152b81363c790977699374b03d93e1d28551", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:56.090932529Z", "last_reviewed_by": [ @@ -10500,7 +10500,7 @@ ], "hash_code": "3173d904f9ac1a4779a3b5fd52f271e6a7871d6cb5387d2ced15025a4a15db93", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:56.261932529Z", "last_reviewed_by": [ @@ -10581,7 +10581,7 @@ ], "hash_code": "775723c89fdaed1cc6b85ecc489c028159d261e95e7ad4ad80d03ddd63bc99ea", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:56.418932529Z", "last_reviewed_by": [ @@ -10662,7 +10662,7 @@ ], "hash_code": "9e3aa3082f7d93e52f9bfe97630e9fd6f6c04c5791dd22505ab238d1a6bf9242", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:56.590932529Z", "last_reviewed_by": [ @@ -10743,7 +10743,7 @@ ], "hash_code": "2fe1558daec12a621f0504714bee44be8d382a57c7cdda160ddad8a2e8b8ca48", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:56.732932529Z", "last_reviewed_by": [ @@ -10824,7 +10824,7 @@ ], "hash_code": "5fb0f064b2f7098c57e1115b391bf7a6eb57feae63c2848b916a5b79dccf66f3", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:56.870932529Z", "last_reviewed_by": [ @@ -10905,7 +10905,7 @@ ], "hash_code": "86efaa45244686266a1c4f1aef52d60ce791dd4cb64feebe5b214db5838b8e06", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:57.016932529Z", "last_reviewed_by": [ @@ -10986,7 +10986,7 @@ ], "hash_code": "7d988ddc1b32f65ada9bd17516943b28e33458ea570ce92843bdb49e7a7e22fb", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:57.165932529Z", "last_reviewed_by": [ @@ -11067,7 +11067,7 @@ ], "hash_code": "1c24c0fc04774515bc6dc38386250282055e0585ae71b405586b552ca04b31c9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:57.339932529Z", "last_reviewed_by": [ @@ -11148,7 +11148,7 @@ ], "hash_code": "d68d7152bc4b3f069aa236ff41cab28da77d7e668b77cb4de10ae8bf7a2e85be", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:57.505932529Z", "last_reviewed_by": [ @@ -11229,7 +11229,7 @@ ], "hash_code": "84c57ed3e3723016b9425c8549bd0faab967538a59e072c2dc5c85974a72bf41", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:57.653932529Z", "last_reviewed_by": [ @@ -11310,7 +11310,7 @@ ], "hash_code": "2dc7787335253be93ebb64d3ad632116363f3a5821c070db4cc28c18a0eee09e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:57.806932529Z", "last_reviewed_by": [ @@ -11391,7 +11391,7 @@ ], "hash_code": "45fe7a9d8b946b2cbc6aaf8b5e36608cc629e5f388f91433664d3c2f19a29991", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:57.955932529Z", "last_reviewed_by": [ @@ -11472,7 +11472,7 @@ ], "hash_code": "6e5f6914b0e963152cff1f6b9fe1c39a2f177979e6885bdbac5bd88f1d40d8cd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:58.092932529Z", "last_reviewed_by": [ @@ -11553,7 +11553,7 @@ ], "hash_code": "763571cd8b09d88baae5cc8bc9d755e2401e204c335894933401186d14be3992", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:58.237932529Z", "last_reviewed_by": [ @@ -11634,7 +11634,7 @@ ], "hash_code": "508298807b8bd2787b58a49d31bd3f056293c7656e8936eb2e478b3636fa5e19", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:58.382932529Z", "last_reviewed_by": [ @@ -11715,7 +11715,7 @@ ], "hash_code": "1544a01109756bdb265135b3dbc4efca3a22c8d19fa9b50407c94760f04d5610", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:58.538932529Z", "last_reviewed_by": [ @@ -11796,7 +11796,7 @@ ], "hash_code": "d6251c8822044d55511b364098e264ca2113391d999c6aefe5c1cca3743e2f2d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:58.698932529Z", "last_reviewed_by": [ @@ -11877,7 +11877,7 @@ ], "hash_code": "f8234be5bed59174a5f1f4efef0acb152b788f55c1804e2abbc185fe69ceea31", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:58.854932529Z", "last_reviewed_by": [ @@ -11958,7 +11958,7 @@ ], "hash_code": "7d3502f71ea947677c3ae5e39ae8da99c7024c3820a1c546bbdfe3ea4a0fdfc0", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:59.012932529Z", "last_reviewed_by": [ @@ -12039,7 +12039,7 @@ ], "hash_code": "779b4fe3dd494b8c323ddb7cb879f60051ac263904a16ac65af5a210cf797c0b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:59.171932529Z", "last_reviewed_by": [ @@ -12120,7 +12120,7 @@ ], "hash_code": "326fbad527801598a49946804f53bff975023eeb4c7c992932611d45d0b46201", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:59.341932529Z", "last_reviewed_by": [ @@ -12201,7 +12201,7 @@ ], "hash_code": "d818b17afca02a70991162f0cf5fbb16d2fef322b72c5c77b4c32bd209b3dc02", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:59.498932529Z", "last_reviewed_by": [ @@ -12282,7 +12282,7 @@ ], "hash_code": "926d5bb4d3abbed178afd6c5ffb752e6774908ad90893262c187e71e3197f31d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:59.656932529Z", "last_reviewed_by": [ @@ -12363,7 +12363,7 @@ ], "hash_code": "cfa4c706348e59de8b65228daccc21474abf67877a50dec0efa031e947d2e3bd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:59.813932529Z", "last_reviewed_by": [ @@ -12444,7 +12444,7 @@ ], "hash_code": "b493926fdab24fe92c9c28363e72429e66631bd5056f574ddefb983212933d10", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:00:59.983932529Z", "last_reviewed_by": [ @@ -12525,7 +12525,7 @@ ], "hash_code": "40f3e776293c5c19ac7b521181adfef56ed09288fa417f519d1cc6071cba8a17", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:00.153932529Z", "last_reviewed_by": [ @@ -12606,7 +12606,7 @@ ], "hash_code": "8332e5bd42770868b5db865ca9017c31fcea5a91cff250c4341dc73ed5fdb6e6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:00.313932529Z", "last_reviewed_by": [ @@ -12687,7 +12687,7 @@ ], "hash_code": "641ba17f6201ed5f40524a90c0e0fc03d8a4731528be567b639362cef3f20ef2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:00.477932529Z", "last_reviewed_by": [ @@ -12768,7 +12768,7 @@ ], "hash_code": "c3fb1583f06a0ce7bee2084607680b357d63dd8f9cc56d5d09f0601a3c62a336", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:00.619932529Z", "last_reviewed_by": [ @@ -12849,7 +12849,7 @@ ], "hash_code": "11b43c1ce56100d6a92b74b27d6e6901f3822b44c4b6e8437a7622f71c3a58a9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:00.770932529Z", "last_reviewed_by": [ @@ -12930,7 +12930,7 @@ ], "hash_code": "7a001d11b5d7d20f5215658fc735a31e530696faddeae3eacf81662d4870e89a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:00.915932529Z", "last_reviewed_by": [ @@ -13011,7 +13011,7 @@ ], "hash_code": "dc13f474e6f512cb31374bfa4658ce7a866d6b832d40742e784ef14f6513ab87", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:01.056932529Z", "last_reviewed_by": [ @@ -13092,7 +13092,7 @@ ], "hash_code": "63f306f6577c64ad2d38ddd3985cc649b11dd360f7a962e98cb63686c89b2b95", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:01.195932529Z", "last_reviewed_by": [ @@ -13173,7 +13173,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:01.348932529Z", "last_reviewed_by": [ @@ -13254,7 +13254,7 @@ ], "hash_code": "5b24a32f74c75879a1adc65bf89b03bb64f81565dbd6a2240149f2ce1bd27d40", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:01.506932529Z", "last_reviewed_by": [ @@ -13335,7 +13335,7 @@ ], "hash_code": "08569015fcc466a18ab405324d0dfe6af4b141110e47b73226ea117ecd44ff10", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:01.680932529Z", "last_reviewed_by": [ @@ -13416,7 +13416,7 @@ ], "hash_code": "fd480c121d5e26af3fb8c7ec89137aab25d86e44ff154f5aae742384cf80a2dd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:01.839932529Z", "last_reviewed_by": [ @@ -13497,7 +13497,7 @@ ], "hash_code": "b755a0cc07b69b72eb284df102459af7c502318c53c769999ec925d0da354d44", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:02.023932529Z", "last_reviewed_by": [ @@ -13578,7 +13578,7 @@ ], "hash_code": "70d68584520c7bc1b47ca45fc75b42460659a52957a10fe2a99858c32b329ae1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:02.225932529Z", "last_reviewed_by": [ @@ -13659,7 +13659,7 @@ ], "hash_code": "920ba1bf2ab979534eda06dd720ba0baa9cff2b1c14fd1ad56e89a5d656ed2f9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:02.452932529Z", "last_reviewed_by": [ @@ -13740,7 +13740,7 @@ ], "hash_code": "6bea74fa6a2e15eb4e272fd8033b63984cb1cfefd52189c7031b58d7bd325f44", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:02.626932529Z", "last_reviewed_by": [ @@ -13821,7 +13821,7 @@ ], "hash_code": "97e071423b295531965759c3641effa4a92e8e67f5ae40a3248a0a296aada52d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:02.807932529Z", "last_reviewed_by": [ @@ -13902,7 +13902,7 @@ ], "hash_code": "810541dc4d59d52088c1c29bfbb5ed70b10bfa657980a3099b26ff8799955f28", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:02.978932529Z", "last_reviewed_by": [ @@ -13983,7 +13983,7 @@ ], "hash_code": "eba9a993ff2b55ebdda24cb3c0fbc777bd7bcf038a01463f56b2f472f5a95296", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:03.128932529Z", "last_reviewed_by": [ @@ -14064,7 +14064,7 @@ ], "hash_code": "af0420cc3c001e6a1c65aceb86644080bcdb3f08b6be7cfc96a3bb3e20685afb", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:03.273932529Z", "last_reviewed_by": [ @@ -14145,7 +14145,7 @@ ], "hash_code": "78ceea05b00023deec3b210877d332bf03d07b237e8339f508a18c62b1146f88", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:03.434932529Z", "last_reviewed_by": [ @@ -14226,7 +14226,7 @@ ], "hash_code": "9384efff38eaa33266a2f5888dea18392a0e8b658b770fcfed268f06d3a1052d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:03.588932529Z", "last_reviewed_by": [ @@ -14307,7 +14307,7 @@ ], "hash_code": "93595b491f79115f85df3ef403cfc4ecd34e22dedf95aa24fbc18f56039d26f3", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:03.729932529Z", "last_reviewed_by": [ @@ -14388,7 +14388,7 @@ ], "hash_code": "ebfe755d6f8f91724d9d8a0672c12dce0200f818bce80b7fcaab30987b124a99", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:03.892932529Z", "last_reviewed_by": [ @@ -14469,7 +14469,7 @@ ], "hash_code": "584b05859f76b43b2736a28ac1c8ac88497704d0f31868218fcda9077396a215", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:04.038932529Z", "last_reviewed_by": [ @@ -14550,7 +14550,7 @@ ], "hash_code": "b1306a4177b37bad4dbe763419df19ec56d7442262be5dfeff6d346b3b900ad1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:04.195932529Z", "last_reviewed_by": [ @@ -14631,7 +14631,7 @@ ], "hash_code": "59304c367c39a7f0983c4ef2f90a13207866a37422ff5cc03db07d0efe46aed2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:04.350932529Z", "last_reviewed_by": [ @@ -14712,7 +14712,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:04.529932529Z", "last_reviewed_by": [ @@ -14793,7 +14793,7 @@ ], "hash_code": "28820e0352bb80a1d3c1085204cfeb522ddd29ee680ae46350260bf63359646f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:04.695932529Z", "last_reviewed_by": [ @@ -14874,7 +14874,7 @@ ], "hash_code": "ee16024c2d5962d243c878bf4f638147a8f879f05d969855c13d083aafab9fa8", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:04.841932529Z", "last_reviewed_by": [ @@ -14955,7 +14955,7 @@ ], "hash_code": "ce6c5523b17b77be323a526e757f04235f6d8a3023ac5208b12b7c34de4fcbb6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:04.994932529Z", "last_reviewed_by": [ @@ -15036,7 +15036,7 @@ ], "hash_code": "85b4b54f401f88fb286b6442b56fecb5922a025504207d94f5835e4b9e4c3d49", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:05.142932529Z", "last_reviewed_by": [ @@ -15117,7 +15117,7 @@ ], "hash_code": "371010ba334ccc433d73bf0c9cdaec557d5f7ec338c6f925d8a71763a228d473", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:05.329932529Z", "last_reviewed_by": [ @@ -15198,7 +15198,7 @@ ], "hash_code": "ea8b569d6c5fe9dba625c6540acd9880534f7a19a5bf4b84fb838ad65d08d26f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:05.507932529Z", "last_reviewed_by": [ @@ -15279,7 +15279,7 @@ ], "hash_code": "d0e517ef410747c79f882b9fc73a04a92ef6b4792017378ae5c4a39e21a921c5", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:01:05.686932529Z", "last_reviewed_by": [ @@ -15360,7 +15360,7 @@ ], "hash_code": "c49c87192b6b4f17151a471fd9d1bf3b302bca08781d67806c6556fe720af1b0", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:38.235932529Z", "last_reviewed_by": [ @@ -15441,7 +15441,7 @@ ], "hash_code": "a9c3269038ed8a49c4e7576b359f61a65a3bd82c163089bc20743e5a14aa0ab5", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:38.402932529Z", "last_reviewed_by": [ @@ -15522,7 +15522,7 @@ ], "hash_code": "418f79f7a59a306d5e46aa4af1924b64200aed234ae994dcd66485eb30bbe869", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:38.573932529Z", "last_reviewed_by": [ @@ -15603,7 +15603,7 @@ ], "hash_code": "21c80d580d9f1de55f6179e2a08e5684f46c9734d79cf701b2ff25e6776ccdfc", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:38.755932529Z", "last_reviewed_by": [ @@ -15684,7 +15684,7 @@ ], "hash_code": "fffd29bd0973269ddbbed2e210926c04d42cb12037117261626b95bd52bcff27", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:38.916932529Z", "last_reviewed_by": [ @@ -15765,7 +15765,7 @@ ], "hash_code": "3406086ac5988ee8b55f70c618daf86c21702bb3c4c00e4607e5c21c2e3d3828", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:39.103932529Z", "last_reviewed_by": [ @@ -15846,7 +15846,7 @@ ], "hash_code": "24e74e8be8b222cf0b17c034d03c5b43a130c2b960095eb44c55f470e50f6924", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:39.277932529Z", "last_reviewed_by": [ @@ -15927,7 +15927,7 @@ ], "hash_code": "a91b30b026cda759c2608e1c8216cdd13e265c030b8c47f4690cd2182e4ad166", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:39.448932529Z", "last_reviewed_by": [ @@ -16008,7 +16008,7 @@ ], "hash_code": "bfd9b74841c8d988d57c99353742f1e3180934ca6be2149a3fb7377329b57b33", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:39.615932529Z", "last_reviewed_by": [ @@ -16089,7 +16089,7 @@ ], "hash_code": "9b003338465e31c37f36b2a2d9b01bf9003d1d2631e2c409b3d19d02c93a20b6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:39.790932529Z", "last_reviewed_by": [ @@ -16170,7 +16170,7 @@ ], "hash_code": "684ee38b55ea509e6c2be4a58ec52ba5d7e0c1952e09f8c8ca2bf0675650bd8f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:39.962932529Z", "last_reviewed_by": [ @@ -16251,7 +16251,7 @@ ], "hash_code": "99fb15b31049df2445ac3fd8729cbccbc6a19e4e410c3eb0ef95908c00b78fd7", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:40.116932529Z", "last_reviewed_by": [ @@ -16332,7 +16332,7 @@ ], "hash_code": "541eb71776b2d297f9aa790c52297b4f7d26acb0bce7de33bda136fdefe43cb7", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:40.284932529Z", "last_reviewed_by": [ @@ -16413,7 +16413,7 @@ ], "hash_code": "e5ac755dbe3bfd23995c8d5a99779d188440c9e573d79b44130d90468d41439c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:40.473932529Z", "last_reviewed_by": [ @@ -16494,7 +16494,7 @@ ], "hash_code": "da32068a6442ce061d43625863d27f5e6346929f2b1d15b750df9d7b4bdb3597", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:40.624932529Z", "last_reviewed_by": [ @@ -16575,7 +16575,7 @@ ], "hash_code": "b0de3516ab323f5577e6ad94803e2ddf541214bbae868bf34e828ba3a4d966ca", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:40.774932529Z", "last_reviewed_by": [ @@ -16656,7 +16656,7 @@ ], "hash_code": "13ceb3acfb49f194493bfb0af44f5f886a9767aa1c6990c8a397af756d97209c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:40.915932529Z", "last_reviewed_by": [ @@ -16737,7 +16737,7 @@ ], "hash_code": "8d7b5f3962f521cd5c2dc40e4ef9a7cc10cfc30efb90f4b5841e8e5463656c61", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:41.062932529Z", "last_reviewed_by": [ @@ -16818,7 +16818,7 @@ ], "hash_code": "2237f06cb695ec1da91d51cab9fb037d8a9e84f1aa9ddbfeef59eef1a65af47e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:41.205932529Z", "last_reviewed_by": [ @@ -16899,7 +16899,7 @@ ], "hash_code": "05880cd0576bed75819cae74abce873fdcce5f857ec95d937a458b0ca0a49195", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:41.374932529Z", "last_reviewed_by": [ @@ -16980,7 +16980,7 @@ ], "hash_code": "9ec4ce27f48767b96297ef3cb8eabba1814ea08a02801692a669540c5a7ce019", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:41.520932529Z", "last_reviewed_by": [ @@ -17061,7 +17061,7 @@ ], "hash_code": "fc95b0887dc03b9f29f45b95aeb41e7f681dc28388279d7e11c233d3b5235c00", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:41.677932529Z", "last_reviewed_by": [ @@ -17142,7 +17142,7 @@ ], "hash_code": "bae03653ab0823182626d77d8ba94f2fab26eccdde7bcb11ddd0fb8dee79d717", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:41.836932529Z", "last_reviewed_by": [ @@ -17223,7 +17223,7 @@ ], "hash_code": "ae4e2ef51220be9b4ca71ee34ae9d174d093e6dd2da41951bc4ad2139a4dad3f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:41.999932529Z", "last_reviewed_by": [ @@ -17304,7 +17304,7 @@ ], "hash_code": "c69d0a9ead39b5990a429c6ed185050ffadfda672b020ac6e7322ef02e72563a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:42.151932529Z", "last_reviewed_by": [ @@ -17385,7 +17385,7 @@ ], "hash_code": "51b52607f2a5915cd128ba4e24ce8e22ba019757f074a0ebc27c33d91a55378b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:42.305932529Z", "last_reviewed_by": [ @@ -17466,7 +17466,7 @@ ], "hash_code": "d947020e418c747ee99a0accd491030f65895189aefea2a96a390b3e843a9905", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:42.446932529Z", "last_reviewed_by": [ @@ -17547,7 +17547,7 @@ ], "hash_code": "b29d81fdf7a5477a7badd1a47406a27deb12b90d0b3db17f567344d1ec24e65c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:42.598932529Z", "last_reviewed_by": [ @@ -17628,7 +17628,7 @@ ], "hash_code": "514c8fbd9da03f03f770c9e0ca12d8bb20db50f3a836b4d50f16e0d75b0cca08", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:42.747932529Z", "last_reviewed_by": [ @@ -17709,7 +17709,7 @@ ], "hash_code": "0441fee04d6e24c168f5b4b567cc31174f464330f27638f83f80ee87d0d3dc03", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:42.899932529Z", "last_reviewed_by": [ @@ -17790,7 +17790,7 @@ ], "hash_code": "7be257602d73f6146bbd1c6c4ab4970db0867933a1d2e87675770529b841d800", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:43.053932529Z", "last_reviewed_by": [ @@ -17871,7 +17871,7 @@ ], "hash_code": "ff922242dd15286d81f09888a33ad571eca598b615bf4d4b9024af17df42bc17", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:43.198932529Z", "last_reviewed_by": [ @@ -17952,7 +17952,7 @@ ], "hash_code": "964aeee36e5998da77d3229f43830d362838d860d9e30c415fb58e9686a49625", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:43.350932529Z", "last_reviewed_by": [ @@ -18033,7 +18033,7 @@ ], "hash_code": "e57ed13a66f4041fa377af4db5110a50a8f4a67e0c7c2b3e955e4118844a2904", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:43.502932529Z", "last_reviewed_by": [ @@ -18114,7 +18114,7 @@ ], "hash_code": "8fc3621137e4dd32d75801ac6948909b20f671d21ed9dfe89d0e2f49a2554653", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:43.672932529Z", "last_reviewed_by": [ @@ -18195,7 +18195,7 @@ ], "hash_code": "3988a18fe8f515ab1f92c649f43f20d33e8e8692d00a9dc80f2863342b522698", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:43.832932529Z", "last_reviewed_by": [ @@ -18276,7 +18276,7 @@ ], "hash_code": "cfc58944e3181521dc3a9ec917dcb54d7a54ebbf3f0e8aaca7fec60a05485c63", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:43.997932529Z", "last_reviewed_by": [ @@ -18357,7 +18357,7 @@ ], "hash_code": "9878411e3b89bc832e58fa15e46d19e2e607309d3df9f152114d5ff62f95f0ce", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:44.153932529Z", "last_reviewed_by": [ @@ -18438,7 +18438,7 @@ ], "hash_code": "35055620006745673ffba1cb3c1e8c09a9fd59f6438e6d45fbbb222a10968120", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:44.318932529Z", "last_reviewed_by": [ @@ -18519,7 +18519,7 @@ ], "hash_code": "60fff62e2e1d2383da91886a96d64905e184a3044037dc2595c3ccf28faacd6c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:44.509932529Z", "last_reviewed_by": [ @@ -18600,7 +18600,7 @@ ], "hash_code": "c81c73f4bd1bb970a016bd7e5f1979af8d05eac71f387b2da9bd4affcaf13f81", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:44.681932529Z", "last_reviewed_by": [ @@ -18681,7 +18681,7 @@ ], "hash_code": "1e74e0c4e0572c6bb5aaee26176b8a40ce024325bbffea1ddbb120bab9d9542c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:44.843932529Z", "last_reviewed_by": [ @@ -18762,7 +18762,7 @@ ], "hash_code": "4568d7e34ac50ab291c955c8acb368e5abe73de05bd3080e2efc7b00f329600f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:45.022932529Z", "last_reviewed_by": [ @@ -18843,7 +18843,7 @@ ], "hash_code": "1f91fef184e69387463ce9719fe9756145e16e76d39609aa5fa3e0eaa1274d05", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:45.184932529Z", "last_reviewed_by": [ @@ -18924,7 +18924,7 @@ ], "hash_code": "75a93a572c186be5fe7f5221a64306b5b35dddf605b5e231ffc74442bd3728a4", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:45.380932529Z", "last_reviewed_by": [ @@ -19005,7 +19005,7 @@ ], "hash_code": "afd07fc450ae8609c93797c8fd893028f7d8a9841999facd0a08236696c05841", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:45.553932529Z", "last_reviewed_by": [ @@ -19086,7 +19086,7 @@ ], "hash_code": "78439e5edd436844bb6dc527f6effe0836b88b0fb946747b7f957da95b479fc2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:45.733932529Z", "last_reviewed_by": [ @@ -19167,7 +19167,7 @@ ], "hash_code": "92b54561d5d262a88920162ba7bf19fc0444975582be837047cab5d79c992447", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:45.915932529Z", "last_reviewed_by": [ @@ -19248,7 +19248,7 @@ ], "hash_code": "f24533b1fc628061c2037eb55ffe66aed6bfa2436fadaf6e424e4905ed238e21", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:46.069932529Z", "last_reviewed_by": [ @@ -19329,7 +19329,7 @@ ], "hash_code": "38321299050d31a3b8168316e30316d786236785a9c31427fb6f2631d3065a7c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:46.231932529Z", "last_reviewed_by": [ @@ -19410,7 +19410,7 @@ ], "hash_code": "24cd9b35200f9ca729fcccb8348baccd2ddfeee2f22177fd40e46931f8547659", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:46.410932529Z", "last_reviewed_by": [ @@ -19491,7 +19491,7 @@ ], "hash_code": "148a501a59e0d04eb52b5cd58b4d654b4a7883e8ad09dcd5801e775113a1000d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:46.578932529Z", "last_reviewed_by": [ @@ -19572,7 +19572,7 @@ ], "hash_code": "55040c9344c964843ff56e19ff1ef4892c9f93234a7a39578c81ed903dd03e08", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:46.737932529Z", "last_reviewed_by": [ @@ -19653,7 +19653,7 @@ ], "hash_code": "06cd6507296edca41e97d652a873c31230bf98fa8bdeab477fedb680ff606932", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:46.906932529Z", "last_reviewed_by": [ @@ -19734,7 +19734,7 @@ ], "hash_code": "62f3875efdcf326015adee1ecd85c4ecdca5bc9c4719e5c9177dff8b0afffa1f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:47.074932529Z", "last_reviewed_by": [ @@ -19815,7 +19815,7 @@ ], "hash_code": "0007a2df1ab7dc00f2144451d894f513c7d872e1153a0759982a8c866001cc02", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:47.285932529Z", "last_reviewed_by": [ @@ -19896,7 +19896,7 @@ ], "hash_code": "7dba1c0820d0f6017ca3333f7f9a8865a862604c4b13a1eed04666c6e364fa36", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:47.478932529Z", "last_reviewed_by": [ @@ -19977,7 +19977,7 @@ ], "hash_code": "95568708fa568cc74c7ef8279b87869ebc932305da1878dbb1b7597c75a57bc1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:47.682932529Z", "last_reviewed_by": [ @@ -20058,7 +20058,7 @@ ], "hash_code": "b037e71624f50f74cfbd0f0cd561daa1e87b1ac3690b19b1d3fe3c36ef452628", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:47.864932529Z", "last_reviewed_by": [ @@ -20139,7 +20139,7 @@ ], "hash_code": "945eb840563ed9b29b08ff0838d391e775d2e45f26817ad0b321b41e608564cf", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:48.053932529Z", "last_reviewed_by": [ @@ -20220,7 +20220,7 @@ ], "hash_code": "6e270eb7494286a67571f0d33112e997365a0de45a119ef8199d270c32d806ab", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:48.259932529Z", "last_reviewed_by": [ @@ -20301,7 +20301,7 @@ ], "hash_code": "76a4b74903cac92c02f0d0c7eca32f417f6ce4a3fb04f16eff17cfc0e8f8df7f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:48.452932529Z", "last_reviewed_by": [ @@ -20382,7 +20382,7 @@ ], "hash_code": "3db6ca06969817d45acccd02c0ba65067c1e11e9d4d7c34c7301612e63b2f75a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:48.627932529Z", "last_reviewed_by": [ @@ -20463,7 +20463,7 @@ ], "hash_code": "66ad49b768c1dcb417d1047d6a3e134473f45969fdc41c529a37088dec29804e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:48.826932529Z", "last_reviewed_by": [ @@ -20544,7 +20544,7 @@ ], "hash_code": "174ea52e3d43e0e3089705762ecd259a74bdb4c592473a8c4615c8d37e840725", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:49.019932529Z", "last_reviewed_by": [ @@ -20625,7 +20625,7 @@ ], "hash_code": "cecce89612fa88ff6270b822a8840911536f983c5ab580f5e7df0ec93a95884a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:49.191932529Z", "last_reviewed_by": [ @@ -20706,7 +20706,7 @@ ], "hash_code": "afa0b4d8453f20629d5863f0cb1b8d4e31bf2e8c4476db973a78731ffcf08bd2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:49.406932529Z", "last_reviewed_by": [ @@ -20787,7 +20787,7 @@ ], "hash_code": "1aec22aeffa8b6201ad60b0a0d2b166ddbaefca6ab534bbc4d2a827bc02f5c20", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:49.646932529Z", "last_reviewed_by": [ @@ -20868,7 +20868,7 @@ ], "hash_code": "2a7f9ff0b80ef53370128384650fe897d773383109c7d171159cbfbc232476e2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:49.844932529Z", "last_reviewed_by": [ @@ -20949,7 +20949,7 @@ ], "hash_code": "bef5f29fc5d5f44cef3dd5db1aaeeb5f2e5d7480a197045e6d176f0ab26b5fa2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:50.021932529Z", "last_reviewed_by": [ @@ -21030,7 +21030,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:50.182932529Z", "last_reviewed_by": [ @@ -21111,7 +21111,7 @@ ], "hash_code": "2de5b8ed091eaaf750260b056239152b81363c790977699374b03d93e1d28551", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:50.387932529Z", "last_reviewed_by": [ @@ -21192,7 +21192,7 @@ ], "hash_code": "3173d904f9ac1a4779a3b5fd52f271e6a7871d6cb5387d2ced15025a4a15db93", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:50.553932529Z", "last_reviewed_by": [ @@ -21273,7 +21273,7 @@ ], "hash_code": "775723c89fdaed1cc6b85ecc489c028159d261e95e7ad4ad80d03ddd63bc99ea", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:50.710932529Z", "last_reviewed_by": [ @@ -21354,7 +21354,7 @@ ], "hash_code": "9e3aa3082f7d93e52f9bfe97630e9fd6f6c04c5791dd22505ab238d1a6bf9242", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:50.859932529Z", "last_reviewed_by": [ @@ -21435,7 +21435,7 @@ ], "hash_code": "2fe1558daec12a621f0504714bee44be8d382a57c7cdda160ddad8a2e8b8ca48", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:51.055932529Z", "last_reviewed_by": [ @@ -21516,7 +21516,7 @@ ], "hash_code": "5fb0f064b2f7098c57e1115b391bf7a6eb57feae63c2848b916a5b79dccf66f3", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:51.214932529Z", "last_reviewed_by": [ @@ -21597,7 +21597,7 @@ ], "hash_code": "86efaa45244686266a1c4f1aef52d60ce791dd4cb64feebe5b214db5838b8e06", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:51.378932529Z", "last_reviewed_by": [ @@ -21678,7 +21678,7 @@ ], "hash_code": "7d988ddc1b32f65ada9bd17516943b28e33458ea570ce92843bdb49e7a7e22fb", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:51.547932529Z", "last_reviewed_by": [ @@ -21759,7 +21759,7 @@ ], "hash_code": "1c24c0fc04774515bc6dc38386250282055e0585ae71b405586b552ca04b31c9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:51.703932529Z", "last_reviewed_by": [ @@ -21840,7 +21840,7 @@ ], "hash_code": "d68d7152bc4b3f069aa236ff41cab28da77d7e668b77cb4de10ae8bf7a2e85be", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:51.910932529Z", "last_reviewed_by": [ @@ -21921,7 +21921,7 @@ ], "hash_code": "84c57ed3e3723016b9425c8549bd0faab967538a59e072c2dc5c85974a72bf41", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:52.084932529Z", "last_reviewed_by": [ @@ -22002,7 +22002,7 @@ ], "hash_code": "2dc7787335253be93ebb64d3ad632116363f3a5821c070db4cc28c18a0eee09e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:52.328932529Z", "last_reviewed_by": [ @@ -22083,7 +22083,7 @@ ], "hash_code": "45fe7a9d8b946b2cbc6aaf8b5e36608cc629e5f388f91433664d3c2f19a29991", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:52.522932529Z", "last_reviewed_by": [ @@ -22164,7 +22164,7 @@ ], "hash_code": "6e5f6914b0e963152cff1f6b9fe1c39a2f177979e6885bdbac5bd88f1d40d8cd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:52.695932529Z", "last_reviewed_by": [ @@ -22245,7 +22245,7 @@ ], "hash_code": "763571cd8b09d88baae5cc8bc9d755e2401e204c335894933401186d14be3992", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:52.870932529Z", "last_reviewed_by": [ @@ -22326,7 +22326,7 @@ ], "hash_code": "508298807b8bd2787b58a49d31bd3f056293c7656e8936eb2e478b3636fa5e19", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:53.052932529Z", "last_reviewed_by": [ @@ -22407,7 +22407,7 @@ ], "hash_code": "1544a01109756bdb265135b3dbc4efca3a22c8d19fa9b50407c94760f04d5610", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:53.222932529Z", "last_reviewed_by": [ @@ -22488,7 +22488,7 @@ ], "hash_code": "d6251c8822044d55511b364098e264ca2113391d999c6aefe5c1cca3743e2f2d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:53.405932529Z", "last_reviewed_by": [ @@ -22569,7 +22569,7 @@ ], "hash_code": "f8234be5bed59174a5f1f4efef0acb152b788f55c1804e2abbc185fe69ceea31", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:53.593932529Z", "last_reviewed_by": [ @@ -22650,7 +22650,7 @@ ], "hash_code": "7d3502f71ea947677c3ae5e39ae8da99c7024c3820a1c546bbdfe3ea4a0fdfc0", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:53.781932529Z", "last_reviewed_by": [ @@ -22731,7 +22731,7 @@ ], "hash_code": "779b4fe3dd494b8c323ddb7cb879f60051ac263904a16ac65af5a210cf797c0b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:54.175932529Z", "last_reviewed_by": [ @@ -22812,7 +22812,7 @@ ], "hash_code": "326fbad527801598a49946804f53bff975023eeb4c7c992932611d45d0b46201", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:54.442932529Z", "last_reviewed_by": [ @@ -22893,7 +22893,7 @@ ], "hash_code": "d818b17afca02a70991162f0cf5fbb16d2fef322b72c5c77b4c32bd209b3dc02", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:54.737932529Z", "last_reviewed_by": [ @@ -22974,7 +22974,7 @@ ], "hash_code": "926d5bb4d3abbed178afd6c5ffb752e6774908ad90893262c187e71e3197f31d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:55.008932529Z", "last_reviewed_by": [ @@ -23055,7 +23055,7 @@ ], "hash_code": "cfa4c706348e59de8b65228daccc21474abf67877a50dec0efa031e947d2e3bd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:55.231932529Z", "last_reviewed_by": [ @@ -23136,7 +23136,7 @@ ], "hash_code": "b493926fdab24fe92c9c28363e72429e66631bd5056f574ddefb983212933d10", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:55.426932529Z", "last_reviewed_by": [ @@ -23217,7 +23217,7 @@ ], "hash_code": "40f3e776293c5c19ac7b521181adfef56ed09288fa417f519d1cc6071cba8a17", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:55.626932529Z", "last_reviewed_by": [ @@ -23298,7 +23298,7 @@ ], "hash_code": "8332e5bd42770868b5db865ca9017c31fcea5a91cff250c4341dc73ed5fdb6e6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:55.856932529Z", "last_reviewed_by": [ @@ -23379,7 +23379,7 @@ ], "hash_code": "641ba17f6201ed5f40524a90c0e0fc03d8a4731528be567b639362cef3f20ef2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:56.073932529Z", "last_reviewed_by": [ @@ -23460,7 +23460,7 @@ ], "hash_code": "c3fb1583f06a0ce7bee2084607680b357d63dd8f9cc56d5d09f0601a3c62a336", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:56.308932529Z", "last_reviewed_by": [ @@ -23541,7 +23541,7 @@ ], "hash_code": "11b43c1ce56100d6a92b74b27d6e6901f3822b44c4b6e8437a7622f71c3a58a9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:56.509932529Z", "last_reviewed_by": [ @@ -23622,7 +23622,7 @@ ], "hash_code": "7a001d11b5d7d20f5215658fc735a31e530696faddeae3eacf81662d4870e89a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:56.732932529Z", "last_reviewed_by": [ @@ -23703,7 +23703,7 @@ ], "hash_code": "dc13f474e6f512cb31374bfa4658ce7a866d6b832d40742e784ef14f6513ab87", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:56.960932529Z", "last_reviewed_by": [ @@ -23784,7 +23784,7 @@ ], "hash_code": "63f306f6577c64ad2d38ddd3985cc649b11dd360f7a962e98cb63686c89b2b95", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:57.242932529Z", "last_reviewed_by": [ @@ -23865,7 +23865,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:57.493932529Z", "last_reviewed_by": [ @@ -23946,7 +23946,7 @@ ], "hash_code": "5b24a32f74c75879a1adc65bf89b03bb64f81565dbd6a2240149f2ce1bd27d40", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:57.719932529Z", "last_reviewed_by": [ @@ -24027,7 +24027,7 @@ ], "hash_code": "08569015fcc466a18ab405324d0dfe6af4b141110e47b73226ea117ecd44ff10", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:57.928932529Z", "last_reviewed_by": [ @@ -24108,7 +24108,7 @@ ], "hash_code": "fd480c121d5e26af3fb8c7ec89137aab25d86e44ff154f5aae742384cf80a2dd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:58.151932529Z", "last_reviewed_by": [ @@ -24189,7 +24189,7 @@ ], "hash_code": "b755a0cc07b69b72eb284df102459af7c502318c53c769999ec925d0da354d44", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:58.366932529Z", "last_reviewed_by": [ @@ -24270,7 +24270,7 @@ ], "hash_code": "70d68584520c7bc1b47ca45fc75b42460659a52957a10fe2a99858c32b329ae1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:58.585932529Z", "last_reviewed_by": [ @@ -24351,7 +24351,7 @@ ], "hash_code": "920ba1bf2ab979534eda06dd720ba0baa9cff2b1c14fd1ad56e89a5d656ed2f9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:58.790932529Z", "last_reviewed_by": [ @@ -24432,7 +24432,7 @@ ], "hash_code": "6bea74fa6a2e15eb4e272fd8033b63984cb1cfefd52189c7031b58d7bd325f44", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:58.941932529Z", "last_reviewed_by": [ @@ -24513,7 +24513,7 @@ ], "hash_code": "97e071423b295531965759c3641effa4a92e8e67f5ae40a3248a0a296aada52d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:59.097932529Z", "last_reviewed_by": [ @@ -24594,7 +24594,7 @@ ], "hash_code": "810541dc4d59d52088c1c29bfbb5ed70b10bfa657980a3099b26ff8799955f28", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:59.304932529Z", "last_reviewed_by": [ @@ -24675,7 +24675,7 @@ ], "hash_code": "eba9a993ff2b55ebdda24cb3c0fbc777bd7bcf038a01463f56b2f472f5a95296", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:59.486932529Z", "last_reviewed_by": [ @@ -24756,7 +24756,7 @@ ], "hash_code": "af0420cc3c001e6a1c65aceb86644080bcdb3f08b6be7cfc96a3bb3e20685afb", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:59.681932529Z", "last_reviewed_by": [ @@ -24837,7 +24837,7 @@ ], "hash_code": "78ceea05b00023deec3b210877d332bf03d07b237e8339f508a18c62b1146f88", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:02:59.880932529Z", "last_reviewed_by": [ @@ -24918,7 +24918,7 @@ ], "hash_code": "9384efff38eaa33266a2f5888dea18392a0e8b658b770fcfed268f06d3a1052d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:00.083932529Z", "last_reviewed_by": [ @@ -24999,7 +24999,7 @@ ], "hash_code": "93595b491f79115f85df3ef403cfc4ecd34e22dedf95aa24fbc18f56039d26f3", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:00.461932529Z", "last_reviewed_by": [ @@ -25080,7 +25080,7 @@ ], "hash_code": "ebfe755d6f8f91724d9d8a0672c12dce0200f818bce80b7fcaab30987b124a99", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:00.642932529Z", "last_reviewed_by": [ @@ -25161,7 +25161,7 @@ ], "hash_code": "584b05859f76b43b2736a28ac1c8ac88497704d0f31868218fcda9077396a215", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:00.849932529Z", "last_reviewed_by": [ @@ -25242,7 +25242,7 @@ ], "hash_code": "b1306a4177b37bad4dbe763419df19ec56d7442262be5dfeff6d346b3b900ad1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:01.057932529Z", "last_reviewed_by": [ @@ -25323,7 +25323,7 @@ ], "hash_code": "59304c367c39a7f0983c4ef2f90a13207866a37422ff5cc03db07d0efe46aed2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:01.271932529Z", "last_reviewed_by": [ @@ -25404,7 +25404,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:01.497932529Z", "last_reviewed_by": [ @@ -25485,7 +25485,7 @@ ], "hash_code": "28820e0352bb80a1d3c1085204cfeb522ddd29ee680ae46350260bf63359646f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:01.698932529Z", "last_reviewed_by": [ @@ -25566,7 +25566,7 @@ ], "hash_code": "ee16024c2d5962d243c878bf4f638147a8f879f05d969855c13d083aafab9fa8", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:01.914932529Z", "last_reviewed_by": [ @@ -25647,7 +25647,7 @@ ], "hash_code": "ce6c5523b17b77be323a526e757f04235f6d8a3023ac5208b12b7c34de4fcbb6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:02.132932529Z", "last_reviewed_by": [ @@ -25728,7 +25728,7 @@ ], "hash_code": "85b4b54f401f88fb286b6442b56fecb5922a025504207d94f5835e4b9e4c3d49", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:02.306932529Z", "last_reviewed_by": [ @@ -25809,7 +25809,7 @@ ], "hash_code": "371010ba334ccc433d73bf0c9cdaec557d5f7ec338c6f925d8a71763a228d473", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:02.467932529Z", "last_reviewed_by": [ @@ -25890,7 +25890,7 @@ ], "hash_code": "ea8b569d6c5fe9dba625c6540acd9880534f7a19a5bf4b84fb838ad65d08d26f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:02.645932529Z", "last_reviewed_by": [ @@ -25971,7 +25971,7 @@ ], "hash_code": "d0e517ef410747c79f882b9fc73a04a92ef6b4792017378ae5c4a39e21a921c5", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:02.798932529Z", "last_reviewed_by": [ @@ -26052,7 +26052,7 @@ ], "hash_code": "f6025b614c1d26ee95556ebcb50473f42a57f04d7653abfd132e98baff1b433e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:02.972932529Z", "last_reviewed_by": [ @@ -26133,7 +26133,7 @@ ], "hash_code": "5852c73c2309bcf533c51c4b6c8221b0519229d4010090067bd6ea629971c099", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:03.131932529Z", "last_reviewed_by": [ @@ -26214,7 +26214,7 @@ ], "hash_code": "39052e0796f538556f2cc6c00b63fbed65ab036a874c9ed0672e6825d68602a2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:03.311932529Z", "last_reviewed_by": [ @@ -26295,7 +26295,7 @@ ], "hash_code": "82b6e67fea88a46706b742dee6eb877a58f0ef800b00de81d044714ae2d83f6b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:03.494932529Z", "last_reviewed_by": [ @@ -26376,7 +26376,7 @@ ], "hash_code": "52d4696d8c8726e0689f91c534c78682a24d80d83406ac7c6d7c4f2952d7c25e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:03.692932529Z", "last_reviewed_by": [ @@ -26457,7 +26457,7 @@ ], "hash_code": "67622d1c580dd13b751a2f6684e3b1e764c0b2059520e9b6683c5b8a6560262a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:03.859932529Z", "last_reviewed_by": [ @@ -26538,7 +26538,7 @@ ], "hash_code": "a580f877f77e73dc81f13869c40402119ff4a964e2cc48fe4dcca3fb0a5e19a9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-10T06:03:04.047932529Z", "last_reviewed_by": [ @@ -26619,7 +26619,7 @@ ], "hash_code": "df2a6f6aba05f414f30448d0594c327f3f9e7f075bff0008820e10d95b4ff3d5", "impact": "asdf", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": null, "last_reviewed_by": null, @@ -26698,7 +26698,7 @@ ], "hash_code": "1dfa2d2c7161cea9a710a5cbe3e1bc7f0116625104edbe31d5de6260c82cf87a", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:43:46.785932529Z", "last_reviewed_by": [ @@ -26779,7 +26779,7 @@ ], "hash_code": "b080d22cc9797327aeebd0e6437057cf1ef61dd128fbe7059388b279c45915bb", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:43:47.063932529Z", "last_reviewed_by": [ @@ -26860,7 +26860,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:17.406932529Z", "last_reviewed_by": [ @@ -26941,7 +26941,7 @@ ], "hash_code": "6190df674dd45e3b28b65c30bfd11b02ef3331eaffecac12a6ee3db03c1de36a", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:17.600932529Z", "last_reviewed_by": [ @@ -27022,7 +27022,7 @@ ], "hash_code": "dfd30d76898319d2181e4464cd74c71ddaca8afe0008b9c94fac41f5420ed62c", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:17.780932529Z", "last_reviewed_by": [ @@ -27103,7 +27103,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:17.978932529Z", "last_reviewed_by": [ @@ -27184,7 +27184,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:18.157932529Z", "last_reviewed_by": [ @@ -27265,7 +27265,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:18.352932529Z", "last_reviewed_by": [ @@ -27346,7 +27346,7 @@ ], "hash_code": "6190df674dd45e3b28b65c30bfd11b02ef3331eaffecac12a6ee3db03c1de36a", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:18.542932529Z", "last_reviewed_by": [ @@ -27427,7 +27427,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:18.741932529Z", "last_reviewed_by": [ @@ -27508,7 +27508,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:18.947932529Z", "last_reviewed_by": [ @@ -27589,7 +27589,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:19.138932529Z", "last_reviewed_by": [ @@ -27670,7 +27670,7 @@ ], "hash_code": "dfd30d76898319d2181e4464cd74c71ddaca8afe0008b9c94fac41f5420ed62c", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:19.331932529Z", "last_reviewed_by": [ @@ -27751,7 +27751,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:19.500932529Z", "last_reviewed_by": [ @@ -27832,7 +27832,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:19.696932529Z", "last_reviewed_by": [ @@ -27913,7 +27913,7 @@ ], "hash_code": "dfd30d76898319d2181e4464cd74c71ddaca8afe0008b9c94fac41f5420ed62c", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:19.917932529Z", "last_reviewed_by": [ @@ -27994,7 +27994,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:20.081932529Z", "last_reviewed_by": [ @@ -28075,7 +28075,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:20.260932529Z", "last_reviewed_by": [ @@ -28156,7 +28156,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:20.437932529Z", "last_reviewed_by": [ @@ -28237,7 +28237,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:45:20.623932529Z", "last_reviewed_by": [ @@ -28318,7 +28318,7 @@ ], "hash_code": "cef2dcb7c7787157edc70e85d5017e72d1dbca1fd80909f5d76cda85a9bdec2c", "impact": "Most browsers have a facility to remember user credentials that are entered into HTML forms. This function can be configured by the user and also by applications that employ user credentials. If the function is enabled, then credentials entered by the user are stored on their local computer and retrieved by the browser on future visits to the same application.\n\nThe stored credentials can be captured by an attacker who gains control over the user's computer. Further, an attacker who finds a separate application vulnerability such as cross-site scripting may be able to exploit this to retrieve a user's browser-stored credentials. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -28399,7 +28399,7 @@ ], "hash_code": "e2a968190c3c79023378ef6f30612b6119bc867f303aafc91eb3bd191d05b90d", "impact": "If a page fails to set an appropriate X-Frame-Options or Content-Security-Policy HTTP header, it might be possible for a page controlled by an attacker to load it within an iframe. This may enable a clickjacking attack, in which the attacker's page overlays the target application's interface with a different interface provided by the attacker. By inducing victim users to perform actions such as mouse clicks and keystrokes, the attacker can cause them to unwittingly carry out actions within the application that is being targeted. This technique allows the attacker to circumvent defenses against cross-site request forgery, and may result in unauthorized actions.\n\nNote that some applications attempt to prevent these attacks from within the HTML page itself, using \"framebusting\" code. However, this type of defense is normally ineffective and can usually be circumvented by a skilled attacker.\n\nYou should determine whether any functions accessible within frameable pages can be used by application users to perform any sensitive actions within the application. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -28480,7 +28480,7 @@ ], "hash_code": "d0353a775431e2fcf6ba2245bba4a11a68a0961e4f6baba21095c56e4c52287c", "impact": "Reflected cross-site scripting vulnerabilities arise when data is copied from a request and echoed into the application's immediate response in an unsafe way. An attacker can use the vulnerability to construct a request that, if issued by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application.\n\nThe attacker-supplied code can perform a wide variety of actions, such as stealing the victim's session token or login credentials, performing arbitrary actions on the victim's behalf, and logging their keystrokes.\n\nUsers can be induced to issue the attacker's crafted request in various ways. For example, the attacker can send a victim a link containing a malicious URL in an email or instant message. They can submit the link to popular web sites that allow content authoring, for example in blog comments. And they can create an innocuous looking web site that causes anyone viewing it to make arbitrary cross-domain requests to the vulnerable application (using either the GET or the POST method).\n\nThe security impact of cross-site scripting vulnerabilities is dependent upon the nature of the vulnerable application, the kinds of data and functionality that it contains, and the other applications that belong to the same domain and organization. If the application is used only to display non-sensitive public content, with no authentication or access control functionality, then a cross-site scripting flaw may be considered low risk. However, if the same application resides on a domain that can access cookies for other more security-critical applications, then the vulnerability could be used to attack those other applications, and so may be considered high risk. Similarly, if the organization that owns the application is a likely target for phishing attacks, then the vulnerability could be leveraged to lend credibility to such attacks, by injecting Trojan functionality into the vulnerable application and exploiting users' trust in the organization in order to capture credentials for other applications that it owns. In many kinds of application, such as those providing online banking functionality, cross-site scripting should always be considered high risk. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -28561,7 +28561,7 @@ ], "hash_code": "7b79656db5b18827a177cdef000720f62cf139c43bfbb8f1f6c2e1382e28b503", "impact": "The application allows users to connect to it over unencrypted connections. An attacker suitably positioned to view a legitimate user's network traffic could record and monitor their interactions with the application and obtain any information the user supplies. Furthermore, an attacker able to modify traffic could use the application as a platform for attacks against its users and third-party websites. Unencrypted connections have been exploited by ISPs and governments to track users, and to inject adverts and malicious JavaScript. Due to these concerns, web browser vendors are planning to visually flag unencrypted connections as hazardous.\n\nTo exploit this vulnerability, an attacker must be suitably positioned to eavesdrop on the victim's network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure. \n\nPlease note that using a mixture of encrypted and unencrypted communications is an ineffective defense against active attackers, because they can easily remove references to encrypted resources when these references are transmitted over an unencrypted connection.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -28642,7 +28642,7 @@ ], "hash_code": "a073a661ec300f853780ebd20d17abefb6c3bcf666776ddea1ab2e3e3c6d9428", "impact": "Some applications return passwords submitted to the application in clear form in later responses. This behavior increases the risk that users' passwords will be captured by an attacker. Many types of vulnerability, such as weaknesses in session handling, broken access controls, and cross-site scripting, could enable an attacker to leverage this behavior to retrieve the passwords of other application users. This possibility typically exacerbates the impact of those other vulnerabilities, and in some situations can enable an attacker to quickly compromise the entire application.\n\nVulnerabilities that result in the disclosure of users' passwords can result in compromises that are extremely difficult to investigate due to obscured audit trails. Even if the application itself only handles non-sensitive information, exposing passwords puts users who have re-used their password elsewhere at risk.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -28723,7 +28723,7 @@ ], "hash_code": "2b9640feda092762b423f98809677e58d24ccd79c948df2e052d3f22274ebe8f", "impact": "The presence of email addresses within application responses does not necessarily constitute a security vulnerability. Email addresses may appear intentionally within contact information, and many applications (such as web mail) include arbitrary third-party email addresses within their core content.\n\nHowever, email addresses of developers and other individuals (whether appearing on-screen or hidden within page source) may disclose information that is useful to an attacker; for example, they may represent usernames that can be used at the application's login, and they may be used in social engineering attacks against the organization's personnel. Unnecessary or excessive disclosure of email addresses may also lead to an increase in the volume of spam email received.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -28804,7 +28804,7 @@ ], "hash_code": "1c732e92e6e9b89c90bd4ef40579d4c06791cc635e6fb16c00f2d443c5922ffa", "impact": "Cross-site request forgery (CSRF) vulnerabilities may arise when applications rely solely on HTTP cookies to identify the user that has issued a particular request. Because browsers automatically add cookies to requests regardless of their origin, it may be possible for an attacker to create a malicious web site that forges a cross-domain request to the vulnerable application. For a request to be vulnerable to CSRF, the following conditions must hold:\n\n * The request can be issued cross-domain, for example using an HTML form. If the request contains non-standard headers or body content, then it may only be issuable from a page that originated on the same domain.\n * The application relies solely on HTTP cookies or Basic Authentication to identify the user that issued the request. If the application places session-related tokens elsewhere within the request, then it may not be vulnerable.\n * The request performs some privileged action within the application, which modifies the application's state based on the identity of the issuing user.\n * The attacker can determine all the parameters required to construct a request that performs the action. If the request contains any values that the attacker cannot determine or predict, then it is not vulnerable.\n\n\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -28885,7 +28885,7 @@ ], "hash_code": "31215cff140491cdd84abb9246ad91145069efda2bdb319b75e2ee916219178a", "impact": "SQL injection vulnerabilities arise when user-controllable data is incorporated into database SQL queries in an unsafe manner. An attacker can supply crafted input to break out of the data context in which their input appears and interfere with the structure of the surrounding query.\n\nA wide range of damaging attacks can often be delivered via SQL injection, including reading or modifying critical application data, interfering with application logic, escalating privileges within the database and taking control of the database server. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -28966,7 +28966,7 @@ ], "hash_code": "e2a968190c3c79023378ef6f30612b6119bc867f303aafc91eb3bd191d05b90d", "impact": "Path-relative style sheet import vulnerabilities arise when the following conditions hold:\n\n 1. A response contains a style sheet import that uses a path-relative URL (for example, the page at \"/original-path/file.php\" might import \"styles/main.css\").\n 2. When handling requests, the application or platform tolerates superfluous path-like data following the original filename in the URL (for example, \"/original-path/file.php/extra-junk/\"). When superfluous data is added to the original URL, the application's response still contains a path-relative stylesheet import.\n 3. The response in condition 2 can be made to render in a browser's quirks mode, either because it has a missing or old doctype directive, or because it allows itself to be framed by a page under an attacker's control.\n 4. When a browser requests the style sheet that is imported in the response from the modified URL (using the URL \"/original-path/file.php/extra-junk/styles/main.css\"), the application returns something other than the CSS response that was supposed to be imported. Given the behavior described in condition 2, this will typically be the same response that was originally returned in condition 1.\n 5. An attacker has a means of manipulating some text within the response in condition 4, for example because the application stores and displays some past input, or echoes some text within the current URL.\n\n\n\nGiven the above conditions, an attacker can execute CSS injection within the browser of the target user. The attacker can construct a URL that causes the victim's browser to import as CSS a different URL than normal, containing text that the attacker can manipulate. Being able to inject arbitrary CSS into the victim's browser may enable various attacks, including:\n\n * Executing arbitrary JavaScript using IE's expression() function.\n * Using CSS selectors to read parts of the HTML source, which may include sensitive data such as anti-CSRF tokens.\n * Capturing any sensitive data within the URL query string by making a further style sheet import to a URL on the attacker's domain, and monitoring the incoming Referer header.\n\n\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -29047,7 +29047,7 @@ ], "hash_code": "cef2dcb7c7787157edc70e85d5017e72d1dbca1fd80909f5d76cda85a9bdec2c", "impact": "Some applications transmit passwords over unencrypted connections, making them vulnerable to interception. To exploit this vulnerability, an attacker must be suitably positioned to eavesdrop on the victim's network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure.\n\nVulnerabilities that result in the disclosure of users' passwords can result in compromises that are extremely difficult to investigate due to obscured audit trails. Even if the application itself only handles non-sensitive information, exposing passwords puts users who have re-used their password elsewhere at risk.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T03:46:49.510932529Z", "last_reviewed_by": [ @@ -29128,7 +29128,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:28.990932529Z", "last_reviewed_by": [ @@ -29209,7 +29209,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:29.243932529Z", "last_reviewed_by": [ @@ -29290,7 +29290,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:29.516932529Z", "last_reviewed_by": [ @@ -29371,7 +29371,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:29.739932529Z", "last_reviewed_by": [ @@ -29452,7 +29452,7 @@ ], "hash_code": "929fb1c92b7a2aeeca7affb985361e279334bf9c72f1dd1e6120cfc134198ddd", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2025-11-06T23:46:52Z", "last_reviewed_by": [ @@ -29533,7 +29533,7 @@ ], "hash_code": "58ce5492f2393592d59ae209ae350b52dc807c0418ebb0f7421c428dba7ce6a5", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:30.125932529Z", "last_reviewed_by": [ @@ -29614,7 +29614,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:30.335932529Z", "last_reviewed_by": [ @@ -29695,7 +29695,7 @@ ], "hash_code": "847363e3519e008224db4a0be2e123b779d1d7e8e9a26c9ff7fb09a1f8e010af", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:30.544932529Z", "last_reviewed_by": [ @@ -29776,7 +29776,7 @@ ], "hash_code": "01b1dd016d858a85a8d6ff3b60e68d5073f35b3d853c8cc076c2a65b22ddd37f", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:30.774932529Z", "last_reviewed_by": [ @@ -29857,7 +29857,7 @@ ], "hash_code": "493bcf78ff02a621a02c282a3f85008d5c2d9aeaea342252083d3f66af9895b4", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:30.980932529Z", "last_reviewed_by": [ @@ -29938,7 +29938,7 @@ ], "hash_code": "a1db5cdf4a0ef0f4b09c2e5205dd5d8ccb3522f5d0c92892c52f5bc2f81407ab", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:31.172932529Z", "last_reviewed_by": [ @@ -30019,7 +30019,7 @@ ], "hash_code": "0e0592103f29773f1fcf3ec4d2bbadd094b71c0ed693fd7f437f21b1a7f466de", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:31.364932529Z", "last_reviewed_by": [ @@ -30100,7 +30100,7 @@ ], "hash_code": "0e0592103f29773f1fcf3ec4d2bbadd094b71c0ed693fd7f437f21b1a7f466de", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:31.557932529Z", "last_reviewed_by": [ @@ -30181,7 +30181,7 @@ ], "hash_code": "2573d64a8468fbbc714c4aa527a5e4f25c8283cbc2b538150e9405141fa47a95", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:31.734932529Z", "last_reviewed_by": [ @@ -30262,7 +30262,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:31.928932529Z", "last_reviewed_by": [ @@ -30343,7 +30343,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:32.115932529Z", "last_reviewed_by": [ @@ -30424,7 +30424,7 @@ ], "hash_code": "6a2543c093ae3492085ed185e29728240264e6b42d20e2594afa0e3bde0df7ed", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:32.292932529Z", "last_reviewed_by": [ @@ -30505,7 +30505,7 @@ ], "hash_code": "6a2543c093ae3492085ed185e29728240264e6b42d20e2594afa0e3bde0df7ed", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:32.485932529Z", "last_reviewed_by": [ @@ -30586,7 +30586,7 @@ ], "hash_code": "409f83523798dff3b0158749c30b73728e1d3b193b51ee6cd1c6cd37c372d692", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:32.667932529Z", "last_reviewed_by": [ @@ -30667,7 +30667,7 @@ ], "hash_code": "822e39e3de094312f76b22d54357c8d7bbd9b015150b89e2664d45a9bba989e1", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:32.854932529Z", "last_reviewed_by": [ @@ -30748,7 +30748,7 @@ ], "hash_code": "1569ac5fdd45a35ee5a0d1b93c485a834fbdc4fb9b73ad56414335ad9bd862ca", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:33.047932529Z", "last_reviewed_by": [ @@ -30829,7 +30829,7 @@ ], "hash_code": "9b2ac951d86e5d4cd419cabdea51aca6a3aaadef4bae8683c655bdba8427669a", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:33.232932529Z", "last_reviewed_by": [ @@ -30910,7 +30910,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:33.474932529Z", "last_reviewed_by": [ @@ -30991,7 +30991,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:33.697932529Z", "last_reviewed_by": [ @@ -31072,7 +31072,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:33.912932529Z", "last_reviewed_by": [ @@ -31153,7 +31153,7 @@ ], "hash_code": "27a0fde11f7ea3c405d889bde32e8fe532dc07017d6329af39726761aca0a5aa", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:34.126932529Z", "last_reviewed_by": [ @@ -31234,7 +31234,7 @@ ], "hash_code": "a1db5cdf4a0ef0f4b09c2e5205dd5d8ccb3522f5d0c92892c52f5bc2f81407ab", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:34.412932529Z", "last_reviewed_by": [ @@ -31315,7 +31315,7 @@ ], "hash_code": "2f4ca826c1093b3fc8c55005f600410d9626704312a6a958544393f936ef9a66", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T04:06:34.643932529Z", "last_reviewed_by": [ @@ -31396,7 +31396,7 @@ ], "hash_code": "cef2dcb7c7787157edc70e85d5017e72d1dbca1fd80909f5d76cda85a9bdec2c", "impact": "Most browsers have a facility to remember user credentials that are entered into HTML forms. This function can be configured by the user and also by applications that employ user credentials. If the function is enabled, then credentials entered by the user are stored on their local computer and retrieved by the browser on future visits to the same application.\n\nThe stored credentials can be captured by an attacker who gains control over the user's computer. Further, an attacker who finds a separate application vulnerability such as cross-site scripting may be able to exploit this to retrieve a user's browser-stored credentials. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:16.869932529Z", "last_reviewed_by": [ @@ -31477,7 +31477,7 @@ ], "hash_code": "e2a968190c3c79023378ef6f30612b6119bc867f303aafc91eb3bd191d05b90d", "impact": "If a page fails to set an appropriate X-Frame-Options or Content-Security-Policy HTTP header, it might be possible for a page controlled by an attacker to load it within an iframe. This may enable a clickjacking attack, in which the attacker's page overlays the target application's interface with a different interface provided by the attacker. By inducing victim users to perform actions such as mouse clicks and keystrokes, the attacker can cause them to unwittingly carry out actions within the application that is being targeted. This technique allows the attacker to circumvent defenses against cross-site request forgery, and may result in unauthorized actions.\n\nNote that some applications attempt to prevent these attacks from within the HTML page itself, using \"framebusting\" code. However, this type of defense is normally ineffective and can usually be circumvented by a skilled attacker.\n\nYou should determine whether any functions accessible within frameable pages can be used by application users to perform any sensitive actions within the application. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:17.159932529Z", "last_reviewed_by": [ @@ -31558,7 +31558,7 @@ ], "hash_code": "d0353a775431e2fcf6ba2245bba4a11a68a0961e4f6baba21095c56e4c52287c", "impact": "Reflected cross-site scripting vulnerabilities arise when data is copied from a request and echoed into the application's immediate response in an unsafe way. An attacker can use the vulnerability to construct a request that, if issued by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application.\n\nThe attacker-supplied code can perform a wide variety of actions, such as stealing the victim's session token or login credentials, performing arbitrary actions on the victim's behalf, and logging their keystrokes.\n\nUsers can be induced to issue the attacker's crafted request in various ways. For example, the attacker can send a victim a link containing a malicious URL in an email or instant message. They can submit the link to popular web sites that allow content authoring, for example in blog comments. And they can create an innocuous looking web site that causes anyone viewing it to make arbitrary cross-domain requests to the vulnerable application (using either the GET or the POST method).\n\nThe security impact of cross-site scripting vulnerabilities is dependent upon the nature of the vulnerable application, the kinds of data and functionality that it contains, and the other applications that belong to the same domain and organization. If the application is used only to display non-sensitive public content, with no authentication or access control functionality, then a cross-site scripting flaw may be considered low risk. However, if the same application resides on a domain that can access cookies for other more security-critical applications, then the vulnerability could be used to attack those other applications, and so may be considered high risk. Similarly, if the organization that owns the application is a likely target for phishing attacks, then the vulnerability could be leveraged to lend credibility to such attacks, by injecting Trojan functionality into the vulnerable application and exploiting users' trust in the organization in order to capture credentials for other applications that it owns. In many kinds of application, such as those providing online banking functionality, cross-site scripting should always be considered high risk. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:17.664932529Z", "last_reviewed_by": [ @@ -31639,7 +31639,7 @@ ], "hash_code": "7b79656db5b18827a177cdef000720f62cf139c43bfbb8f1f6c2e1382e28b503", "impact": "The application allows users to connect to it over unencrypted connections. An attacker suitably positioned to view a legitimate user's network traffic could record and monitor their interactions with the application and obtain any information the user supplies. Furthermore, an attacker able to modify traffic could use the application as a platform for attacks against its users and third-party websites. Unencrypted connections have been exploited by ISPs and governments to track users, and to inject adverts and malicious JavaScript. Due to these concerns, web browser vendors are planning to visually flag unencrypted connections as hazardous.\n\nTo exploit this vulnerability, an attacker must be suitably positioned to eavesdrop on the victim's network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure. \n\nPlease note that using a mixture of encrypted and unencrypted communications is an ineffective defense against active attackers, because they can easily remove references to encrypted resources when these references are transmitted over an unencrypted connection.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:17.962932529Z", "last_reviewed_by": [ @@ -31720,7 +31720,7 @@ ], "hash_code": "a073a661ec300f853780ebd20d17abefb6c3bcf666776ddea1ab2e3e3c6d9428", "impact": "Some applications return passwords submitted to the application in clear form in later responses. This behavior increases the risk that users' passwords will be captured by an attacker. Many types of vulnerability, such as weaknesses in session handling, broken access controls, and cross-site scripting, could enable an attacker to leverage this behavior to retrieve the passwords of other application users. This possibility typically exacerbates the impact of those other vulnerabilities, and in some situations can enable an attacker to quickly compromise the entire application.\n\nVulnerabilities that result in the disclosure of users' passwords can result in compromises that are extremely difficult to investigate due to obscured audit trails. Even if the application itself only handles non-sensitive information, exposing passwords puts users who have re-used their password elsewhere at risk.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:18.220932529Z", "last_reviewed_by": [ @@ -31801,7 +31801,7 @@ ], "hash_code": "2b9640feda092762b423f98809677e58d24ccd79c948df2e052d3f22274ebe8f", "impact": "The presence of email addresses within application responses does not necessarily constitute a security vulnerability. Email addresses may appear intentionally within contact information, and many applications (such as web mail) include arbitrary third-party email addresses within their core content.\n\nHowever, email addresses of developers and other individuals (whether appearing on-screen or hidden within page source) may disclose information that is useful to an attacker; for example, they may represent usernames that can be used at the application's login, and they may be used in social engineering attacks against the organization's personnel. Unnecessary or excessive disclosure of email addresses may also lead to an increase in the volume of spam email received.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:18.471932529Z", "last_reviewed_by": [ @@ -31882,7 +31882,7 @@ ], "hash_code": "1c732e92e6e9b89c90bd4ef40579d4c06791cc635e6fb16c00f2d443c5922ffa", "impact": "Cross-site request forgery (CSRF) vulnerabilities may arise when applications rely solely on HTTP cookies to identify the user that has issued a particular request. Because browsers automatically add cookies to requests regardless of their origin, it may be possible for an attacker to create a malicious web site that forges a cross-domain request to the vulnerable application. For a request to be vulnerable to CSRF, the following conditions must hold:\n\n * The request can be issued cross-domain, for example using an HTML form. If the request contains non-standard headers or body content, then it may only be issuable from a page that originated on the same domain.\n * The application relies solely on HTTP cookies or Basic Authentication to identify the user that issued the request. If the application places session-related tokens elsewhere within the request, then it may not be vulnerable.\n * The request performs some privileged action within the application, which modifies the application's state based on the identity of the issuing user.\n * The attacker can determine all the parameters required to construct a request that performs the action. If the request contains any values that the attacker cannot determine or predict, then it is not vulnerable.\n\n\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:18.811932529Z", "last_reviewed_by": [ @@ -31963,7 +31963,7 @@ ], "hash_code": "31215cff140491cdd84abb9246ad91145069efda2bdb319b75e2ee916219178a", "impact": "SQL injection vulnerabilities arise when user-controllable data is incorporated into database SQL queries in an unsafe manner. An attacker can supply crafted input to break out of the data context in which their input appears and interfere with the structure of the surrounding query.\n\nA wide range of damaging attacks can often be delivered via SQL injection, including reading or modifying critical application data, interfering with application logic, escalating privileges within the database and taking control of the database server. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:19.066932529Z", "last_reviewed_by": [ @@ -32044,7 +32044,7 @@ ], "hash_code": "e2a968190c3c79023378ef6f30612b6119bc867f303aafc91eb3bd191d05b90d", "impact": "Path-relative style sheet import vulnerabilities arise when the following conditions hold:\n\n 1. A response contains a style sheet import that uses a path-relative URL (for example, the page at \"/original-path/file.php\" might import \"styles/main.css\").\n 2. When handling requests, the application or platform tolerates superfluous path-like data following the original filename in the URL (for example, \"/original-path/file.php/extra-junk/\"). When superfluous data is added to the original URL, the application's response still contains a path-relative stylesheet import.\n 3. The response in condition 2 can be made to render in a browser's quirks mode, either because it has a missing or old doctype directive, or because it allows itself to be framed by a page under an attacker's control.\n 4. When a browser requests the style sheet that is imported in the response from the modified URL (using the URL \"/original-path/file.php/extra-junk/styles/main.css\"), the application returns something other than the CSS response that was supposed to be imported. Given the behavior described in condition 2, this will typically be the same response that was originally returned in condition 1.\n 5. An attacker has a means of manipulating some text within the response in condition 4, for example because the application stores and displays some past input, or echoes some text within the current URL.\n\n\n\nGiven the above conditions, an attacker can execute CSS injection within the browser of the target user. The attacker can construct a URL that causes the victim's browser to import as CSS a different URL than normal, containing text that the attacker can manipulate. Being able to inject arbitrary CSS into the victim's browser may enable various attacks, including:\n\n * Executing arbitrary JavaScript using IE's expression() function.\n * Using CSS selectors to read parts of the HTML source, which may include sensitive data such as anti-CSRF tokens.\n * Capturing any sensitive data within the URL query string by making a further style sheet import to a URL on the attacker's domain, and monitoring the incoming Referer header.\n\n\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:19.363932529Z", "last_reviewed_by": [ @@ -32125,7 +32125,7 @@ ], "hash_code": "cef2dcb7c7787157edc70e85d5017e72d1dbca1fd80909f5d76cda85a9bdec2c", "impact": "Some applications transmit passwords over unencrypted connections, making them vulnerable to interception. To exploit this vulnerability, an attacker must be suitably positioned to eavesdrop on the victim's network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure.\n\nVulnerabilities that result in the disclosure of users' passwords can result in compromises that are extremely difficult to investigate due to obscured audit trails. Even if the application itself only handles non-sensitive information, exposing passwords puts users who have re-used their password elsewhere at risk.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "last_reviewed": "2022-11-11T07:42:19.828932529Z", "last_reviewed_by": [ diff --git a/dojo/fixtures/defect_dojo_sample_data_locations.json b/dojo/fixtures/defect_dojo_sample_data_locations.json index 12459311d1a..ec180425e4a 100644 --- a/dojo/fixtures/defect_dojo_sample_data_locations.json +++ b/dojo/fixtures/defect_dojo_sample_data_locations.json @@ -2763,7 +2763,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "product_manager" ], @@ -2810,7 +2810,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -2857,7 +2857,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "product_manager" ], @@ -2904,7 +2904,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -2951,7 +2951,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3000,7 +3000,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "name": "Ad Hoc Engagement", "notes": [], @@ -3045,7 +3045,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3092,7 +3092,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3141,7 +3141,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3188,7 +3188,7 @@ "engagement_type": "CI/CD", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3235,7 +3235,7 @@ "engagement_type": "Interactive", "files": [], "first_contacted": null, - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "name": "AdHoc Import - Fri, 17 Aug 2018 18:20:55", "notes": [], @@ -3324,7 +3324,7 @@ "engagement": 1, "environment": 1, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "notes": [], "percent_complete": 100, @@ -3351,7 +3351,7 @@ "engagement": 2, "environment": 1, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "product_manager" ], @@ -3380,7 +3380,7 @@ "engagement": 1, "environment": 1, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "notes": [], "percent_complete": 100, @@ -3407,7 +3407,7 @@ "engagement": 4, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3436,7 +3436,7 @@ "engagement": 4, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3465,7 +3465,7 @@ "engagement": 6, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3494,7 +3494,7 @@ "engagement": 7, "environment": null, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": null, "notes": [], "percent_complete": null, @@ -3521,7 +3521,7 @@ "engagement": 8, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3550,7 +3550,7 @@ "engagement": 8, "environment": 2, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3579,7 +3579,7 @@ "engagement": 8, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3608,7 +3608,7 @@ "engagement": 8, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3637,7 +3637,7 @@ "engagement": 10, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3666,7 +3666,7 @@ "engagement": 10, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3695,7 +3695,7 @@ "engagement": 10, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3724,7 +3724,7 @@ "engagement": 11, "environment": 3, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3753,7 +3753,7 @@ "engagement": 11, "environment": 5, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3782,7 +3782,7 @@ "engagement": 12, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3811,7 +3811,7 @@ "engagement": 13, "environment": 7, "files": [], - "inherited_tags": [], + "_inherited_tag_names": [], "lead": [ "admin" ], @@ -3862,7 +3862,7 @@ ], "hash_code": "91a538bb2d339f9f73553971ede199f44df8e96df30f34ac8d9c224322aa5d62", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -3953,7 +3953,7 @@ ], "hash_code": "5b0dead640b58a2b778aa2e8f5cccf67df7dc833b0c3f410985d1237615c86e7", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4044,7 +4044,7 @@ ], "hash_code": "5b0dead640b58a2b778aa2e8f5cccf67df7dc833b0c3f410985d1237615c86e7", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4135,7 +4135,7 @@ ], "hash_code": "5b0dead640b58a2b778aa2e8f5cccf67df7dc833b0c3f410985d1237615c86e7", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4226,7 +4226,7 @@ ], "hash_code": "5b0dead640b58a2b778aa2e8f5cccf67df7dc833b0c3f410985d1237615c86e7", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4317,7 +4317,7 @@ ], "hash_code": "c89d25e445b088ba339908f68e15e3177b78d22f3039d1bfea51c4be251bf4e0", "impact": "HIGH", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4406,7 +4406,7 @@ ], "hash_code": "c49c87192b6b4f17151a471fd9d1bf3b302bca08781d67806c6556fe720af1b0", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4495,7 +4495,7 @@ ], "hash_code": "a9c3269038ed8a49c4e7576b359f61a65a3bd82c163089bc20743e5a14aa0ab5", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4584,7 +4584,7 @@ ], "hash_code": "418f79f7a59a306d5e46aa4af1924b64200aed234ae994dcd66485eb30bbe869", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4673,7 +4673,7 @@ ], "hash_code": "21c80d580d9f1de55f6179e2a08e5684f46c9734d79cf701b2ff25e6776ccdfc", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4762,7 +4762,7 @@ ], "hash_code": "fffd29bd0973269ddbbed2e210926c04d42cb12037117261626b95bd52bcff27", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4851,7 +4851,7 @@ ], "hash_code": "3406086ac5988ee8b55f70c618daf86c21702bb3c4c00e4607e5c21c2e3d3828", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -4940,7 +4940,7 @@ ], "hash_code": "24e74e8be8b222cf0b17c034d03c5b43a130c2b960095eb44c55f470e50f6924", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5029,7 +5029,7 @@ ], "hash_code": "a91b30b026cda759c2608e1c8216cdd13e265c030b8c47f4690cd2182e4ad166", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5118,7 +5118,7 @@ ], "hash_code": "bfd9b74841c8d988d57c99353742f1e3180934ca6be2149a3fb7377329b57b33", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5207,7 +5207,7 @@ ], "hash_code": "9b003338465e31c37f36b2a2d9b01bf9003d1d2631e2c409b3d19d02c93a20b6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5296,7 +5296,7 @@ ], "hash_code": "684ee38b55ea509e6c2be4a58ec52ba5d7e0c1952e09f8c8ca2bf0675650bd8f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5385,7 +5385,7 @@ ], "hash_code": "99fb15b31049df2445ac3fd8729cbccbc6a19e4e410c3eb0ef95908c00b78fd7", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5474,7 +5474,7 @@ ], "hash_code": "541eb71776b2d297f9aa790c52297b4f7d26acb0bce7de33bda136fdefe43cb7", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5563,7 +5563,7 @@ ], "hash_code": "e5ac755dbe3bfd23995c8d5a99779d188440c9e573d79b44130d90468d41439c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5652,7 +5652,7 @@ ], "hash_code": "da32068a6442ce061d43625863d27f5e6346929f2b1d15b750df9d7b4bdb3597", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5741,7 +5741,7 @@ ], "hash_code": "b0de3516ab323f5577e6ad94803e2ddf541214bbae868bf34e828ba3a4d966ca", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5830,7 +5830,7 @@ ], "hash_code": "13ceb3acfb49f194493bfb0af44f5f886a9767aa1c6990c8a397af756d97209c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -5919,7 +5919,7 @@ ], "hash_code": "8d7b5f3962f521cd5c2dc40e4ef9a7cc10cfc30efb90f4b5841e8e5463656c61", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6008,7 +6008,7 @@ ], "hash_code": "2237f06cb695ec1da91d51cab9fb037d8a9e84f1aa9ddbfeef59eef1a65af47e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6097,7 +6097,7 @@ ], "hash_code": "05880cd0576bed75819cae74abce873fdcce5f857ec95d937a458b0ca0a49195", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6186,7 +6186,7 @@ ], "hash_code": "9ec4ce27f48767b96297ef3cb8eabba1814ea08a02801692a669540c5a7ce019", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6275,7 +6275,7 @@ ], "hash_code": "fc95b0887dc03b9f29f45b95aeb41e7f681dc28388279d7e11c233d3b5235c00", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6364,7 +6364,7 @@ ], "hash_code": "bae03653ab0823182626d77d8ba94f2fab26eccdde7bcb11ddd0fb8dee79d717", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6453,7 +6453,7 @@ ], "hash_code": "ae4e2ef51220be9b4ca71ee34ae9d174d093e6dd2da41951bc4ad2139a4dad3f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6542,7 +6542,7 @@ ], "hash_code": "c69d0a9ead39b5990a429c6ed185050ffadfda672b020ac6e7322ef02e72563a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6631,7 +6631,7 @@ ], "hash_code": "51b52607f2a5915cd128ba4e24ce8e22ba019757f074a0ebc27c33d91a55378b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6720,7 +6720,7 @@ ], "hash_code": "d947020e418c747ee99a0accd491030f65895189aefea2a96a390b3e843a9905", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6809,7 +6809,7 @@ ], "hash_code": "b29d81fdf7a5477a7badd1a47406a27deb12b90d0b3db17f567344d1ec24e65c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6898,7 +6898,7 @@ ], "hash_code": "514c8fbd9da03f03f770c9e0ca12d8bb20db50f3a836b4d50f16e0d75b0cca08", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -6987,7 +6987,7 @@ ], "hash_code": "0441fee04d6e24c168f5b4b567cc31174f464330f27638f83f80ee87d0d3dc03", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7076,7 +7076,7 @@ ], "hash_code": "7be257602d73f6146bbd1c6c4ab4970db0867933a1d2e87675770529b841d800", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7165,7 +7165,7 @@ ], "hash_code": "ff922242dd15286d81f09888a33ad571eca598b615bf4d4b9024af17df42bc17", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7254,7 +7254,7 @@ ], "hash_code": "964aeee36e5998da77d3229f43830d362838d860d9e30c415fb58e9686a49625", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7343,7 +7343,7 @@ ], "hash_code": "e57ed13a66f4041fa377af4db5110a50a8f4a67e0c7c2b3e955e4118844a2904", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7432,7 +7432,7 @@ ], "hash_code": "8fc3621137e4dd32d75801ac6948909b20f671d21ed9dfe89d0e2f49a2554653", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7521,7 +7521,7 @@ ], "hash_code": "3988a18fe8f515ab1f92c649f43f20d33e8e8692d00a9dc80f2863342b522698", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7610,7 +7610,7 @@ ], "hash_code": "cfc58944e3181521dc3a9ec917dcb54d7a54ebbf3f0e8aaca7fec60a05485c63", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7699,7 +7699,7 @@ ], "hash_code": "9878411e3b89bc832e58fa15e46d19e2e607309d3df9f152114d5ff62f95f0ce", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7788,7 +7788,7 @@ ], "hash_code": "35055620006745673ffba1cb3c1e8c09a9fd59f6438e6d45fbbb222a10968120", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7877,7 +7877,7 @@ ], "hash_code": "60fff62e2e1d2383da91886a96d64905e184a3044037dc2595c3ccf28faacd6c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -7966,7 +7966,7 @@ ], "hash_code": "c81c73f4bd1bb970a016bd7e5f1979af8d05eac71f387b2da9bd4affcaf13f81", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8055,7 +8055,7 @@ ], "hash_code": "1e74e0c4e0572c6bb5aaee26176b8a40ce024325bbffea1ddbb120bab9d9542c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8144,7 +8144,7 @@ ], "hash_code": "4568d7e34ac50ab291c955c8acb368e5abe73de05bd3080e2efc7b00f329600f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8233,7 +8233,7 @@ ], "hash_code": "1f91fef184e69387463ce9719fe9756145e16e76d39609aa5fa3e0eaa1274d05", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8322,7 +8322,7 @@ ], "hash_code": "75a93a572c186be5fe7f5221a64306b5b35dddf605b5e231ffc74442bd3728a4", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8411,7 +8411,7 @@ ], "hash_code": "afd07fc450ae8609c93797c8fd893028f7d8a9841999facd0a08236696c05841", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8500,7 +8500,7 @@ ], "hash_code": "78439e5edd436844bb6dc527f6effe0836b88b0fb946747b7f957da95b479fc2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8589,7 +8589,7 @@ ], "hash_code": "92b54561d5d262a88920162ba7bf19fc0444975582be837047cab5d79c992447", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8678,7 +8678,7 @@ ], "hash_code": "f24533b1fc628061c2037eb55ffe66aed6bfa2436fadaf6e424e4905ed238e21", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8767,7 +8767,7 @@ ], "hash_code": "38321299050d31a3b8168316e30316d786236785a9c31427fb6f2631d3065a7c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8856,7 +8856,7 @@ ], "hash_code": "24cd9b35200f9ca729fcccb8348baccd2ddfeee2f22177fd40e46931f8547659", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -8945,7 +8945,7 @@ ], "hash_code": "148a501a59e0d04eb52b5cd58b4d654b4a7883e8ad09dcd5801e775113a1000d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9034,7 +9034,7 @@ ], "hash_code": "55040c9344c964843ff56e19ff1ef4892c9f93234a7a39578c81ed903dd03e08", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9123,7 +9123,7 @@ ], "hash_code": "06cd6507296edca41e97d652a873c31230bf98fa8bdeab477fedb680ff606932", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9212,7 +9212,7 @@ ], "hash_code": "62f3875efdcf326015adee1ecd85c4ecdca5bc9c4719e5c9177dff8b0afffa1f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9301,7 +9301,7 @@ ], "hash_code": "0007a2df1ab7dc00f2144451d894f513c7d872e1153a0759982a8c866001cc02", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9390,7 +9390,7 @@ ], "hash_code": "7dba1c0820d0f6017ca3333f7f9a8865a862604c4b13a1eed04666c6e364fa36", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9479,7 +9479,7 @@ ], "hash_code": "95568708fa568cc74c7ef8279b87869ebc932305da1878dbb1b7597c75a57bc1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9568,7 +9568,7 @@ ], "hash_code": "b037e71624f50f74cfbd0f0cd561daa1e87b1ac3690b19b1d3fe3c36ef452628", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9657,7 +9657,7 @@ ], "hash_code": "945eb840563ed9b29b08ff0838d391e775d2e45f26817ad0b321b41e608564cf", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9746,7 +9746,7 @@ ], "hash_code": "6e270eb7494286a67571f0d33112e997365a0de45a119ef8199d270c32d806ab", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9835,7 +9835,7 @@ ], "hash_code": "76a4b74903cac92c02f0d0c7eca32f417f6ce4a3fb04f16eff17cfc0e8f8df7f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -9924,7 +9924,7 @@ ], "hash_code": "3db6ca06969817d45acccd02c0ba65067c1e11e9d4d7c34c7301612e63b2f75a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10013,7 +10013,7 @@ ], "hash_code": "66ad49b768c1dcb417d1047d6a3e134473f45969fdc41c529a37088dec29804e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10102,7 +10102,7 @@ ], "hash_code": "174ea52e3d43e0e3089705762ecd259a74bdb4c592473a8c4615c8d37e840725", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10191,7 +10191,7 @@ ], "hash_code": "cecce89612fa88ff6270b822a8840911536f983c5ab580f5e7df0ec93a95884a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10280,7 +10280,7 @@ ], "hash_code": "afa0b4d8453f20629d5863f0cb1b8d4e31bf2e8c4476db973a78731ffcf08bd2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10369,7 +10369,7 @@ ], "hash_code": "1aec22aeffa8b6201ad60b0a0d2b166ddbaefca6ab534bbc4d2a827bc02f5c20", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10458,7 +10458,7 @@ ], "hash_code": "2a7f9ff0b80ef53370128384650fe897d773383109c7d171159cbfbc232476e2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10547,7 +10547,7 @@ ], "hash_code": "bef5f29fc5d5f44cef3dd5db1aaeeb5f2e5d7480a197045e6d176f0ab26b5fa2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10636,7 +10636,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10725,7 +10725,7 @@ ], "hash_code": "2de5b8ed091eaaf750260b056239152b81363c790977699374b03d93e1d28551", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10814,7 +10814,7 @@ ], "hash_code": "3173d904f9ac1a4779a3b5fd52f271e6a7871d6cb5387d2ced15025a4a15db93", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10903,7 +10903,7 @@ ], "hash_code": "775723c89fdaed1cc6b85ecc489c028159d261e95e7ad4ad80d03ddd63bc99ea", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -10992,7 +10992,7 @@ ], "hash_code": "9e3aa3082f7d93e52f9bfe97630e9fd6f6c04c5791dd22505ab238d1a6bf9242", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11081,7 +11081,7 @@ ], "hash_code": "2fe1558daec12a621f0504714bee44be8d382a57c7cdda160ddad8a2e8b8ca48", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11170,7 +11170,7 @@ ], "hash_code": "5fb0f064b2f7098c57e1115b391bf7a6eb57feae63c2848b916a5b79dccf66f3", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11259,7 +11259,7 @@ ], "hash_code": "86efaa45244686266a1c4f1aef52d60ce791dd4cb64feebe5b214db5838b8e06", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11348,7 +11348,7 @@ ], "hash_code": "7d988ddc1b32f65ada9bd17516943b28e33458ea570ce92843bdb49e7a7e22fb", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11437,7 +11437,7 @@ ], "hash_code": "1c24c0fc04774515bc6dc38386250282055e0585ae71b405586b552ca04b31c9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11526,7 +11526,7 @@ ], "hash_code": "d68d7152bc4b3f069aa236ff41cab28da77d7e668b77cb4de10ae8bf7a2e85be", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11615,7 +11615,7 @@ ], "hash_code": "84c57ed3e3723016b9425c8549bd0faab967538a59e072c2dc5c85974a72bf41", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11704,7 +11704,7 @@ ], "hash_code": "2dc7787335253be93ebb64d3ad632116363f3a5821c070db4cc28c18a0eee09e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11793,7 +11793,7 @@ ], "hash_code": "45fe7a9d8b946b2cbc6aaf8b5e36608cc629e5f388f91433664d3c2f19a29991", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11882,7 +11882,7 @@ ], "hash_code": "6e5f6914b0e963152cff1f6b9fe1c39a2f177979e6885bdbac5bd88f1d40d8cd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -11971,7 +11971,7 @@ ], "hash_code": "763571cd8b09d88baae5cc8bc9d755e2401e204c335894933401186d14be3992", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12060,7 +12060,7 @@ ], "hash_code": "508298807b8bd2787b58a49d31bd3f056293c7656e8936eb2e478b3636fa5e19", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12149,7 +12149,7 @@ ], "hash_code": "1544a01109756bdb265135b3dbc4efca3a22c8d19fa9b50407c94760f04d5610", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12238,7 +12238,7 @@ ], "hash_code": "d6251c8822044d55511b364098e264ca2113391d999c6aefe5c1cca3743e2f2d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12327,7 +12327,7 @@ ], "hash_code": "f8234be5bed59174a5f1f4efef0acb152b788f55c1804e2abbc185fe69ceea31", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12416,7 +12416,7 @@ ], "hash_code": "7d3502f71ea947677c3ae5e39ae8da99c7024c3820a1c546bbdfe3ea4a0fdfc0", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12505,7 +12505,7 @@ ], "hash_code": "779b4fe3dd494b8c323ddb7cb879f60051ac263904a16ac65af5a210cf797c0b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12594,7 +12594,7 @@ ], "hash_code": "326fbad527801598a49946804f53bff975023eeb4c7c992932611d45d0b46201", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12683,7 +12683,7 @@ ], "hash_code": "d818b17afca02a70991162f0cf5fbb16d2fef322b72c5c77b4c32bd209b3dc02", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12772,7 +12772,7 @@ ], "hash_code": "926d5bb4d3abbed178afd6c5ffb752e6774908ad90893262c187e71e3197f31d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12861,7 +12861,7 @@ ], "hash_code": "cfa4c706348e59de8b65228daccc21474abf67877a50dec0efa031e947d2e3bd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -12950,7 +12950,7 @@ ], "hash_code": "b493926fdab24fe92c9c28363e72429e66631bd5056f574ddefb983212933d10", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13039,7 +13039,7 @@ ], "hash_code": "40f3e776293c5c19ac7b521181adfef56ed09288fa417f519d1cc6071cba8a17", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13128,7 +13128,7 @@ ], "hash_code": "8332e5bd42770868b5db865ca9017c31fcea5a91cff250c4341dc73ed5fdb6e6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13217,7 +13217,7 @@ ], "hash_code": "641ba17f6201ed5f40524a90c0e0fc03d8a4731528be567b639362cef3f20ef2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13306,7 +13306,7 @@ ], "hash_code": "c3fb1583f06a0ce7bee2084607680b357d63dd8f9cc56d5d09f0601a3c62a336", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13395,7 +13395,7 @@ ], "hash_code": "11b43c1ce56100d6a92b74b27d6e6901f3822b44c4b6e8437a7622f71c3a58a9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13484,7 +13484,7 @@ ], "hash_code": "7a001d11b5d7d20f5215658fc735a31e530696faddeae3eacf81662d4870e89a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13573,7 +13573,7 @@ ], "hash_code": "dc13f474e6f512cb31374bfa4658ce7a866d6b832d40742e784ef14f6513ab87", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13662,7 +13662,7 @@ ], "hash_code": "63f306f6577c64ad2d38ddd3985cc649b11dd360f7a962e98cb63686c89b2b95", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13751,7 +13751,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13840,7 +13840,7 @@ ], "hash_code": "5b24a32f74c75879a1adc65bf89b03bb64f81565dbd6a2240149f2ce1bd27d40", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -13929,7 +13929,7 @@ ], "hash_code": "08569015fcc466a18ab405324d0dfe6af4b141110e47b73226ea117ecd44ff10", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14018,7 +14018,7 @@ ], "hash_code": "fd480c121d5e26af3fb8c7ec89137aab25d86e44ff154f5aae742384cf80a2dd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14107,7 +14107,7 @@ ], "hash_code": "b755a0cc07b69b72eb284df102459af7c502318c53c769999ec925d0da354d44", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14196,7 +14196,7 @@ ], "hash_code": "70d68584520c7bc1b47ca45fc75b42460659a52957a10fe2a99858c32b329ae1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14285,7 +14285,7 @@ ], "hash_code": "920ba1bf2ab979534eda06dd720ba0baa9cff2b1c14fd1ad56e89a5d656ed2f9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14374,7 +14374,7 @@ ], "hash_code": "6bea74fa6a2e15eb4e272fd8033b63984cb1cfefd52189c7031b58d7bd325f44", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14463,7 +14463,7 @@ ], "hash_code": "97e071423b295531965759c3641effa4a92e8e67f5ae40a3248a0a296aada52d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14552,7 +14552,7 @@ ], "hash_code": "810541dc4d59d52088c1c29bfbb5ed70b10bfa657980a3099b26ff8799955f28", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14641,7 +14641,7 @@ ], "hash_code": "eba9a993ff2b55ebdda24cb3c0fbc777bd7bcf038a01463f56b2f472f5a95296", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14730,7 +14730,7 @@ ], "hash_code": "af0420cc3c001e6a1c65aceb86644080bcdb3f08b6be7cfc96a3bb3e20685afb", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14819,7 +14819,7 @@ ], "hash_code": "78ceea05b00023deec3b210877d332bf03d07b237e8339f508a18c62b1146f88", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14908,7 +14908,7 @@ ], "hash_code": "9384efff38eaa33266a2f5888dea18392a0e8b658b770fcfed268f06d3a1052d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -14997,7 +14997,7 @@ ], "hash_code": "93595b491f79115f85df3ef403cfc4ecd34e22dedf95aa24fbc18f56039d26f3", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15086,7 +15086,7 @@ ], "hash_code": "ebfe755d6f8f91724d9d8a0672c12dce0200f818bce80b7fcaab30987b124a99", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15175,7 +15175,7 @@ ], "hash_code": "584b05859f76b43b2736a28ac1c8ac88497704d0f31868218fcda9077396a215", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15264,7 +15264,7 @@ ], "hash_code": "b1306a4177b37bad4dbe763419df19ec56d7442262be5dfeff6d346b3b900ad1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15353,7 +15353,7 @@ ], "hash_code": "59304c367c39a7f0983c4ef2f90a13207866a37422ff5cc03db07d0efe46aed2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15442,7 +15442,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15531,7 +15531,7 @@ ], "hash_code": "28820e0352bb80a1d3c1085204cfeb522ddd29ee680ae46350260bf63359646f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15620,7 +15620,7 @@ ], "hash_code": "ee16024c2d5962d243c878bf4f638147a8f879f05d969855c13d083aafab9fa8", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15709,7 +15709,7 @@ ], "hash_code": "ce6c5523b17b77be323a526e757f04235f6d8a3023ac5208b12b7c34de4fcbb6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15798,7 +15798,7 @@ ], "hash_code": "85b4b54f401f88fb286b6442b56fecb5922a025504207d94f5835e4b9e4c3d49", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15887,7 +15887,7 @@ ], "hash_code": "371010ba334ccc433d73bf0c9cdaec557d5f7ec338c6f925d8a71763a228d473", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -15976,7 +15976,7 @@ ], "hash_code": "ea8b569d6c5fe9dba625c6540acd9880534f7a19a5bf4b84fb838ad65d08d26f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16065,7 +16065,7 @@ ], "hash_code": "d0e517ef410747c79f882b9fc73a04a92ef6b4792017378ae5c4a39e21a921c5", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16154,7 +16154,7 @@ ], "hash_code": "c49c87192b6b4f17151a471fd9d1bf3b302bca08781d67806c6556fe720af1b0", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16243,7 +16243,7 @@ ], "hash_code": "a9c3269038ed8a49c4e7576b359f61a65a3bd82c163089bc20743e5a14aa0ab5", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16332,7 +16332,7 @@ ], "hash_code": "418f79f7a59a306d5e46aa4af1924b64200aed234ae994dcd66485eb30bbe869", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16421,7 +16421,7 @@ ], "hash_code": "21c80d580d9f1de55f6179e2a08e5684f46c9734d79cf701b2ff25e6776ccdfc", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16510,7 +16510,7 @@ ], "hash_code": "fffd29bd0973269ddbbed2e210926c04d42cb12037117261626b95bd52bcff27", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16599,7 +16599,7 @@ ], "hash_code": "3406086ac5988ee8b55f70c618daf86c21702bb3c4c00e4607e5c21c2e3d3828", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16688,7 +16688,7 @@ ], "hash_code": "24e74e8be8b222cf0b17c034d03c5b43a130c2b960095eb44c55f470e50f6924", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16777,7 +16777,7 @@ ], "hash_code": "a91b30b026cda759c2608e1c8216cdd13e265c030b8c47f4690cd2182e4ad166", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16866,7 +16866,7 @@ ], "hash_code": "bfd9b74841c8d988d57c99353742f1e3180934ca6be2149a3fb7377329b57b33", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -16955,7 +16955,7 @@ ], "hash_code": "9b003338465e31c37f36b2a2d9b01bf9003d1d2631e2c409b3d19d02c93a20b6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17044,7 +17044,7 @@ ], "hash_code": "684ee38b55ea509e6c2be4a58ec52ba5d7e0c1952e09f8c8ca2bf0675650bd8f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17133,7 +17133,7 @@ ], "hash_code": "99fb15b31049df2445ac3fd8729cbccbc6a19e4e410c3eb0ef95908c00b78fd7", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17222,7 +17222,7 @@ ], "hash_code": "541eb71776b2d297f9aa790c52297b4f7d26acb0bce7de33bda136fdefe43cb7", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17311,7 +17311,7 @@ ], "hash_code": "e5ac755dbe3bfd23995c8d5a99779d188440c9e573d79b44130d90468d41439c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17400,7 +17400,7 @@ ], "hash_code": "da32068a6442ce061d43625863d27f5e6346929f2b1d15b750df9d7b4bdb3597", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17489,7 +17489,7 @@ ], "hash_code": "b0de3516ab323f5577e6ad94803e2ddf541214bbae868bf34e828ba3a4d966ca", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17578,7 +17578,7 @@ ], "hash_code": "13ceb3acfb49f194493bfb0af44f5f886a9767aa1c6990c8a397af756d97209c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17667,7 +17667,7 @@ ], "hash_code": "8d7b5f3962f521cd5c2dc40e4ef9a7cc10cfc30efb90f4b5841e8e5463656c61", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17756,7 +17756,7 @@ ], "hash_code": "2237f06cb695ec1da91d51cab9fb037d8a9e84f1aa9ddbfeef59eef1a65af47e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17845,7 +17845,7 @@ ], "hash_code": "05880cd0576bed75819cae74abce873fdcce5f857ec95d937a458b0ca0a49195", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -17934,7 +17934,7 @@ ], "hash_code": "9ec4ce27f48767b96297ef3cb8eabba1814ea08a02801692a669540c5a7ce019", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18023,7 +18023,7 @@ ], "hash_code": "fc95b0887dc03b9f29f45b95aeb41e7f681dc28388279d7e11c233d3b5235c00", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18112,7 +18112,7 @@ ], "hash_code": "bae03653ab0823182626d77d8ba94f2fab26eccdde7bcb11ddd0fb8dee79d717", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18201,7 +18201,7 @@ ], "hash_code": "ae4e2ef51220be9b4ca71ee34ae9d174d093e6dd2da41951bc4ad2139a4dad3f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18290,7 +18290,7 @@ ], "hash_code": "c69d0a9ead39b5990a429c6ed185050ffadfda672b020ac6e7322ef02e72563a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18379,7 +18379,7 @@ ], "hash_code": "51b52607f2a5915cd128ba4e24ce8e22ba019757f074a0ebc27c33d91a55378b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18468,7 +18468,7 @@ ], "hash_code": "d947020e418c747ee99a0accd491030f65895189aefea2a96a390b3e843a9905", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18557,7 +18557,7 @@ ], "hash_code": "b29d81fdf7a5477a7badd1a47406a27deb12b90d0b3db17f567344d1ec24e65c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18646,7 +18646,7 @@ ], "hash_code": "514c8fbd9da03f03f770c9e0ca12d8bb20db50f3a836b4d50f16e0d75b0cca08", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18735,7 +18735,7 @@ ], "hash_code": "0441fee04d6e24c168f5b4b567cc31174f464330f27638f83f80ee87d0d3dc03", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18824,7 +18824,7 @@ ], "hash_code": "7be257602d73f6146bbd1c6c4ab4970db0867933a1d2e87675770529b841d800", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -18913,7 +18913,7 @@ ], "hash_code": "ff922242dd15286d81f09888a33ad571eca598b615bf4d4b9024af17df42bc17", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19002,7 +19002,7 @@ ], "hash_code": "964aeee36e5998da77d3229f43830d362838d860d9e30c415fb58e9686a49625", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19091,7 +19091,7 @@ ], "hash_code": "e57ed13a66f4041fa377af4db5110a50a8f4a67e0c7c2b3e955e4118844a2904", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19180,7 +19180,7 @@ ], "hash_code": "8fc3621137e4dd32d75801ac6948909b20f671d21ed9dfe89d0e2f49a2554653", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19269,7 +19269,7 @@ ], "hash_code": "3988a18fe8f515ab1f92c649f43f20d33e8e8692d00a9dc80f2863342b522698", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19358,7 +19358,7 @@ ], "hash_code": "cfc58944e3181521dc3a9ec917dcb54d7a54ebbf3f0e8aaca7fec60a05485c63", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19447,7 +19447,7 @@ ], "hash_code": "9878411e3b89bc832e58fa15e46d19e2e607309d3df9f152114d5ff62f95f0ce", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19536,7 +19536,7 @@ ], "hash_code": "35055620006745673ffba1cb3c1e8c09a9fd59f6438e6d45fbbb222a10968120", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19625,7 +19625,7 @@ ], "hash_code": "60fff62e2e1d2383da91886a96d64905e184a3044037dc2595c3ccf28faacd6c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19714,7 +19714,7 @@ ], "hash_code": "c81c73f4bd1bb970a016bd7e5f1979af8d05eac71f387b2da9bd4affcaf13f81", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19803,7 +19803,7 @@ ], "hash_code": "1e74e0c4e0572c6bb5aaee26176b8a40ce024325bbffea1ddbb120bab9d9542c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19892,7 +19892,7 @@ ], "hash_code": "4568d7e34ac50ab291c955c8acb368e5abe73de05bd3080e2efc7b00f329600f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -19981,7 +19981,7 @@ ], "hash_code": "1f91fef184e69387463ce9719fe9756145e16e76d39609aa5fa3e0eaa1274d05", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20070,7 +20070,7 @@ ], "hash_code": "75a93a572c186be5fe7f5221a64306b5b35dddf605b5e231ffc74442bd3728a4", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20159,7 +20159,7 @@ ], "hash_code": "afd07fc450ae8609c93797c8fd893028f7d8a9841999facd0a08236696c05841", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20248,7 +20248,7 @@ ], "hash_code": "78439e5edd436844bb6dc527f6effe0836b88b0fb946747b7f957da95b479fc2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20337,7 +20337,7 @@ ], "hash_code": "92b54561d5d262a88920162ba7bf19fc0444975582be837047cab5d79c992447", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20426,7 +20426,7 @@ ], "hash_code": "f24533b1fc628061c2037eb55ffe66aed6bfa2436fadaf6e424e4905ed238e21", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20515,7 +20515,7 @@ ], "hash_code": "38321299050d31a3b8168316e30316d786236785a9c31427fb6f2631d3065a7c", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20604,7 +20604,7 @@ ], "hash_code": "24cd9b35200f9ca729fcccb8348baccd2ddfeee2f22177fd40e46931f8547659", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20693,7 +20693,7 @@ ], "hash_code": "148a501a59e0d04eb52b5cd58b4d654b4a7883e8ad09dcd5801e775113a1000d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20782,7 +20782,7 @@ ], "hash_code": "55040c9344c964843ff56e19ff1ef4892c9f93234a7a39578c81ed903dd03e08", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20871,7 +20871,7 @@ ], "hash_code": "06cd6507296edca41e97d652a873c31230bf98fa8bdeab477fedb680ff606932", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -20960,7 +20960,7 @@ ], "hash_code": "62f3875efdcf326015adee1ecd85c4ecdca5bc9c4719e5c9177dff8b0afffa1f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21049,7 +21049,7 @@ ], "hash_code": "0007a2df1ab7dc00f2144451d894f513c7d872e1153a0759982a8c866001cc02", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21138,7 +21138,7 @@ ], "hash_code": "7dba1c0820d0f6017ca3333f7f9a8865a862604c4b13a1eed04666c6e364fa36", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21227,7 +21227,7 @@ ], "hash_code": "95568708fa568cc74c7ef8279b87869ebc932305da1878dbb1b7597c75a57bc1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21316,7 +21316,7 @@ ], "hash_code": "b037e71624f50f74cfbd0f0cd561daa1e87b1ac3690b19b1d3fe3c36ef452628", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21405,7 +21405,7 @@ ], "hash_code": "945eb840563ed9b29b08ff0838d391e775d2e45f26817ad0b321b41e608564cf", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21494,7 +21494,7 @@ ], "hash_code": "6e270eb7494286a67571f0d33112e997365a0de45a119ef8199d270c32d806ab", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21583,7 +21583,7 @@ ], "hash_code": "76a4b74903cac92c02f0d0c7eca32f417f6ce4a3fb04f16eff17cfc0e8f8df7f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21672,7 +21672,7 @@ ], "hash_code": "3db6ca06969817d45acccd02c0ba65067c1e11e9d4d7c34c7301612e63b2f75a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21761,7 +21761,7 @@ ], "hash_code": "66ad49b768c1dcb417d1047d6a3e134473f45969fdc41c529a37088dec29804e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21850,7 +21850,7 @@ ], "hash_code": "174ea52e3d43e0e3089705762ecd259a74bdb4c592473a8c4615c8d37e840725", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -21939,7 +21939,7 @@ ], "hash_code": "cecce89612fa88ff6270b822a8840911536f983c5ab580f5e7df0ec93a95884a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22028,7 +22028,7 @@ ], "hash_code": "afa0b4d8453f20629d5863f0cb1b8d4e31bf2e8c4476db973a78731ffcf08bd2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22117,7 +22117,7 @@ ], "hash_code": "1aec22aeffa8b6201ad60b0a0d2b166ddbaefca6ab534bbc4d2a827bc02f5c20", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22206,7 +22206,7 @@ ], "hash_code": "2a7f9ff0b80ef53370128384650fe897d773383109c7d171159cbfbc232476e2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22295,7 +22295,7 @@ ], "hash_code": "bef5f29fc5d5f44cef3dd5db1aaeeb5f2e5d7480a197045e6d176f0ab26b5fa2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22384,7 +22384,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22473,7 +22473,7 @@ ], "hash_code": "2de5b8ed091eaaf750260b056239152b81363c790977699374b03d93e1d28551", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22562,7 +22562,7 @@ ], "hash_code": "3173d904f9ac1a4779a3b5fd52f271e6a7871d6cb5387d2ced15025a4a15db93", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22651,7 +22651,7 @@ ], "hash_code": "775723c89fdaed1cc6b85ecc489c028159d261e95e7ad4ad80d03ddd63bc99ea", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22740,7 +22740,7 @@ ], "hash_code": "9e3aa3082f7d93e52f9bfe97630e9fd6f6c04c5791dd22505ab238d1a6bf9242", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22829,7 +22829,7 @@ ], "hash_code": "2fe1558daec12a621f0504714bee44be8d382a57c7cdda160ddad8a2e8b8ca48", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -22918,7 +22918,7 @@ ], "hash_code": "5fb0f064b2f7098c57e1115b391bf7a6eb57feae63c2848b916a5b79dccf66f3", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23007,7 +23007,7 @@ ], "hash_code": "86efaa45244686266a1c4f1aef52d60ce791dd4cb64feebe5b214db5838b8e06", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23096,7 +23096,7 @@ ], "hash_code": "7d988ddc1b32f65ada9bd17516943b28e33458ea570ce92843bdb49e7a7e22fb", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23185,7 +23185,7 @@ ], "hash_code": "1c24c0fc04774515bc6dc38386250282055e0585ae71b405586b552ca04b31c9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23274,7 +23274,7 @@ ], "hash_code": "d68d7152bc4b3f069aa236ff41cab28da77d7e668b77cb4de10ae8bf7a2e85be", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23363,7 +23363,7 @@ ], "hash_code": "84c57ed3e3723016b9425c8549bd0faab967538a59e072c2dc5c85974a72bf41", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23452,7 +23452,7 @@ ], "hash_code": "2dc7787335253be93ebb64d3ad632116363f3a5821c070db4cc28c18a0eee09e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23541,7 +23541,7 @@ ], "hash_code": "45fe7a9d8b946b2cbc6aaf8b5e36608cc629e5f388f91433664d3c2f19a29991", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23630,7 +23630,7 @@ ], "hash_code": "6e5f6914b0e963152cff1f6b9fe1c39a2f177979e6885bdbac5bd88f1d40d8cd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23719,7 +23719,7 @@ ], "hash_code": "763571cd8b09d88baae5cc8bc9d755e2401e204c335894933401186d14be3992", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23808,7 +23808,7 @@ ], "hash_code": "508298807b8bd2787b58a49d31bd3f056293c7656e8936eb2e478b3636fa5e19", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23897,7 +23897,7 @@ ], "hash_code": "1544a01109756bdb265135b3dbc4efca3a22c8d19fa9b50407c94760f04d5610", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -23986,7 +23986,7 @@ ], "hash_code": "d6251c8822044d55511b364098e264ca2113391d999c6aefe5c1cca3743e2f2d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24075,7 +24075,7 @@ ], "hash_code": "f8234be5bed59174a5f1f4efef0acb152b788f55c1804e2abbc185fe69ceea31", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24164,7 +24164,7 @@ ], "hash_code": "7d3502f71ea947677c3ae5e39ae8da99c7024c3820a1c546bbdfe3ea4a0fdfc0", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24253,7 +24253,7 @@ ], "hash_code": "779b4fe3dd494b8c323ddb7cb879f60051ac263904a16ac65af5a210cf797c0b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24342,7 +24342,7 @@ ], "hash_code": "326fbad527801598a49946804f53bff975023eeb4c7c992932611d45d0b46201", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24431,7 +24431,7 @@ ], "hash_code": "d818b17afca02a70991162f0cf5fbb16d2fef322b72c5c77b4c32bd209b3dc02", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24520,7 +24520,7 @@ ], "hash_code": "926d5bb4d3abbed178afd6c5ffb752e6774908ad90893262c187e71e3197f31d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24609,7 +24609,7 @@ ], "hash_code": "cfa4c706348e59de8b65228daccc21474abf67877a50dec0efa031e947d2e3bd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24698,7 +24698,7 @@ ], "hash_code": "b493926fdab24fe92c9c28363e72429e66631bd5056f574ddefb983212933d10", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24787,7 +24787,7 @@ ], "hash_code": "40f3e776293c5c19ac7b521181adfef56ed09288fa417f519d1cc6071cba8a17", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24876,7 +24876,7 @@ ], "hash_code": "8332e5bd42770868b5db865ca9017c31fcea5a91cff250c4341dc73ed5fdb6e6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -24965,7 +24965,7 @@ ], "hash_code": "641ba17f6201ed5f40524a90c0e0fc03d8a4731528be567b639362cef3f20ef2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25054,7 +25054,7 @@ ], "hash_code": "c3fb1583f06a0ce7bee2084607680b357d63dd8f9cc56d5d09f0601a3c62a336", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25143,7 +25143,7 @@ ], "hash_code": "11b43c1ce56100d6a92b74b27d6e6901f3822b44c4b6e8437a7622f71c3a58a9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25232,7 +25232,7 @@ ], "hash_code": "7a001d11b5d7d20f5215658fc735a31e530696faddeae3eacf81662d4870e89a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25321,7 +25321,7 @@ ], "hash_code": "dc13f474e6f512cb31374bfa4658ce7a866d6b832d40742e784ef14f6513ab87", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25410,7 +25410,7 @@ ], "hash_code": "63f306f6577c64ad2d38ddd3985cc649b11dd360f7a962e98cb63686c89b2b95", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25499,7 +25499,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25588,7 +25588,7 @@ ], "hash_code": "5b24a32f74c75879a1adc65bf89b03bb64f81565dbd6a2240149f2ce1bd27d40", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25677,7 +25677,7 @@ ], "hash_code": "08569015fcc466a18ab405324d0dfe6af4b141110e47b73226ea117ecd44ff10", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25766,7 +25766,7 @@ ], "hash_code": "fd480c121d5e26af3fb8c7ec89137aab25d86e44ff154f5aae742384cf80a2dd", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25855,7 +25855,7 @@ ], "hash_code": "b755a0cc07b69b72eb284df102459af7c502318c53c769999ec925d0da354d44", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -25944,7 +25944,7 @@ ], "hash_code": "70d68584520c7bc1b47ca45fc75b42460659a52957a10fe2a99858c32b329ae1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26033,7 +26033,7 @@ ], "hash_code": "920ba1bf2ab979534eda06dd720ba0baa9cff2b1c14fd1ad56e89a5d656ed2f9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26122,7 +26122,7 @@ ], "hash_code": "6bea74fa6a2e15eb4e272fd8033b63984cb1cfefd52189c7031b58d7bd325f44", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26211,7 +26211,7 @@ ], "hash_code": "97e071423b295531965759c3641effa4a92e8e67f5ae40a3248a0a296aada52d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26300,7 +26300,7 @@ ], "hash_code": "810541dc4d59d52088c1c29bfbb5ed70b10bfa657980a3099b26ff8799955f28", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26389,7 +26389,7 @@ ], "hash_code": "eba9a993ff2b55ebdda24cb3c0fbc777bd7bcf038a01463f56b2f472f5a95296", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26478,7 +26478,7 @@ ], "hash_code": "af0420cc3c001e6a1c65aceb86644080bcdb3f08b6be7cfc96a3bb3e20685afb", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26567,7 +26567,7 @@ ], "hash_code": "78ceea05b00023deec3b210877d332bf03d07b237e8339f508a18c62b1146f88", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26656,7 +26656,7 @@ ], "hash_code": "9384efff38eaa33266a2f5888dea18392a0e8b658b770fcfed268f06d3a1052d", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26745,7 +26745,7 @@ ], "hash_code": "93595b491f79115f85df3ef403cfc4ecd34e22dedf95aa24fbc18f56039d26f3", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26834,7 +26834,7 @@ ], "hash_code": "ebfe755d6f8f91724d9d8a0672c12dce0200f818bce80b7fcaab30987b124a99", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -26923,7 +26923,7 @@ ], "hash_code": "584b05859f76b43b2736a28ac1c8ac88497704d0f31868218fcda9077396a215", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27012,7 +27012,7 @@ ], "hash_code": "b1306a4177b37bad4dbe763419df19ec56d7442262be5dfeff6d346b3b900ad1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27101,7 +27101,7 @@ ], "hash_code": "59304c367c39a7f0983c4ef2f90a13207866a37422ff5cc03db07d0efe46aed2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27190,7 +27190,7 @@ ], "hash_code": "db7a77c20f51041b98ba80af21a73ef2db784e82fd0af050fefb552826be04b1", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27279,7 +27279,7 @@ ], "hash_code": "28820e0352bb80a1d3c1085204cfeb522ddd29ee680ae46350260bf63359646f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27368,7 +27368,7 @@ ], "hash_code": "ee16024c2d5962d243c878bf4f638147a8f879f05d969855c13d083aafab9fa8", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27457,7 +27457,7 @@ ], "hash_code": "ce6c5523b17b77be323a526e757f04235f6d8a3023ac5208b12b7c34de4fcbb6", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27546,7 +27546,7 @@ ], "hash_code": "85b4b54f401f88fb286b6442b56fecb5922a025504207d94f5835e4b9e4c3d49", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27635,7 +27635,7 @@ ], "hash_code": "371010ba334ccc433d73bf0c9cdaec557d5f7ec338c6f925d8a71763a228d473", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27724,7 +27724,7 @@ ], "hash_code": "ea8b569d6c5fe9dba625c6540acd9880534f7a19a5bf4b84fb838ad65d08d26f", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27813,7 +27813,7 @@ ], "hash_code": "d0e517ef410747c79f882b9fc73a04a92ef6b4792017378ae5c4a39e21a921c5", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27902,7 +27902,7 @@ ], "hash_code": "f6025b614c1d26ee95556ebcb50473f42a57f04d7653abfd132e98baff1b433e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -27991,7 +27991,7 @@ ], "hash_code": "5852c73c2309bcf533c51c4b6c8221b0519229d4010090067bd6ea629971c099", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28080,7 +28080,7 @@ ], "hash_code": "39052e0796f538556f2cc6c00b63fbed65ab036a874c9ed0672e6825d68602a2", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28169,7 +28169,7 @@ ], "hash_code": "82b6e67fea88a46706b742dee6eb877a58f0ef800b00de81d044714ae2d83f6b", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28258,7 +28258,7 @@ ], "hash_code": "52d4696d8c8726e0689f91c534c78682a24d80d83406ac7c6d7c4f2952d7c25e", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28347,7 +28347,7 @@ ], "hash_code": "67622d1c580dd13b751a2f6684e3b1e764c0b2059520e9b6683c5b8a6560262a", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28436,7 +28436,7 @@ ], "hash_code": "a580f877f77e73dc81f13869c40402119ff4a964e2cc48fe4dcca3fb0a5e19a9", "impact": "N/A", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28525,7 +28525,7 @@ ], "hash_code": "df2a6f6aba05f414f30448d0594c327f3f9e7f075bff0008820e10d95b4ff3d5", "impact": "asdf", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28612,7 +28612,7 @@ ], "hash_code": "1dfa2d2c7161cea9a710a5cbe3e1bc7f0116625104edbe31d5de6260c82cf87a", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28701,7 +28701,7 @@ ], "hash_code": "b080d22cc9797327aeebd0e6437057cf1ef61dd128fbe7059388b279c45915bb", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28790,7 +28790,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28879,7 +28879,7 @@ ], "hash_code": "6190df674dd45e3b28b65c30bfd11b02ef3331eaffecac12a6ee3db03c1de36a", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -28968,7 +28968,7 @@ ], "hash_code": "dfd30d76898319d2181e4464cd74c71ddaca8afe0008b9c94fac41f5420ed62c", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29057,7 +29057,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29146,7 +29146,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29235,7 +29235,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29324,7 +29324,7 @@ ], "hash_code": "6190df674dd45e3b28b65c30bfd11b02ef3331eaffecac12a6ee3db03c1de36a", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29413,7 +29413,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29502,7 +29502,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29591,7 +29591,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29680,7 +29680,7 @@ ], "hash_code": "dfd30d76898319d2181e4464cd74c71ddaca8afe0008b9c94fac41f5420ed62c", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29769,7 +29769,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29858,7 +29858,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -29947,7 +29947,7 @@ ], "hash_code": "dfd30d76898319d2181e4464cd74c71ddaca8afe0008b9c94fac41f5420ed62c", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30036,7 +30036,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30125,7 +30125,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30214,7 +30214,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30303,7 +30303,7 @@ ], "hash_code": "5bf9791b69a7661dfcfac47b4284db7ff46f729ba30698d418e56c3f4c4f70db", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30392,7 +30392,7 @@ ], "hash_code": "cef2dcb7c7787157edc70e85d5017e72d1dbca1fd80909f5d76cda85a9bdec2c", "impact": "Most browsers have a facility to remember user credentials that are entered into HTML forms. This function can be configured by the user and also by applications that employ user credentials. If the function is enabled, then credentials entered by the user are stored on their local computer and retrieved by the browser on future visits to the same application.\n\nThe stored credentials can be captured by an attacker who gains control over the user's computer. Further, an attacker who finds a separate application vulnerability such as cross-site scripting may be able to exploit this to retrieve a user's browser-stored credentials. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30481,7 +30481,7 @@ ], "hash_code": "e2a968190c3c79023378ef6f30612b6119bc867f303aafc91eb3bd191d05b90d", "impact": "If a page fails to set an appropriate X-Frame-Options or Content-Security-Policy HTTP header, it might be possible for a page controlled by an attacker to load it within an iframe. This may enable a clickjacking attack, in which the attacker's page overlays the target application's interface with a different interface provided by the attacker. By inducing victim users to perform actions such as mouse clicks and keystrokes, the attacker can cause them to unwittingly carry out actions within the application that is being targeted. This technique allows the attacker to circumvent defenses against cross-site request forgery, and may result in unauthorized actions.\n\nNote that some applications attempt to prevent these attacks from within the HTML page itself, using \"framebusting\" code. However, this type of defense is normally ineffective and can usually be circumvented by a skilled attacker.\n\nYou should determine whether any functions accessible within frameable pages can be used by application users to perform any sensitive actions within the application. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30570,7 +30570,7 @@ ], "hash_code": "d0353a775431e2fcf6ba2245bba4a11a68a0961e4f6baba21095c56e4c52287c", "impact": "Reflected cross-site scripting vulnerabilities arise when data is copied from a request and echoed into the application's immediate response in an unsafe way. An attacker can use the vulnerability to construct a request that, if issued by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application.\n\nThe attacker-supplied code can perform a wide variety of actions, such as stealing the victim's session token or login credentials, performing arbitrary actions on the victim's behalf, and logging their keystrokes.\n\nUsers can be induced to issue the attacker's crafted request in various ways. For example, the attacker can send a victim a link containing a malicious URL in an email or instant message. They can submit the link to popular web sites that allow content authoring, for example in blog comments. And they can create an innocuous looking web site that causes anyone viewing it to make arbitrary cross-domain requests to the vulnerable application (using either the GET or the POST method).\n\nThe security impact of cross-site scripting vulnerabilities is dependent upon the nature of the vulnerable application, the kinds of data and functionality that it contains, and the other applications that belong to the same domain and organization. If the application is used only to display non-sensitive public content, with no authentication or access control functionality, then a cross-site scripting flaw may be considered low risk. However, if the same application resides on a domain that can access cookies for other more security-critical applications, then the vulnerability could be used to attack those other applications, and so may be considered high risk. Similarly, if the organization that owns the application is a likely target for phishing attacks, then the vulnerability could be leveraged to lend credibility to such attacks, by injecting Trojan functionality into the vulnerable application and exploiting users' trust in the organization in order to capture credentials for other applications that it owns. In many kinds of application, such as those providing online banking functionality, cross-site scripting should always be considered high risk. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30659,7 +30659,7 @@ ], "hash_code": "7b79656db5b18827a177cdef000720f62cf139c43bfbb8f1f6c2e1382e28b503", "impact": "The application allows users to connect to it over unencrypted connections. An attacker suitably positioned to view a legitimate user's network traffic could record and monitor their interactions with the application and obtain any information the user supplies. Furthermore, an attacker able to modify traffic could use the application as a platform for attacks against its users and third-party websites. Unencrypted connections have been exploited by ISPs and governments to track users, and to inject adverts and malicious JavaScript. Due to these concerns, web browser vendors are planning to visually flag unencrypted connections as hazardous.\n\nTo exploit this vulnerability, an attacker must be suitably positioned to eavesdrop on the victim's network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure. \n\nPlease note that using a mixture of encrypted and unencrypted communications is an ineffective defense against active attackers, because they can easily remove references to encrypted resources when these references are transmitted over an unencrypted connection.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30748,7 +30748,7 @@ ], "hash_code": "a073a661ec300f853780ebd20d17abefb6c3bcf666776ddea1ab2e3e3c6d9428", "impact": "Some applications return passwords submitted to the application in clear form in later responses. This behavior increases the risk that users' passwords will be captured by an attacker. Many types of vulnerability, such as weaknesses in session handling, broken access controls, and cross-site scripting, could enable an attacker to leverage this behavior to retrieve the passwords of other application users. This possibility typically exacerbates the impact of those other vulnerabilities, and in some situations can enable an attacker to quickly compromise the entire application.\n\nVulnerabilities that result in the disclosure of users' passwords can result in compromises that are extremely difficult to investigate due to obscured audit trails. Even if the application itself only handles non-sensitive information, exposing passwords puts users who have re-used their password elsewhere at risk.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30837,7 +30837,7 @@ ], "hash_code": "2b9640feda092762b423f98809677e58d24ccd79c948df2e052d3f22274ebe8f", "impact": "The presence of email addresses within application responses does not necessarily constitute a security vulnerability. Email addresses may appear intentionally within contact information, and many applications (such as web mail) include arbitrary third-party email addresses within their core content.\n\nHowever, email addresses of developers and other individuals (whether appearing on-screen or hidden within page source) may disclose information that is useful to an attacker; for example, they may represent usernames that can be used at the application's login, and they may be used in social engineering attacks against the organization's personnel. Unnecessary or excessive disclosure of email addresses may also lead to an increase in the volume of spam email received.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -30926,7 +30926,7 @@ ], "hash_code": "1c732e92e6e9b89c90bd4ef40579d4c06791cc635e6fb16c00f2d443c5922ffa", "impact": "Cross-site request forgery (CSRF) vulnerabilities may arise when applications rely solely on HTTP cookies to identify the user that has issued a particular request. Because browsers automatically add cookies to requests regardless of their origin, it may be possible for an attacker to create a malicious web site that forges a cross-domain request to the vulnerable application. For a request to be vulnerable to CSRF, the following conditions must hold:\n\n * The request can be issued cross-domain, for example using an HTML form. If the request contains non-standard headers or body content, then it may only be issuable from a page that originated on the same domain.\n * The application relies solely on HTTP cookies or Basic Authentication to identify the user that issued the request. If the application places session-related tokens elsewhere within the request, then it may not be vulnerable.\n * The request performs some privileged action within the application, which modifies the application's state based on the identity of the issuing user.\n * The attacker can determine all the parameters required to construct a request that performs the action. If the request contains any values that the attacker cannot determine or predict, then it is not vulnerable.\n\n\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31015,7 +31015,7 @@ ], "hash_code": "31215cff140491cdd84abb9246ad91145069efda2bdb319b75e2ee916219178a", "impact": "SQL injection vulnerabilities arise when user-controllable data is incorporated into database SQL queries in an unsafe manner. An attacker can supply crafted input to break out of the data context in which their input appears and interfere with the structure of the surrounding query.\n\nA wide range of damaging attacks can often be delivered via SQL injection, including reading or modifying critical application data, interfering with application logic, escalating privileges within the database and taking control of the database server. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31104,7 +31104,7 @@ ], "hash_code": "e2a968190c3c79023378ef6f30612b6119bc867f303aafc91eb3bd191d05b90d", "impact": "Path-relative style sheet import vulnerabilities arise when the following conditions hold:\n\n 1. A response contains a style sheet import that uses a path-relative URL (for example, the page at \"/original-path/file.php\" might import \"styles/main.css\").\n 2. When handling requests, the application or platform tolerates superfluous path-like data following the original filename in the URL (for example, \"/original-path/file.php/extra-junk/\"). When superfluous data is added to the original URL, the application's response still contains a path-relative stylesheet import.\n 3. The response in condition 2 can be made to render in a browser's quirks mode, either because it has a missing or old doctype directive, or because it allows itself to be framed by a page under an attacker's control.\n 4. When a browser requests the style sheet that is imported in the response from the modified URL (using the URL \"/original-path/file.php/extra-junk/styles/main.css\"), the application returns something other than the CSS response that was supposed to be imported. Given the behavior described in condition 2, this will typically be the same response that was originally returned in condition 1.\n 5. An attacker has a means of manipulating some text within the response in condition 4, for example because the application stores and displays some past input, or echoes some text within the current URL.\n\n\n\nGiven the above conditions, an attacker can execute CSS injection within the browser of the target user. The attacker can construct a URL that causes the victim's browser to import as CSS a different URL than normal, containing text that the attacker can manipulate. Being able to inject arbitrary CSS into the victim's browser may enable various attacks, including:\n\n * Executing arbitrary JavaScript using IE's expression() function.\n * Using CSS selectors to read parts of the HTML source, which may include sensitive data such as anti-CSRF tokens.\n * Capturing any sensitive data within the URL query string by making a further style sheet import to a URL on the attacker's domain, and monitoring the incoming Referer header.\n\n\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31193,7 +31193,7 @@ ], "hash_code": "cef2dcb7c7787157edc70e85d5017e72d1dbca1fd80909f5d76cda85a9bdec2c", "impact": "Some applications transmit passwords over unencrypted connections, making them vulnerable to interception. To exploit this vulnerability, an attacker must be suitably positioned to eavesdrop on the victim's network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure.\n\nVulnerabilities that result in the disclosure of users' passwords can result in compromises that are extremely difficult to investigate due to obscured audit trails. Even if the application itself only handles non-sensitive information, exposing passwords puts users who have re-used their password elsewhere at risk.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31282,7 +31282,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31371,7 +31371,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31460,7 +31460,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31549,7 +31549,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31638,7 +31638,7 @@ ], "hash_code": "929fb1c92b7a2aeeca7affb985361e279334bf9c72f1dd1e6120cfc134198ddd", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31727,7 +31727,7 @@ ], "hash_code": "58ce5492f2393592d59ae209ae350b52dc807c0418ebb0f7421c428dba7ce6a5", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31816,7 +31816,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31905,7 +31905,7 @@ ], "hash_code": "847363e3519e008224db4a0be2e123b779d1d7e8e9a26c9ff7fb09a1f8e010af", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -31994,7 +31994,7 @@ ], "hash_code": "01b1dd016d858a85a8d6ff3b60e68d5073f35b3d853c8cc076c2a65b22ddd37f", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32083,7 +32083,7 @@ ], "hash_code": "493bcf78ff02a621a02c282a3f85008d5c2d9aeaea342252083d3f66af9895b4", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32172,7 +32172,7 @@ ], "hash_code": "a1db5cdf4a0ef0f4b09c2e5205dd5d8ccb3522f5d0c92892c52f5bc2f81407ab", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32261,7 +32261,7 @@ ], "hash_code": "0e0592103f29773f1fcf3ec4d2bbadd094b71c0ed693fd7f437f21b1a7f466de", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32350,7 +32350,7 @@ ], "hash_code": "0e0592103f29773f1fcf3ec4d2bbadd094b71c0ed693fd7f437f21b1a7f466de", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32439,7 +32439,7 @@ ], "hash_code": "2573d64a8468fbbc714c4aa527a5e4f25c8283cbc2b538150e9405141fa47a95", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32528,7 +32528,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32617,7 +32617,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32706,7 +32706,7 @@ ], "hash_code": "6a2543c093ae3492085ed185e29728240264e6b42d20e2594afa0e3bde0df7ed", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32795,7 +32795,7 @@ ], "hash_code": "6a2543c093ae3492085ed185e29728240264e6b42d20e2594afa0e3bde0df7ed", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32884,7 +32884,7 @@ ], "hash_code": "409f83523798dff3b0158749c30b73728e1d3b193b51ee6cd1c6cd37c372d692", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -32973,7 +32973,7 @@ ], "hash_code": "822e39e3de094312f76b22d54357c8d7bbd9b015150b89e2664d45a9bba989e1", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33062,7 +33062,7 @@ ], "hash_code": "1569ac5fdd45a35ee5a0d1b93c485a834fbdc4fb9b73ad56414335ad9bd862ca", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33151,7 +33151,7 @@ ], "hash_code": "9b2ac951d86e5d4cd419cabdea51aca6a3aaadef4bae8683c655bdba8427669a", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33240,7 +33240,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33329,7 +33329,7 @@ ], "hash_code": "ac6eead6ef51634c47bbe1a2722fda95f0772202132e9a94d78b314a454533a9", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33418,7 +33418,7 @@ ], "hash_code": "b07a2dcd65f4741740291c39b71bc9312b4a0327196594046d6c48421c2ceea3", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33507,7 +33507,7 @@ ], "hash_code": "27a0fde11f7ea3c405d889bde32e8fe532dc07017d6329af39726761aca0a5aa", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33596,7 +33596,7 @@ ], "hash_code": "a1db5cdf4a0ef0f4b09c2e5205dd5d8ccb3522f5d0c92892c52f5bc2f81407ab", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33685,7 +33685,7 @@ ], "hash_code": "2f4ca826c1093b3fc8c55005f600410d9626704312a6a958544393f936ef9a66", "impact": "", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33774,7 +33774,7 @@ ], "hash_code": "cef2dcb7c7787157edc70e85d5017e72d1dbca1fd80909f5d76cda85a9bdec2c", "impact": "Most browsers have a facility to remember user credentials that are entered into HTML forms. This function can be configured by the user and also by applications that employ user credentials. If the function is enabled, then credentials entered by the user are stored on their local computer and retrieved by the browser on future visits to the same application.\n\nThe stored credentials can be captured by an attacker who gains control over the user's computer. Further, an attacker who finds a separate application vulnerability such as cross-site scripting may be able to exploit this to retrieve a user's browser-stored credentials. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33863,7 +33863,7 @@ ], "hash_code": "e2a968190c3c79023378ef6f30612b6119bc867f303aafc91eb3bd191d05b90d", "impact": "If a page fails to set an appropriate X-Frame-Options or Content-Security-Policy HTTP header, it might be possible for a page controlled by an attacker to load it within an iframe. This may enable a clickjacking attack, in which the attacker's page overlays the target application's interface with a different interface provided by the attacker. By inducing victim users to perform actions such as mouse clicks and keystrokes, the attacker can cause them to unwittingly carry out actions within the application that is being targeted. This technique allows the attacker to circumvent defenses against cross-site request forgery, and may result in unauthorized actions.\n\nNote that some applications attempt to prevent these attacks from within the HTML page itself, using \"framebusting\" code. However, this type of defense is normally ineffective and can usually be circumvented by a skilled attacker.\n\nYou should determine whether any functions accessible within frameable pages can be used by application users to perform any sensitive actions within the application. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -33952,7 +33952,7 @@ ], "hash_code": "d0353a775431e2fcf6ba2245bba4a11a68a0961e4f6baba21095c56e4c52287c", "impact": "Reflected cross-site scripting vulnerabilities arise when data is copied from a request and echoed into the application's immediate response in an unsafe way. An attacker can use the vulnerability to construct a request that, if issued by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application.\n\nThe attacker-supplied code can perform a wide variety of actions, such as stealing the victim's session token or login credentials, performing arbitrary actions on the victim's behalf, and logging their keystrokes.\n\nUsers can be induced to issue the attacker's crafted request in various ways. For example, the attacker can send a victim a link containing a malicious URL in an email or instant message. They can submit the link to popular web sites that allow content authoring, for example in blog comments. And they can create an innocuous looking web site that causes anyone viewing it to make arbitrary cross-domain requests to the vulnerable application (using either the GET or the POST method).\n\nThe security impact of cross-site scripting vulnerabilities is dependent upon the nature of the vulnerable application, the kinds of data and functionality that it contains, and the other applications that belong to the same domain and organization. If the application is used only to display non-sensitive public content, with no authentication or access control functionality, then a cross-site scripting flaw may be considered low risk. However, if the same application resides on a domain that can access cookies for other more security-critical applications, then the vulnerability could be used to attack those other applications, and so may be considered high risk. Similarly, if the organization that owns the application is a likely target for phishing attacks, then the vulnerability could be leveraged to lend credibility to such attacks, by injecting Trojan functionality into the vulnerable application and exploiting users' trust in the organization in order to capture credentials for other applications that it owns. In many kinds of application, such as those providing online banking functionality, cross-site scripting should always be considered high risk. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -34041,7 +34041,7 @@ ], "hash_code": "7b79656db5b18827a177cdef000720f62cf139c43bfbb8f1f6c2e1382e28b503", "impact": "The application allows users to connect to it over unencrypted connections. An attacker suitably positioned to view a legitimate user's network traffic could record and monitor their interactions with the application and obtain any information the user supplies. Furthermore, an attacker able to modify traffic could use the application as a platform for attacks against its users and third-party websites. Unencrypted connections have been exploited by ISPs and governments to track users, and to inject adverts and malicious JavaScript. Due to these concerns, web browser vendors are planning to visually flag unencrypted connections as hazardous.\n\nTo exploit this vulnerability, an attacker must be suitably positioned to eavesdrop on the victim's network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure. \n\nPlease note that using a mixture of encrypted and unencrypted communications is an ineffective defense against active attackers, because they can easily remove references to encrypted resources when these references are transmitted over an unencrypted connection.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -34130,7 +34130,7 @@ ], "hash_code": "a073a661ec300f853780ebd20d17abefb6c3bcf666776ddea1ab2e3e3c6d9428", "impact": "Some applications return passwords submitted to the application in clear form in later responses. This behavior increases the risk that users' passwords will be captured by an attacker. Many types of vulnerability, such as weaknesses in session handling, broken access controls, and cross-site scripting, could enable an attacker to leverage this behavior to retrieve the passwords of other application users. This possibility typically exacerbates the impact of those other vulnerabilities, and in some situations can enable an attacker to quickly compromise the entire application.\n\nVulnerabilities that result in the disclosure of users' passwords can result in compromises that are extremely difficult to investigate due to obscured audit trails. Even if the application itself only handles non-sensitive information, exposing passwords puts users who have re-used their password elsewhere at risk.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -34219,7 +34219,7 @@ ], "hash_code": "2b9640feda092762b423f98809677e58d24ccd79c948df2e052d3f22274ebe8f", "impact": "The presence of email addresses within application responses does not necessarily constitute a security vulnerability. Email addresses may appear intentionally within contact information, and many applications (such as web mail) include arbitrary third-party email addresses within their core content.\n\nHowever, email addresses of developers and other individuals (whether appearing on-screen or hidden within page source) may disclose information that is useful to an attacker; for example, they may represent usernames that can be used at the application's login, and they may be used in social engineering attacks against the organization's personnel. Unnecessary or excessive disclosure of email addresses may also lead to an increase in the volume of spam email received.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -34308,7 +34308,7 @@ ], "hash_code": "1c732e92e6e9b89c90bd4ef40579d4c06791cc635e6fb16c00f2d443c5922ffa", "impact": "Cross-site request forgery (CSRF) vulnerabilities may arise when applications rely solely on HTTP cookies to identify the user that has issued a particular request. Because browsers automatically add cookies to requests regardless of their origin, it may be possible for an attacker to create a malicious web site that forges a cross-domain request to the vulnerable application. For a request to be vulnerable to CSRF, the following conditions must hold:\n\n * The request can be issued cross-domain, for example using an HTML form. If the request contains non-standard headers or body content, then it may only be issuable from a page that originated on the same domain.\n * The application relies solely on HTTP cookies or Basic Authentication to identify the user that issued the request. If the application places session-related tokens elsewhere within the request, then it may not be vulnerable.\n * The request performs some privileged action within the application, which modifies the application's state based on the identity of the issuing user.\n * The attacker can determine all the parameters required to construct a request that performs the action. If the request contains any values that the attacker cannot determine or predict, then it is not vulnerable.\n\n\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -34397,7 +34397,7 @@ ], "hash_code": "31215cff140491cdd84abb9246ad91145069efda2bdb319b75e2ee916219178a", "impact": "SQL injection vulnerabilities arise when user-controllable data is incorporated into database SQL queries in an unsafe manner. An attacker can supply crafted input to break out of the data context in which their input appears and interfere with the structure of the surrounding query.\n\nA wide range of damaging attacks can often be delivered via SQL injection, including reading or modifying critical application data, interfering with application logic, escalating privileges within the database and taking control of the database server. \n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -34486,7 +34486,7 @@ ], "hash_code": "e2a968190c3c79023378ef6f30612b6119bc867f303aafc91eb3bd191d05b90d", "impact": "Path-relative style sheet import vulnerabilities arise when the following conditions hold:\n\n 1. A response contains a style sheet import that uses a path-relative URL (for example, the page at \"/original-path/file.php\" might import \"styles/main.css\").\n 2. When handling requests, the application or platform tolerates superfluous path-like data following the original filename in the URL (for example, \"/original-path/file.php/extra-junk/\"). When superfluous data is added to the original URL, the application's response still contains a path-relative stylesheet import.\n 3. The response in condition 2 can be made to render in a browser's quirks mode, either because it has a missing or old doctype directive, or because it allows itself to be framed by a page under an attacker's control.\n 4. When a browser requests the style sheet that is imported in the response from the modified URL (using the URL \"/original-path/file.php/extra-junk/styles/main.css\"), the application returns something other than the CSS response that was supposed to be imported. Given the behavior described in condition 2, this will typically be the same response that was originally returned in condition 1.\n 5. An attacker has a means of manipulating some text within the response in condition 4, for example because the application stores and displays some past input, or echoes some text within the current URL.\n\n\n\nGiven the above conditions, an attacker can execute CSS injection within the browser of the target user. The attacker can construct a URL that causes the victim's browser to import as CSS a different URL than normal, containing text that the attacker can manipulate. Being able to inject arbitrary CSS into the victim's browser may enable various attacks, including:\n\n * Executing arbitrary JavaScript using IE's expression() function.\n * Using CSS selectors to read parts of the HTML source, which may include sensitive data such as anti-CSRF tokens.\n * Capturing any sensitive data within the URL query string by making a further style sheet import to a URL on the attacker's domain, and monitoring the incoming Referer header.\n\n\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -34575,7 +34575,7 @@ ], "hash_code": "cef2dcb7c7787157edc70e85d5017e72d1dbca1fd80909f5d76cda85a9bdec2c", "impact": "Some applications transmit passwords over unencrypted connections, making them vulnerable to interception. To exploit this vulnerability, an attacker must be suitably positioned to eavesdrop on the victim's network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection such as public Wi-Fi, or a corporate or home network that is shared with a compromised computer. Common defenses such as switched networks are not sufficient to prevent this. An attacker situated in the user's ISP or the application's hosting infrastructure could also perform this attack. Note that an advanced adversary could potentially target any connection made over the Internet's core infrastructure.\n\nVulnerabilities that result in the disclosure of users' passwords can result in compromises that are extremely difficult to investigate due to obscured audit trails. Even if the application itself only handles non-sensitive information, exposing passwords puts users who have re-used their password elsewhere at risk.\n", - "inherited_tags": [], + "_inherited_tag_names": [], "is_mitigated": false, "kev_date": null, "known_exploited": false, @@ -45651,7 +45651,7 @@ { "fields": { "created": "2026-02-26T19:36:48.224385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "ssh://127.0.0.1", "tags": [], @@ -45663,7 +45663,7 @@ { "fields": { "created": "2026-02-26T19:36:48.245385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "127.0.0.1", "tags": [], @@ -45675,7 +45675,7 @@ { "fields": { "created": "2026-02-26T19:36:48.256385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "ftp://localhost/", "tags": [], @@ -45687,7 +45687,7 @@ { "fields": { "created": "2026-02-26T19:36:48.266385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/", "tags": [], @@ -45699,7 +45699,7 @@ { "fields": { "created": "2026-02-26T19:36:48.276385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/", "tags": [], @@ -45711,7 +45711,7 @@ { "fields": { "created": "2026-02-26T19:36:48.286385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/about.jsp", "tags": [], @@ -45723,7 +45723,7 @@ { "fields": { "created": "2026-02-26T19:36:48.296385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/admin.jsp", "tags": [], @@ -45735,7 +45735,7 @@ { "fields": { "created": "2026-02-26T19:36:48.307385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/advanced.jsp", "tags": [], @@ -45747,7 +45747,7 @@ { "fields": { "created": "2026-02-26T19:36:48.317385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/basket.jsp", "tags": [], @@ -45759,7 +45759,7 @@ { "fields": { "created": "2026-02-26T19:36:48.327385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/contact.jsp", "tags": [], @@ -45771,7 +45771,7 @@ { "fields": { "created": "2026-02-26T19:36:48.339385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/home.jsp", "tags": [], @@ -45783,7 +45783,7 @@ { "fields": { "created": "2026-02-26T19:36:48.348385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/login.jsp", "tags": [], @@ -45795,7 +45795,7 @@ { "fields": { "created": "2026-02-26T19:36:48.359385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/logout.jsp", "tags": [], @@ -45807,7 +45807,7 @@ { "fields": { "created": "2026-02-26T19:36:48.369385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/password.jsp", "tags": [], @@ -45819,7 +45819,7 @@ { "fields": { "created": "2026-02-26T19:36:48.380385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/product.jsp", "tags": [], @@ -45831,7 +45831,7 @@ { "fields": { "created": "2026-02-26T19:36:48.391385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/register.jsp", "tags": [], @@ -45843,7 +45843,7 @@ { "fields": { "created": "2026-02-26T19:36:48.401385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/score.jsp", "tags": [], @@ -45855,7 +45855,7 @@ { "fields": { "created": "2026-02-26T19:36:48.411385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://localhost:8888/bodgeit/search.jsp", "tags": [], @@ -45867,7 +45867,7 @@ { "fields": { "created": "2026-02-26T19:36:48.421385054Z", - "inherited_tags": [], + "_inherited_tag_names": [], "location_type": "url", "location_value": "http://127.0.0.1/endpoint/420/edit/", "tags": [], diff --git a/dojo/fixtures/dojo_testdata_locations.json b/dojo/fixtures/dojo_testdata_locations.json index 3979f87d6f8..01a1ac9a9cd 100644 --- a/dojo/fixtures/dojo_testdata_locations.json +++ b/dojo/fixtures/dojo_testdata_locations.json @@ -3151,7 +3151,7 @@ "notes": [], "files": [], "tags": [], - "inherited_tags": [] + "_inherited_tag_names": [] } }, { @@ -3238,7 +3238,7 @@ 1000 ], "tags": [], - "inherited_tags": [] + "_inherited_tag_names": [] } }, { @@ -3311,7 +3311,7 @@ "notes": [], "files": [], "tags": [], - "inherited_tags": [] + "_inherited_tag_names": [] } }, { @@ -3398,7 +3398,7 @@ 1001 ], "tags": [], - "inherited_tags": [] + "_inherited_tag_names": [] } }, { From f57e775064836ed9ed858682cc95d82373c6f677 Mon Sep 17 00:00:00 2001 From: Valentijn Scholten Date: Thu, 7 May 2026 00:09:49 +0200 Subject: [PATCH 12/12] fix(tags): handle list input in _sync_inheritance_for_qs + recalibrate Stage 3 pins After Stage 2's location precompute landed under Stage 3, the `locations` list passed by `propagate_tags_on_product_sync` reached `_sync_inheritance_for_qs` which tried to call `.only(...)` on it. Accept either a list or a queryset. Recalibrate V3 pins for the Stage 2 + Stage 3 compound effect: - product_tag_add (100 locations): 123 -> 75 - product_tag_remove (100 locations): 73 -> 49 - ZAP scan import: 698 -> 661 - ZAP scan reimport, no change: 136 -> 99 --- dojo/product/helpers.py | 2 +- unittests/test_tag_inheritance_perf.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dojo/product/helpers.py b/dojo/product/helpers.py index 17cab218f02..b8f11bd2463 100644 --- a/dojo/product/helpers.py +++ b/dojo/product/helpers.py @@ -129,7 +129,7 @@ def _sync_inheritance_for_qs(queryset, *, target_names_per_child): - bulk add/remove on `tags` based on the diff - bulk UPDATE of `_inherited_tag_names` """ - children = list(queryset.only("pk", "_inherited_tag_names")) + children = queryset if isinstance(queryset, list) else list(queryset.only("pk", "_inherited_tag_names")) if not children: return diff --git a/unittests/test_tag_inheritance_perf.py b/unittests/test_tag_inheritance_perf.py index 8e5dee477bd..29ff6e80351 100644 --- a/unittests/test_tag_inheritance_perf.py +++ b/unittests/test_tag_inheritance_perf.py @@ -385,9 +385,9 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self): # V3 location paths. Pre-Phase-A: 4532 add, 4307 remove. # Phase B Stage 2 + location precompute: bulk-built target-name map. - # Stage 3 may further drop these once JSON column replaces M2M reads. - EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 123 - EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 73 + # Stage 3 (JSON column) collapsed inherited_tags M2M reads further. + EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 75 + EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 49 @override_settings( @@ -509,6 +509,6 @@ def test_baseline_zap_scan_reimport_no_change_v3(self): # when there's no work. Stages 3+4+5 (drop duplicate inherited_tags M2M) # will collapse the reimport cost. EXPECTED_ZAP_IMPORT_V2 = 700 - EXPECTED_ZAP_IMPORT_V3 = 698 + EXPECTED_ZAP_IMPORT_V3 = 661 EXPECTED_ZAP_REIMPORT_NO_CHANGE_V2 = 78 - EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 136 + EXPECTED_ZAP_REIMPORT_NO_CHANGE_V3 = 99