regscale-cli 6.25.1.0__py3-none-any.whl → 6.26.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of regscale-cli might be problematic. Click here for more details.

Files changed (80) hide show
  1. regscale/_version.py +1 -1
  2. regscale/airflow/hierarchy.py +2 -2
  3. regscale/core/app/application.py +18 -3
  4. regscale/core/app/internal/login.py +0 -1
  5. regscale/core/app/utils/catalog_utils/common.py +1 -1
  6. regscale/integrations/commercial/sicura/api.py +14 -13
  7. regscale/integrations/commercial/sicura/commands.py +8 -2
  8. regscale/integrations/commercial/sicura/scanner.py +49 -39
  9. regscale/integrations/commercial/stigv2/ckl_parser.py +5 -5
  10. regscale/integrations/commercial/wizv2/click.py +26 -26
  11. regscale/integrations/commercial/wizv2/compliance_report.py +152 -157
  12. regscale/integrations/commercial/wizv2/scanner.py +3 -3
  13. regscale/integrations/compliance_integration.py +67 -2
  14. regscale/integrations/control_matcher.py +358 -0
  15. regscale/integrations/milestone_manager.py +291 -0
  16. regscale/integrations/public/__init__.py +1 -0
  17. regscale/integrations/public/cci_importer.py +37 -38
  18. regscale/integrations/public/fedramp/click.py +60 -2
  19. regscale/integrations/public/fedramp/poam_export_v5.py +888 -0
  20. regscale/integrations/scanner_integration.py +150 -96
  21. regscale/models/integration_models/cisa_kev_data.json +154 -4
  22. regscale/models/integration_models/nexpose.py +36 -10
  23. regscale/models/integration_models/synqly_models/capabilities.json +1 -1
  24. regscale/models/locking.py +12 -8
  25. regscale/models/platform.py +1 -2
  26. regscale/models/regscale_models/control_implementation.py +46 -21
  27. regscale/models/regscale_models/issue.py +256 -94
  28. regscale/models/regscale_models/milestone.py +1 -1
  29. regscale/models/regscale_models/regscale_model.py +6 -1
  30. regscale/templates/__init__.py +0 -0
  31. {regscale_cli-6.25.1.0.dist-info → regscale_cli-6.26.0.0.dist-info}/METADATA +1 -1
  32. {regscale_cli-6.25.1.0.dist-info → regscale_cli-6.26.0.0.dist-info}/RECORD +80 -33
  33. tests/regscale/integrations/commercial/__init__.py +0 -0
  34. tests/regscale/integrations/commercial/conftest.py +28 -0
  35. tests/regscale/integrations/commercial/microsoft_defender/__init__.py +1 -0
  36. tests/regscale/integrations/commercial/microsoft_defender/test_defender.py +1517 -0
  37. tests/regscale/integrations/commercial/microsoft_defender/test_defender_api.py +1748 -0
  38. tests/regscale/integrations/commercial/microsoft_defender/test_defender_constants.py +327 -0
  39. tests/regscale/integrations/commercial/microsoft_defender/test_defender_scanner.py +487 -0
  40. tests/regscale/integrations/commercial/test_aws.py +3731 -0
  41. tests/regscale/integrations/commercial/test_burp.py +48 -0
  42. tests/regscale/integrations/commercial/test_crowdstrike.py +49 -0
  43. tests/regscale/integrations/commercial/test_dependabot.py +341 -0
  44. tests/regscale/integrations/commercial/test_gcp.py +1543 -0
  45. tests/regscale/integrations/commercial/test_gitlab.py +549 -0
  46. tests/regscale/integrations/commercial/test_ip_mac_address_length.py +84 -0
  47. tests/regscale/integrations/commercial/test_jira.py +1814 -0
  48. tests/regscale/integrations/commercial/test_npm_audit.py +42 -0
  49. tests/regscale/integrations/commercial/test_okta.py +1228 -0
  50. tests/regscale/integrations/commercial/test_sarif_converter.py +251 -0
  51. tests/regscale/integrations/commercial/test_sicura.py +350 -0
  52. tests/regscale/integrations/commercial/test_snow.py +423 -0
  53. tests/regscale/integrations/commercial/test_sonarcloud.py +394 -0
  54. tests/regscale/integrations/commercial/test_sqlserver.py +186 -0
  55. tests/regscale/integrations/commercial/test_stig.py +33 -0
  56. tests/regscale/integrations/commercial/test_stig_mapper.py +153 -0
  57. tests/regscale/integrations/commercial/test_stigv2.py +406 -0
  58. tests/regscale/integrations/commercial/test_wiz.py +1469 -0
  59. tests/regscale/integrations/commercial/test_wiz_inventory.py +256 -0
  60. tests/regscale/integrations/commercial/wizv2/__init__.py +339 -0
  61. tests/regscale/integrations/commercial/wizv2/test_compliance_report_normalization.py +138 -0
  62. tests/regscale/integrations/commercial/wizv2/test_issue.py +343 -0
  63. tests/regscale/integrations/commercial/wizv2/test_wiz_click_client_id.py +165 -0
  64. tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_report.py +1351 -0
  65. tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_unit.py +341 -0
  66. tests/regscale/integrations/commercial/wizv2/test_wiz_control_normalization.py +138 -0
  67. tests/regscale/integrations/commercial/wizv2/test_wiz_policy_compliance.py +750 -0
  68. tests/regscale/integrations/commercial/wizv2/test_wiz_status_mapping.py +149 -0
  69. tests/regscale/integrations/commercial/wizv2/test_wizv2.py +264 -0
  70. tests/regscale/integrations/commercial/wizv2/test_wizv2_utils.py +624 -0
  71. tests/regscale/integrations/public/fedramp/__init__.py +1 -0
  72. tests/regscale/integrations/public/fedramp/test_poam_export_v5.py +1293 -0
  73. tests/regscale/integrations/test_control_matcher.py +1314 -0
  74. tests/regscale/integrations/test_control_matching.py +155 -0
  75. tests/regscale/integrations/test_milestone_manager.py +408 -0
  76. tests/regscale/models/test_issue.py +378 -1
  77. {regscale_cli-6.25.1.0.dist-info → regscale_cli-6.26.0.0.dist-info}/LICENSE +0 -0
  78. {regscale_cli-6.25.1.0.dist-info → regscale_cli-6.26.0.0.dist-info}/WHEEL +0 -0
  79. {regscale_cli-6.25.1.0.dist-info → regscale_cli-6.26.0.0.dist-info}/entry_points.txt +0 -0
  80. {regscale_cli-6.25.1.0.dist-info → regscale_cli-6.26.0.0.dist-info}/top_level.txt +0 -0
@@ -27,6 +27,7 @@ from regscale.integrations.commercial.durosuite.process_devices import scan_duro
27
27
  from regscale.integrations.commercial.durosuite.variables import DuroSuiteVariables
28
28
  from regscale.integrations.commercial.stig_mapper_integration.mapping_engine import StigMappingEngine as STIGMapper
29
29
  from regscale.integrations.due_date_handler import DueDateHandler
30
+ from regscale.integrations.milestone_manager import MilestoneManager
30
31
  from regscale.integrations.public.cisa import pull_cisa_kev
31
32
  from regscale.integrations.variables import ScannerVariables
32
33
  from regscale.models import DateTimeEncoder, OpenIssueDict, Property, regscale_models
@@ -672,6 +673,9 @@ class ScannerIntegration(ABC):
672
673
  # Initialize due date handler for this integration
673
674
  self.due_date_handler = DueDateHandler(self.title, config=self.app.config)
674
675
 
676
+ # Initialize milestone manager for this integration
677
+ self.milestone_manager = None # Lazy initialization after scan_date is set
678
+
675
679
  if self.is_component:
676
680
  self.component = regscale_models.Component.get_object(self.plan_id)
677
681
  self.parent_module: str = regscale_models.Component.get_module_string()
@@ -737,6 +741,21 @@ class ScannerIntegration(ABC):
737
741
  cls._lock_registry[key] = lock
738
742
  return lock
739
743
 
744
+ def get_milestone_manager(self) -> MilestoneManager:
745
+ """
746
+ Get or initialize the milestone manager.
747
+
748
+ :return: MilestoneManager instance
749
+ :rtype: MilestoneManager
750
+ """
751
+ if self.milestone_manager is None:
752
+ self.milestone_manager = MilestoneManager(
753
+ integration_title=self.title,
754
+ assessor_id=self.assessor_id,
755
+ scan_date=self.scan_date or get_current_datetime(),
756
+ )
757
+ return self.milestone_manager
758
+
740
759
  @staticmethod
741
760
  def load_stig_mapper() -> Optional[STIGMapper]:
742
761
  """
@@ -997,15 +1016,18 @@ class ScannerIntegration(ABC):
997
1016
  return res[:450]
998
1017
  return prefix[:450]
999
1018
 
1000
- def get_or_create_assessment(self, control_implementation_id: int) -> regscale_models.Assessment:
1019
+ def get_or_create_assessment(
1020
+ self, control_implementation_id: int, status: Optional[regscale_models.AssessmentResultsStatus] = None
1021
+ ) -> regscale_models.Assessment:
1001
1022
  """
1002
- Gets or creates a RegScale assessment
1023
+ Gets or creates a RegScale assessment.
1003
1024
 
1004
1025
  :param int control_implementation_id: The ID of the control implementation
1026
+ :param Optional[regscale_models.AssessmentResultsStatus] status: Optional status override (used by cci_assessment)
1005
1027
  :return: The assessment
1006
1028
  :rtype: regscale_models.Assessment
1007
1029
  """
1008
- logger.info("Getting or create assessment for control implementation %d", control_implementation_id)
1030
+ logger.debug("Getting or create assessment for control implementation %d", control_implementation_id)
1009
1031
  assessment: Optional[regscale_models.Assessment] = self.assessment_map.get(control_implementation_id)
1010
1032
  if assessment:
1011
1033
  logger.debug(
@@ -1017,7 +1039,7 @@ class ScannerIntegration(ABC):
1017
1039
  plannedStart=get_current_datetime(),
1018
1040
  plannedFinish=get_current_datetime(),
1019
1041
  status=regscale_models.AssessmentStatus.COMPLETE.value,
1020
- assessmentResult=regscale_models.AssessmentResultsStatus.FAIL.value,
1042
+ assessmentResult=status.value if status else regscale_models.AssessmentResultsStatus.FAIL.value,
1021
1043
  actualFinish=get_current_datetime(),
1022
1044
  leadAssessorId=self.assessor_id,
1023
1045
  parentId=control_implementation_id,
@@ -2284,87 +2306,26 @@ class ScannerIntegration(ABC):
2284
2306
  """
2285
2307
  Create milestones for an issue based on status transitions.
2286
2308
 
2309
+ Delegates to MilestoneManager for cleaner separation of concerns.
2310
+ Also ensures existing issues have creation milestones (backfills if missing).
2311
+
2287
2312
  :param regscale_models.Issue issue: The issue to create milestones for
2288
2313
  :param IntegrationFinding finding: The finding data
2289
2314
  :param Optional[regscale_models.Issue] existing_issue: Existing issue for comparison
2290
2315
  """
2291
- if not (ScannerVariables.useMilestones and issue.id):
2292
- return
2293
-
2294
- if self._should_create_reopened_milestone(existing_issue, issue):
2295
- self._create_milestone_safe(
2296
- issue, finding, "Issue reopened from", get_current_datetime(), "reopened milestone"
2297
- )
2298
- elif self._should_create_closed_milestone(existing_issue, issue):
2299
- self._create_milestone_safe(issue, finding, "Issue closed from", issue.dateCompleted, "closed milestone")
2300
- elif not existing_issue:
2301
- self._create_milestone_safe(issue, finding, "Issue created from", self.scan_date, "new issue milestone")
2302
- else:
2303
- logger.debug("No milestone created for issue %s from finding %s", issue.id, finding.external_id)
2316
+ milestone_manager = self.get_milestone_manager()
2304
2317
 
2305
- def _should_create_reopened_milestone(
2306
- self, existing_issue: Optional[regscale_models.Issue], issue: regscale_models.Issue
2307
- ) -> bool:
2308
- """
2309
- Check if a reopened milestone should be created.
2310
-
2311
- :param Optional[regscale_models.Issue] existing_issue: The existing issue
2312
- :param regscale_models.Issue issue: The current issue
2313
- :return: True if reopened milestone should be created
2314
- :rtype: bool
2315
- """
2316
- return (
2317
- existing_issue
2318
- and existing_issue.status == regscale_models.IssueStatus.Closed
2319
- and issue.status == regscale_models.IssueStatus.Open
2320
- )
2321
-
2322
- def _should_create_closed_milestone(
2323
- self, existing_issue: Optional[regscale_models.Issue], issue: regscale_models.Issue
2324
- ) -> bool:
2325
- """
2326
- Check if a closed milestone should be created.
2318
+ # For existing issues, ensure they have a creation milestone (backfill if missing)
2319
+ if existing_issue:
2320
+ milestone_manager.ensure_creation_milestone_exists(issue=issue, finding=finding)
2327
2321
 
2328
- :param Optional[regscale_models.Issue] existing_issue: The existing issue
2329
- :param regscale_models.Issue issue: The current issue
2330
- :return: True if closed milestone should be created
2331
- :rtype: bool
2332
- """
2333
- return (
2334
- existing_issue
2335
- and existing_issue.status == regscale_models.IssueStatus.Open
2336
- and issue.status == regscale_models.IssueStatus.Closed
2322
+ # Handle status transition milestones
2323
+ milestone_manager.create_milestones_for_issue(
2324
+ issue=issue,
2325
+ finding=finding,
2326
+ existing_issue=existing_issue,
2337
2327
  )
2338
2328
 
2339
- def _create_milestone_safe(
2340
- self,
2341
- issue: regscale_models.Issue,
2342
- finding: IntegrationFinding,
2343
- title_prefix: str,
2344
- milestone_date: str,
2345
- milestone_type: str,
2346
- ) -> None:
2347
- """
2348
- Safely create a milestone with error handling.
2349
-
2350
- :param regscale_models.Issue issue: The issue to create milestone for
2351
- :param IntegrationFinding finding: The finding data
2352
- :param str title_prefix: Prefix for milestone title
2353
- :param str milestone_date: Date for the milestone
2354
- :param str milestone_type: Description for logging purposes
2355
- """
2356
- try:
2357
- regscale_models.Milestone(
2358
- title=f"{title_prefix} {self.title} scan",
2359
- milestoneDate=milestone_date,
2360
- responsiblePersonId=self.assessor_id,
2361
- parentID=issue.id,
2362
- parentModule="issues",
2363
- ).create_or_update()
2364
- logger.debug("Added milestone for issue %s from finding %s", issue.id, finding.external_id)
2365
- except Exception as e:
2366
- logger.warning("Failed to create %s: %s", milestone_type, str(e))
2367
-
2368
2329
  @staticmethod
2369
2330
  def extra_data_to_properties(finding: IntegrationFinding, issue_id: int) -> None:
2370
2331
  """
@@ -2530,6 +2491,8 @@ class ScannerIntegration(ABC):
2530
2491
  if found_issue.controlImplementationIds:
2531
2492
  for control_id in found_issue.controlImplementationIds:
2532
2493
  self.update_control_implementation_status_after_close(control_id)
2494
+ # Update assessment status to reflect the control implementation status
2495
+ self.update_assessment_status_from_control_implementation(control_id)
2533
2496
 
2534
2497
  def handle_failing_checklist(
2535
2498
  self,
@@ -2554,11 +2517,13 @@ class ScannerIntegration(ABC):
2554
2517
  if failing_objective.name.lower().startswith("cci-"):
2555
2518
  implementation_id = self.get_control_implementation_id_for_cci(failing_objective.name)
2556
2519
  else:
2557
- control_label = objective_to_control_dot(failing_objective.name)
2558
- if control_label not in self.control_implementation_id_map:
2559
- logger.warning("Control %s not found for %s", control_label, control_label)
2560
- continue
2561
- implementation_id = self.control_implementation_id_map[control_label]
2520
+ implementation_id = self._fallback_implementation_id(failing_objective)
2521
+
2522
+ if not implementation_id or implementation_id is None:
2523
+ logger.warning(
2524
+ "Could not map objective to a Control Implementation for objective #%i.", failing_objective.id
2525
+ )
2526
+ continue
2562
2527
 
2563
2528
  failing_option = regscale_models.ImplementationOption(
2564
2529
  name="Failed STIG",
@@ -2580,13 +2545,36 @@ class ScannerIntegration(ABC):
2580
2545
  ).create_or_update()
2581
2546
 
2582
2547
  # Create assessment and control test result
2583
- assessment = self.get_or_create_assessment(implementation_id)
2548
+ assessment = self.get_or_create_assessment(
2549
+ implementation_id, status=regscale_models.AssessmentResultsStatus.FAIL
2550
+ )
2584
2551
  if implementation_id:
2585
2552
  control_test = self.create_or_get_control_test(finding, implementation_id)
2586
2553
  self.create_control_test_result(
2587
2554
  finding, control_test, assessment, regscale_models.ControlTestResultStatus.FAIL
2588
2555
  )
2589
2556
 
2557
+ def _fallback_implementation_id(self, objective: regscale_models.ControlObjective) -> Optional[int]:
2558
+ """
2559
+ Fallback method to get control implementation ID from objective name if CCI mapping fails.
2560
+
2561
+ :param regscale_models.ControlObjective objective: The control objective
2562
+ :return: The control implementation ID if found, None otherwise
2563
+ :rtype: Optional[int]
2564
+ """
2565
+ control_label = objective_to_control_dot(objective.name)
2566
+ if implementation_id := self.control_implementation_id_map.get(control_label):
2567
+ return implementation_id
2568
+
2569
+ if control_id := self.control_id_to_implementation_map.get(objective.securityControlId):
2570
+ if control_label := self.control_map.get(control_id):
2571
+ implementation_id = self.control_implementation_id_map.get(control_label)
2572
+ if not implementation_id:
2573
+ print("No dice.")
2574
+ return implementation_id
2575
+ logger.debug("Could not find fallback implementation ID for objective #%i", objective.id)
2576
+ return None
2577
+
2590
2578
  def handle_passing_checklist(
2591
2579
  self,
2592
2580
  finding: IntegrationFinding,
@@ -2610,15 +2598,12 @@ class ScannerIntegration(ABC):
2610
2598
  if passing_objective.name.lower().startswith("cci-"):
2611
2599
  implementation_id = self.get_control_implementation_id_for_cci(passing_objective.name)
2612
2600
  else:
2613
- control_label = objective_to_control_dot(passing_objective.name)
2614
- if control_label not in self.control_implementation_id_map:
2615
- logger.warning("Control %s not found for %s", control_label, control_label)
2616
- continue
2617
- implementation_id = self.control_implementation_id_map[control_label]
2618
-
2619
- # Skip if we couldn't determine the implementation ID
2620
- if implementation_id is None:
2621
- logger.warning("Could not determine implementation ID for objective %s", passing_objective.name)
2601
+ implementation_id = self._fallback_implementation_id(passing_objective)
2602
+
2603
+ if not implementation_id or implementation_id is None:
2604
+ logger.warning(
2605
+ "Could not map objective to a Control Implementation for objective #%i.", passing_objective.id
2606
+ )
2622
2607
  continue
2623
2608
 
2624
2609
  passing_option = regscale_models.ImplementationOption(
@@ -2641,7 +2626,9 @@ class ScannerIntegration(ABC):
2641
2626
  ).create_or_update()
2642
2627
 
2643
2628
  # Create assessment and control test result
2644
- assessment = self.get_or_create_assessment(implementation_id)
2629
+ assessment = self.get_or_create_assessment(
2630
+ implementation_id, status=regscale_models.AssessmentResultsStatus.PASS
2631
+ )
2645
2632
  control_test = self.create_or_get_control_test(finding, implementation_id)
2646
2633
  self.create_control_test_result(
2647
2634
  finding, control_test, assessment, regscale_models.ControlTestResultStatus.PASS
@@ -2706,7 +2693,11 @@ class ScannerIntegration(ABC):
2706
2693
  logger.error("2. Asset not found for identifier %s", finding.asset_identifier)
2707
2694
  return 0
2708
2695
 
2709
- tool = regscale_models.ChecklistTool.STIGs
2696
+ tool = (
2697
+ regscale_models.ChecklistTool.CISBenchmarks
2698
+ if "simp.cis" in str(finding.vulnerability_number).lower()
2699
+ else regscale_models.ChecklistTool.STIGs
2700
+ )
2710
2701
  if finding.vulnerability_type == "Vulnerability Scan":
2711
2702
  tool = regscale_models.ChecklistTool.VulnerabilityScanner
2712
2703
 
@@ -3381,6 +3372,8 @@ class ScannerIntegration(ABC):
3381
3372
 
3382
3373
  for control_id in affected_control_ids:
3383
3374
  self.update_control_implementation_status_after_close(control_id)
3375
+ # Update assessment status to reflect the control implementation status
3376
+ self.update_assessment_status_from_control_implementation(control_id)
3384
3377
 
3385
3378
  (
3386
3379
  logger.info("Closed %d outdated issues.", closed_count)
@@ -3483,9 +3476,70 @@ class ScannerIntegration(ABC):
3483
3476
  if control_implementation.status != new_status:
3484
3477
  control_implementation.status = new_status
3485
3478
  self.control_implementation_map[control_id] = control_implementation.save()
3486
- logger.info("Updated control implementation %d status to %s", control_id, new_status)
3479
+ logger.debug("Updated control implementation %d status to %s", control_id, new_status)
3480
+
3481
+ def update_assessment_status_from_control_implementation(self, control_implementation_id: int) -> None:
3482
+ """
3483
+ Updates the assessment status based on the control implementation status.
3484
+ Treats the ControlImplementation status as the source of truth.
3487
3485
 
3488
- def is_issue_protected_from_auto_close(self, issue: regscale_models.Issue) -> bool:
3486
+ Sets assessment to PASS if ControlImplementation status is FULLY_IMPLEMENTED,
3487
+ otherwise sets it to FAIL.
3488
+
3489
+ This method should be called after update_control_implementation_status_after_close
3490
+ to ensure assessments reflect the final control implementation state.
3491
+
3492
+ :param int control_implementation_id: The ID of the control implementation
3493
+ :rtype: None
3494
+ """
3495
+ # Get the cached assessment for this control implementation
3496
+ assessment = self.assessment_map.get(control_implementation_id)
3497
+
3498
+ if not assessment:
3499
+ logger.debug(
3500
+ "No assessment found in cache for control implementation %d, skipping assessment update",
3501
+ control_implementation_id,
3502
+ )
3503
+ return
3504
+
3505
+ # Get the control implementation to check its status
3506
+ control_implementation = self.control_implementation_map.get(
3507
+ control_implementation_id
3508
+ ) or regscale_models.ControlImplementation.get_object(object_id=control_implementation_id)
3509
+
3510
+ if not control_implementation:
3511
+ logger.warning("Control implementation %d not found, cannot update assessment", control_implementation_id)
3512
+ return
3513
+
3514
+ # Determine assessment result based on control implementation status
3515
+ # Treat ControlImplementation status as the source of truth
3516
+ new_assessment_result = (
3517
+ regscale_models.AssessmentResultsStatus.PASS
3518
+ if control_implementation.status == regscale_models.ImplementationStatus.FULLY_IMPLEMENTED.value
3519
+ else regscale_models.AssessmentResultsStatus.FAIL
3520
+ )
3521
+
3522
+ # Only update if the status has changed
3523
+ if assessment.assessmentResult != new_assessment_result.value:
3524
+ assessment.assessmentResult = new_assessment_result.value
3525
+ assessment.save()
3526
+ logger.debug(
3527
+ "Updated assessment %d for control implementation %d: assessmentResult=%s (based on control status: %s)",
3528
+ assessment.id,
3529
+ control_implementation_id,
3530
+ new_assessment_result.value,
3531
+ control_implementation.status,
3532
+ )
3533
+ else:
3534
+ logger.debug(
3535
+ "Assessment %d already has correct status %s for control implementation %d",
3536
+ assessment.id,
3537
+ assessment.assessmentResult,
3538
+ control_implementation_id,
3539
+ )
3540
+
3541
+ @staticmethod
3542
+ def is_issue_protected_from_auto_close(issue: regscale_models.Issue) -> bool:
3489
3543
  """
3490
3544
  Check if an issue is protected from automatic closure.
3491
3545
 
@@ -1,9 +1,159 @@
1
1
  {
2
2
  "title": "CISA Catalog of Known Exploited Vulnerabilities",
3
- "catalogVersion": "2025.09.25",
4
- "dateReleased": "2025-09-25T16:17:38.0447Z",
5
- "count": 1417,
3
+ "catalogVersion": "2025.10.02",
4
+ "dateReleased": "2025-10-02T14:59:13.7696Z",
5
+ "count": 1427,
6
6
  "vulnerabilities": [
7
+ {
8
+ "cveID": "CVE-2014-6278",
9
+ "vendorProject": "GNU",
10
+ "product": "GNU Bash",
11
+ "vulnerabilityName": "GNU Bash OS Command Injection Vulnerability",
12
+ "dateAdded": "2025-10-02",
13
+ "shortDescription": "GNU Bash contains an OS command injection vulnerability which allows remote attackers to execute arbitrary commands via a crafted environment.",
14
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable. ",
15
+ "dueDate": "2025-10-23",
16
+ "knownRansomwareCampaignUse": "Unknown",
17
+ "notes": "This vulnerability could affect an open-source component, third-party library, protocol, or proprietary implementation that could be used by different products. For more information, please see: http:\/\/ftp.gnu.org\/gnu\/bash\/bash-4.3-patches\/bash43-027 ; https:\/\/support.broadcom.com\/web\/ecx\/support-content-notification\/-\/external\/content\/SecurityAdvisories\/0\/23467 ; https:\/\/sec.cloudapps.cisco.com\/security\/center\/content\/CiscoSecurityAdvisory\/cisco-sa-20140926-bash ; https:\/\/www.ibm.com\/support\/pages\/security-bulletin-update-vulnerabilities-bash-affect-aix-toolbox-linux-applications-cve-2014-6271-cve-2014-6277-cve-2014-6278-cve-2014-7169-cve-2014-7186-and-cve-2014-7187 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2014-6278",
18
+ "cwes": [
19
+ "CWE-78"
20
+ ]
21
+ },
22
+ {
23
+ "cveID": "CVE-2017-1000353",
24
+ "vendorProject": "Jenkins",
25
+ "product": "Jenkins",
26
+ "vulnerabilityName": "Jenkins Remote Code Execution Vulnerability",
27
+ "dateAdded": "2025-10-02",
28
+ "shortDescription": "Jenkins contains a remote code execution vulnerability. This vulnerability that could allowed attackers to transfer a serialized Java SignedObject object to the remoting-based Jenkins CLI, that would be deserialized using a new ObjectInputStream, bypassing the existing blocklist-based protection mechanism.",
29
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
30
+ "dueDate": "2025-10-23",
31
+ "knownRansomwareCampaignUse": "Unknown",
32
+ "notes": "https:\/\/www.jenkins.io\/security\/advisory\/2017-04-26\/ ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2017-1000353",
33
+ "cwes": []
34
+ },
35
+ {
36
+ "cveID": "CVE-2015-7755",
37
+ "vendorProject": "Juniper",
38
+ "product": "ScreenOS",
39
+ "vulnerabilityName": "Juniper ScreenOS Improper Authentication Vulnerability",
40
+ "dateAdded": "2025-10-02",
41
+ "shortDescription": "Juniper ScreenOS contains an improper authentication vulnerability that could allow unauthorized remote administrative access to the device.",
42
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
43
+ "dueDate": "2025-10-23",
44
+ "knownRansomwareCampaignUse": "Unknown",
45
+ "notes": "https:\/\/supportportal.juniper.net\/s\/article\/2015-12-Out-of-Cycle-Security-Bulletin-ScreenOS-Multiple-Security-issues-with-ScreenOS-CVE-2015-7755-CVE-2015-7756 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2015-7755",
46
+ "cwes": [
47
+ "CWE-287"
48
+ ]
49
+ },
50
+ {
51
+ "cveID": "CVE-2025-21043",
52
+ "vendorProject": "Samsung",
53
+ "product": "Mobile Devices",
54
+ "vulnerabilityName": "Samsung Mobile Devices Out-of-Bounds Write Vulnerability",
55
+ "dateAdded": "2025-10-02",
56
+ "shortDescription": "Samsung mobile devices contain an out-of-bounds write vulnerability in libimagecodec.quram.so which allows remote attackers to execute arbitrary code.",
57
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
58
+ "dueDate": "2025-10-23",
59
+ "knownRansomwareCampaignUse": "Unknown",
60
+ "notes": "https:\/\/security.samsungmobile.com\/securityUpdate.smsb?year=2025&month=09 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2025-21043",
61
+ "cwes": [
62
+ "CWE-787"
63
+ ]
64
+ },
65
+ {
66
+ "cveID": "CVE-2025-4008",
67
+ "vendorProject": "Smartbedded",
68
+ "product": "Meteobridge",
69
+ "vulnerabilityName": "Smartbedded Meteobridge Command Injection Vulnerability",
70
+ "dateAdded": "2025-10-02",
71
+ "shortDescription": "Smartbedded Meteobridge contains a command injection vulnerability that could allow remote unauthenticated attackers to gain arbitrary command execution with elevated privileges (root) on affected devices.",
72
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
73
+ "dueDate": "2025-10-23",
74
+ "knownRansomwareCampaignUse": "Unknown",
75
+ "notes": "https:\/\/forum.meteohub.de\/viewtopic.php?t=18687 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2025-4008",
76
+ "cwes": [
77
+ "CWE-306",
78
+ "CWE-77"
79
+ ]
80
+ },
81
+ {
82
+ "cveID": "CVE-2025-32463",
83
+ "vendorProject": "Sudo",
84
+ "product": "Sudo",
85
+ "vulnerabilityName": "Sudo Inclusion of Functionality from Untrusted Control Sphere Vulnerability",
86
+ "dateAdded": "2025-09-29",
87
+ "shortDescription": "Sudo contains an inclusion of functionality from untrusted control sphere vulnerability. This vulnerability could allow local attacker to leverage sudo\u2019s -R (--chroot) option to run arbitrary commands as root, even if they are not listed in the sudoers file.",
88
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
89
+ "dueDate": "2025-10-20",
90
+ "knownRansomwareCampaignUse": "Unknown",
91
+ "notes": "This vulnerability could affect an open-source component, third-party library, protocol, or proprietary implementation that could be used by different products. For more information, please see: https:\/\/www.sudo.ws\/security\/advisories\/chroot_bug\/ ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2025-32463",
92
+ "cwes": [
93
+ "CWE-829"
94
+ ]
95
+ },
96
+ {
97
+ "cveID": "CVE-2025-59689",
98
+ "vendorProject": "Libraesva",
99
+ "product": "Email Security Gateway",
100
+ "vulnerabilityName": "Libraesva Email Security Gateway Command Injection Vulnerability",
101
+ "dateAdded": "2025-09-29",
102
+ "shortDescription": "Libraesva Email Security Gateway (ESG) contains a command injection vulnerability which allows command injection via a compressed e-mail attachment.",
103
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
104
+ "dueDate": "2025-10-20",
105
+ "knownRansomwareCampaignUse": "Unknown",
106
+ "notes": "https:\/\/docs.libraesva.com\/knowledgebase\/security-advisory-command-injection-vulnerability-cve-2025-59689\/ ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2025-59689",
107
+ "cwes": [
108
+ "CWE-77"
109
+ ]
110
+ },
111
+ {
112
+ "cveID": "CVE-2025-10035",
113
+ "vendorProject": "Fortra",
114
+ "product": "GoAnywhere MFT",
115
+ "vulnerabilityName": "Fortra GoAnywhere MFT Deserialization of Untrusted Data Vulnerability",
116
+ "dateAdded": "2025-09-29",
117
+ "shortDescription": "Fortra GoAnywhere MFT contains a deserialization of untrusted data vulnerability allows an actor with a validly forged license response signature to deserialize an arbitrary actor-controlled object, possibly leading to command injection.",
118
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
119
+ "dueDate": "2025-10-20",
120
+ "knownRansomwareCampaignUse": "Unknown",
121
+ "notes": "https:\/\/www.fortra.com\/security\/advisories\/product-security\/fi-2025-012 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2025-10035",
122
+ "cwes": [
123
+ "CWE-502",
124
+ "CWE-77"
125
+ ]
126
+ },
127
+ {
128
+ "cveID": "CVE-2025-20352",
129
+ "vendorProject": "Cisco",
130
+ "product": "IOS and IOS XE",
131
+ "vulnerabilityName": "Cisco IOS and IOS XE Software SNMP Denial of Service and Remote Code Execution Vulnerability",
132
+ "dateAdded": "2025-09-29",
133
+ "shortDescription": "Cisco IOS and IOS XE contains a stack-based buffer overflow vulnerability in the Simple Network Management Protocol (SNMP) subsystem that could allow for denial of service or remote code execution. A successful exploit could allow a low-privileged attacker to cause the affected system to reload, resulting in a DoS condition, or allow a high-privileged attacker to execute arbitrary code as the root user and obtain full control of the affected system.",
134
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
135
+ "dueDate": "2025-10-20",
136
+ "knownRansomwareCampaignUse": "Unknown",
137
+ "notes": "https:\/\/sec.cloudapps.cisco.com\/security\/center\/content\/CiscoSecurityAdvisory\/cisco-sa-snmp-x4LPhte ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2025-20352",
138
+ "cwes": [
139
+ "CWE-121"
140
+ ]
141
+ },
142
+ {
143
+ "cveID": "CVE-2021-21311",
144
+ "vendorProject": "Adminer",
145
+ "product": "Adminer",
146
+ "vulnerabilityName": "Adminer Server-Side Request Forgery Vulnerability",
147
+ "dateAdded": "2025-09-29",
148
+ "shortDescription": "Adminer contains a server-side request forgery vulnerability that, when exploited, allows a remote attacker to obtain potentially sensitive information.",
149
+ "requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
150
+ "dueDate": "2025-10-20",
151
+ "knownRansomwareCampaignUse": "Unknown",
152
+ "notes": "https:\/\/github.com\/vrana\/adminer\/security\/advisories\/GHSA-x5r2-hj5c-8jx6 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2021-21311",
153
+ "cwes": [
154
+ "CWE-918"
155
+ ]
156
+ },
7
157
  {
8
158
  "cveID": "CVE-2025-20362",
9
159
  "vendorProject": "Cisco",
@@ -2489,7 +2639,7 @@
2489
2639
  "requiredAction": "Apply mitigations per vendor instructions or discontinue use of the product if mitigations are unavailable.",
2490
2640
  "dueDate": "2025-02-13",
2491
2641
  "knownRansomwareCampaignUse": "Unknown",
2492
- "notes": "https:\/\/blog.jquery.com\/2020\/04\/10\/jquery-3-5-0-released\/ ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2020-11023",
2642
+ "notes": "This vulnerability could affect an open-source component, third-party library, protocol, or proprietary implementation that could be used by different products. For more information, please see: https:\/\/github.com\/jquery\/jquery\/security\/advisories\/GHSA-jpcq-cgw6-v4j6 ; https:\/\/blog.jquery.com\/2020\/04\/10\/jquery-3-5-0-released\/ ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2020-11023",
2493
2643
  "cwes": [
2494
2644
  "CWE-79"
2495
2645
  ]
@@ -25,11 +25,11 @@ CVE = "CVEs"
25
25
 
26
26
  class Nexpose(FlatFileImporter): # pylint: disable=too-many-instance-attributes
27
27
  """
28
- Nexpose Scan information
28
+ Nexpose Scan information with FedRAMP POAM export support
29
29
  """
30
30
 
31
31
  def __init__(self, **kwargs): # pylint: disable=R0902
32
- self.name = kwargs.get("name")
32
+ self.name: str = kwargs.get("name", "Nexpose")
33
33
  self.vuln_title = VULNERABILITY_TITLE
34
34
  self.vuln_id = VULNERABILITY_ID
35
35
  self.cvss3_score = CVSS3_SCORE
@@ -46,13 +46,18 @@ class Nexpose(FlatFileImporter): # pylint: disable=too-many-instance-attributes
46
46
  "Solution",
47
47
  "CVEs",
48
48
  ]
49
- self.mapping_file = kwargs.get("mappings_path")
50
- self.disable_mapping = kwargs.get("disable_mapping")
49
+ self.mapping_file: Optional[str] = kwargs.get("mappings_path")
50
+ self.disable_mapping: Optional[bool] = kwargs.get("disable_mapping")
51
+ file_path: Optional[str] = kwargs.get("file_path")
51
52
  self.validater = ImportValidater(
52
- self.required_headers, kwargs.get("file_path"), self.mapping_file, self.disable_mapping
53
+ self.required_headers, file_path or "", self.mapping_file or "", self.disable_mapping or False
53
54
  )
54
55
  self.headers = self.validater.parsed_headers
55
56
  self.mapping = self.validater.mapping
57
+
58
+ # Store file path for property generation
59
+ self.file_path = kwargs.get("file_path")
60
+
56
61
  logger = create_logger()
57
62
  super().__init__(
58
63
  logger=logger,
@@ -127,6 +132,8 @@ class Nexpose(FlatFileImporter): # pylint: disable=too-many-instance-attributes
127
132
  :return: IssueSeverity or None
128
133
  :rtype: Optional[IssueSeverity]
129
134
  """
135
+ if not text_severity:
136
+ return None
130
137
  if text_severity.lower() == "low":
131
138
  return IssueSeverity.Low
132
139
  if text_severity.lower() in ["medium", "moderate"]:
@@ -170,9 +177,30 @@ class Nexpose(FlatFileImporter): # pylint: disable=too-many-instance-attributes
170
177
 
171
178
  return severity
172
179
 
173
- def create_vuln(self, dat: Optional[dict] = None, **kwargs) -> Optional[IntegrationFinding]:
180
+ def get_source_file_path(self) -> Optional[str]:
174
181
  """
175
- Create an IntegrationFinding from a row in the Prisma/Nexpose csv file
182
+ Get source file path for POAM ID generation
183
+
184
+ Returns file_path if set, None otherwise.
185
+ This supports FedRAMP POAM export logic that generates POAM IDs
186
+ based on source file path properties (e.g., pdf, signatures, campaign, etc.)
187
+
188
+ Note: Properties must be created separately after Issue creation using
189
+ Property.create() or bulk operations, as IntegrationFinding doesn't
190
+ directly support properties.
191
+
192
+ :return: Source file path string or None
193
+ :rtype: Optional[str]
194
+ """
195
+ if not self.file_path:
196
+ return None
197
+ return str(self.file_path)
198
+
199
+ def create_vuln(
200
+ self, dat: Optional[dict] = None, **kwargs
201
+ ) -> Optional[IntegrationFinding]: # pylint: disable=unused-argument
202
+ """
203
+ Create an IntegrationFinding from a row in the Nexpose csv file
176
204
 
177
205
  :param Optional[dict] dat: Data row from CSV file, defaults to None
178
206
  :param kwargs: Additional keyword arguments
@@ -189,8 +217,6 @@ class Nexpose(FlatFileImporter): # pylint: disable=too-many-instance-attributes
189
217
  # Determine severity using priority logic
190
218
  severity = self._determine_severity(dat)
191
219
 
192
- # Find matching asset
193
-
194
220
  # Extract date information
195
221
  first_seen = (
196
222
  self.mapping.get_value(dat, self.first_seen)
@@ -216,7 +242,7 @@ class Nexpose(FlatFileImporter): # pylint: disable=too-many-instance-attributes
216
242
  cvss_score=cvss_score or 0.0,
217
243
  cvss_v3_score=cvss3_score or 0.0,
218
244
  cvss_v2_score=cvss_score or 0.0,
219
- plugin_text=description[:255],
245
+ plugin_text=description[:255] if description else "",
220
246
  remediation=self.mapping.get_value(dat, "Solution"),
221
247
  category="Hardware",
222
248
  status=IssueStatus.Open,