socketsecurity 2.2.40__tar.gz → 2.2.51__tar.gz

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.
Files changed (88) hide show
  1. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/PKG-INFO +3 -3
  2. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/README.md +1 -1
  3. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/pyproject.toml +8 -2
  4. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/__init__.py +1 -1
  5. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/config.py +13 -0
  6. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/__init__.py +49 -27
  7. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/messages.py +3 -3
  8. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/socket_config.py +0 -8
  9. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/tools/reachability.py +8 -3
  10. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/socketcli.py +36 -11
  11. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/core/conftest.py +1 -11
  12. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/core/test_package_and_alerts.py +2 -31
  13. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/unit/test_config.py +1 -12
  14. socketsecurity-2.2.51/uv.lock +1541 -0
  15. socketsecurity-2.2.40/uv.lock +0 -1428
  16. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/CODEOWNERS +0 -0
  17. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
  18. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
  19. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
  20. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  21. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/workflows/docker-stable.yml +0 -0
  22. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/workflows/pr-preview.yml +0 -0
  23. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/workflows/release.yml +0 -0
  24. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.github/workflows/version-check.yml +0 -0
  25. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.gitignore +0 -0
  26. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.hooks/sync_version.py +0 -0
  27. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.pre-commit-config.yaml +0 -0
  28. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/.python-version +0 -0
  29. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/Dockerfile +0 -0
  30. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/LICENSE +0 -0
  31. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/Makefile +0 -0
  32. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/docs/README.md +0 -0
  33. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/pytest.ini +0 -0
  34. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/scripts/build_container.sh +0 -0
  35. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/scripts/build_container_flexible.sh +0 -0
  36. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/scripts/deploy-test-docker.sh +0 -0
  37. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/scripts/deploy-test-pypi.sh +0 -0
  38. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/scripts/docker-entrypoint.sh +0 -0
  39. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/scripts/run.sh +0 -0
  40. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/classes.py +0 -0
  41. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/cli_client.py +0 -0
  42. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/exceptions.py +0 -0
  43. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/git_interface.py +0 -0
  44. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/helper/__init__.py +0 -0
  45. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/lazy_file_loader.py +0 -0
  46. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/logging.py +0 -0
  47. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/resource_utils.py +0 -0
  48. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/scm/__init__.py +0 -0
  49. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/scm/base.py +0 -0
  50. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/scm/client.py +0 -0
  51. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/scm/github.py +0 -0
  52. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/scm/gitlab.py +0 -0
  53. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/scm_comments.py +0 -0
  54. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/core/utils.py +0 -0
  55. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/output.py +0 -0
  56. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/plugins/__init__.py +0 -0
  57. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/plugins/base.py +0 -0
  58. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/plugins/jira.py +0 -0
  59. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/plugins/manager.py +0 -0
  60. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/plugins/slack.py +0 -0
  61. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/plugins/teams.py +0 -0
  62. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/socketsecurity/plugins/webhook.py +0 -0
  63. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/__init__.py +0 -0
  64. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/core/create_diff_input.json +0 -0
  65. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/core/test_diff_generation.py +0 -0
  66. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/core/test_sdk_methods.py +0 -0
  67. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/core/test_supporting_methods.py +0 -0
  68. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/fullscans/create_response.json +0 -0
  69. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/fullscans/diff/stream_diff.json +0 -0
  70. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
  71. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/fullscans/head_scan/metadata.json +0 -0
  72. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
  73. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
  74. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/fullscans/new_scan/metadata.json +0 -0
  75. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
  76. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/repos/repo_info_error.json +0 -0
  77. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/repos/repo_info_no_head.json +0 -0
  78. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/repos/repo_info_success.json +0 -0
  79. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/data/settings/security-policy.json +0 -0
  80. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/unit/__init__.py +0 -0
  81. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/unit/test_cli_config.py +0 -0
  82. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/unit/test_client.py +0 -0
  83. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/unit/test_gitlab_auth.py +0 -0
  84. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/unit/test_gitlab_auth_fallback.py +0 -0
  85. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/tests/unit/test_output.py +0 -0
  86. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/workflows/bitbucket-pipelines.yml +0 -0
  87. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/workflows/github-actions.yml +0 -0
  88. {socketsecurity-2.2.40 → socketsecurity-2.2.51}/workflows/gitlab-ci.yml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: socketsecurity
3
- Version: 2.2.40
3
+ Version: 2.2.51
4
4
  Summary: Socket Security CLI for CI/CD
5
5
  Project-URL: Homepage, https://socket.dev
6
6
  Author-email: Douglas Coburn <douglas@socket.dev>
@@ -40,7 +40,7 @@ Requires-Dist: packaging
40
40
  Requires-Dist: prettytable
41
41
  Requires-Dist: python-dotenv
42
42
  Requires-Dist: requests
43
- Requires-Dist: socketdev<4.0.0,>=3.0.21
43
+ Requires-Dist: socketdev<4.0.0,>=3.0.22
44
44
  Provides-Extra: dev
45
45
  Requires-Dist: hatch; extra == 'dev'
46
46
  Requires-Dist: pre-commit; extra == 'dev'
@@ -57,7 +57,7 @@ Description-Content-Type: text/markdown
57
57
 
58
58
  # Socket Security CLI
59
59
 
60
- The Socket Security CLI was created to enable integrations with other tools like GitHub Actions, GitLab, BitBucket, local use cases and more. The tool will get the head scan for the provided repo from Socket, create a new one, and then report any new alerts detected. If there are new alerts against the Socket security policy it'll exit with a non-Zero exit code.
60
+ The Socket Security CLI was created to enable integrations with other tools like GitHub Actions, GitLab, BitBucket, local use cases and more. The tool will get the head scan for the provided repo from Socket, create a new one, and then report any new alerts detected. If there are new alerts with blocking actions it'll exit with a non-Zero exit code.
61
61
 
62
62
  ## Quick Start
63
63
 
@@ -1,6 +1,6 @@
1
1
  # Socket Security CLI
2
2
 
3
- The Socket Security CLI was created to enable integrations with other tools like GitHub Actions, GitLab, BitBucket, local use cases and more. The tool will get the head scan for the provided repo from Socket, create a new one, and then report any new alerts detected. If there are new alerts against the Socket security policy it'll exit with a non-Zero exit code.
3
+ The Socket Security CLI was created to enable integrations with other tools like GitHub Actions, GitLab, BitBucket, local use cases and more. The tool will get the head scan for the provided repo from Socket, create a new one, and then report any new alerts detected. If there are new alerts with blocking actions it'll exit with a non-Zero exit code.
4
4
 
5
5
  ## Quick Start
6
6
 
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "socketsecurity"
9
- version = "2.2.40"
9
+ version = "2.2.51"
10
10
  requires-python = ">= 3.10"
11
11
  license = {"file" = "LICENSE"}
12
12
  dependencies = [
@@ -16,7 +16,7 @@ dependencies = [
16
16
  'GitPython',
17
17
  'packaging',
18
18
  'python-dotenv',
19
- 'socketdev>=3.0.21,<4.0.0',
19
+ 'socketdev>=3.0.22,<4.0.0',
20
20
  "bs4>=0.0.2",
21
21
  ]
22
22
  readme = "README.md"
@@ -160,3 +160,9 @@ docstring-code-line-length = "dynamic"
160
160
 
161
161
  [tool.hatch.build.targets.wheel]
162
162
  include = ["socketsecurity", "LICENSE"]
163
+
164
+ [dependency-groups]
165
+ dev = [
166
+ "pre-commit>=4.3.0",
167
+ ]
168
+
@@ -1,3 +1,3 @@
1
1
  __author__ = 'socket.dev'
2
- __version__ = '2.2.40'
2
+ __version__ = '2.2.51'
3
3
  USER_AGENT = f'SocketPythonCLI/{__version__}'
@@ -77,6 +77,7 @@ class CliConfig:
77
77
  reach_concurrency: Optional[int] = None
78
78
  reach_additional_params: Optional[List[str]] = None
79
79
  only_facts_file: bool = False
80
+ reach_use_only_pregenerated_sboms: bool = False
80
81
 
81
82
  @classmethod
82
83
  def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
@@ -139,6 +140,7 @@ class CliConfig:
139
140
  'reach_concurrency': args.reach_concurrency,
140
141
  'reach_additional_params': args.reach_additional_params,
141
142
  'only_facts_file': args.only_facts_file,
143
+ 'reach_use_only_pregenerated_sboms': args.reach_use_only_pregenerated_sboms,
142
144
  'version': __version__
143
145
  }
144
146
  try:
@@ -175,6 +177,11 @@ class CliConfig:
175
177
  logging.error("--only-facts-file requires --reach to be specified")
176
178
  exit(1)
177
179
 
180
+ # Validate that reach_use_only_pregenerated_sboms requires reach
181
+ if args.reach_use_only_pregenerated_sboms and not args.reach:
182
+ logging.error("--reach-use-only-pregenerated-sboms requires --reach to be specified")
183
+ exit(1)
184
+
178
185
  # Validate reach_concurrency is >= 1 if provided
179
186
  if args.reach_concurrency is not None and args.reach_concurrency < 1:
180
187
  logging.error("--reach-concurrency must be >= 1")
@@ -602,6 +609,12 @@ def create_argument_parser() -> argparse.ArgumentParser:
602
609
  action="store_true",
603
610
  help="Submit only the .socket.facts.json file when creating full scan (requires --reach)"
604
611
  )
612
+ reachability_group.add_argument(
613
+ "--reach-use-only-pregenerated-sboms",
614
+ dest="reach_use_only_pregenerated_sboms",
615
+ action="store_true",
616
+ help="When using this option, the scan is created based only on pre-generated CDX and SPDX files in your project. (requires --reach)"
617
+ )
605
618
 
606
619
  parser.add_argument(
607
620
  '--version',
@@ -19,7 +19,6 @@ from socketdev.exceptions import APIFailure
19
19
  from socketdev.fullscans import FullScanParams, SocketArtifact
20
20
  from socketdev.org import Organization
21
21
  from socketdev.repos import RepositoryInfo
22
- from socketdev.settings import SecurityPolicyRule
23
22
  import copy
24
23
  from socketsecurity import __version__, USER_AGENT
25
24
  from socketsecurity.core.classes import (
@@ -82,8 +81,6 @@ class Core:
82
81
  self.config.full_scan_path = f"{base_path}/full-scans"
83
82
  self.config.repository_path = f"{base_path}/repos"
84
83
 
85
- self.config.security_policy = self.get_security_policy()
86
-
87
84
  def get_org_id_slug(self) -> Tuple[str, str]:
88
85
  """Gets the Org ID and Org Slug for the API Token."""
89
86
  response = self.sdk.org.get(use_types=True)
@@ -112,16 +109,7 @@ class Core:
112
109
  """Converts artifacts dictionary to a list."""
113
110
  return list(artifacts_dict.values())
114
111
 
115
- def get_security_policy(self) -> Dict[str, SecurityPolicyRule]:
116
- """Gets the organization's security policy."""
117
- response = self.sdk.settings.get(self.config.org_slug, use_types=True)
118
-
119
- if not response.success:
120
- log.error(f"Failed to get security policy: {response.status}")
121
- log.error(response.message)
122
- raise Exception(f"Failed to get security policy: {response.status}, message: {response.message}")
123
112
 
124
- return response.securityPolicyRules
125
113
 
126
114
  def create_sbom_output(self, diff: Diff) -> dict:
127
115
  """Creates CycloneDX output for a given diff."""
@@ -293,12 +281,13 @@ class Core:
293
281
  except Exception as e:
294
282
  log.error(f"Failed to save manifest tar.gz to {output_path}: {e}")
295
283
 
296
- def find_files(self, path: str) -> List[str]:
284
+ def find_files(self, path: str, ecosystems: Optional[List[str]] = None) -> List[str]:
297
285
  """
298
286
  Finds supported manifest files in the given path.
299
287
 
300
288
  Args:
301
289
  path: Path to search for manifest files.
290
+ ecosystems: Optional list of ecosystems to include. If None, all ecosystems are included.
302
291
 
303
292
  Returns:
304
293
  List of found manifest file paths.
@@ -311,6 +300,9 @@ class Core:
311
300
  patterns = self.get_supported_patterns()
312
301
 
313
302
  for ecosystem in patterns:
303
+ # If ecosystems filter is provided, only include specified ecosystems
304
+ if ecosystems is not None and ecosystem not in ecosystems:
305
+ continue
314
306
  if ecosystem in self.config.excluded_ecosystems:
315
307
  continue
316
308
  log.debug(f'Scanning ecosystem: {ecosystem}')
@@ -355,6 +347,23 @@ class Core:
355
347
 
356
348
  return file_list
357
349
 
350
+ def find_sbom_files(self, path: str) -> List[str]:
351
+ """
352
+ Finds only pre-generated SBOM files (CDX and SPDX) in the given path.
353
+
354
+ This is used with --reach-use-only-pregenerated-sboms to find only
355
+ pre-computed CycloneDX and SPDX manifest files.
356
+
357
+ Args:
358
+ path: Path to search for SBOM files.
359
+
360
+ Returns:
361
+ List of found CDX and SPDX file paths.
362
+ """
363
+ log.debug("Starting Find SBOM Files (CDX and SPDX only)")
364
+ sbom_ecosystems = ['cdx', 'spdx']
365
+ return self.find_files(path, ecosystems=sbom_ecosystems)
366
+
358
367
  def get_supported_patterns(self) -> Dict:
359
368
  """
360
369
  Gets supported file patterns from the Socket API.
@@ -559,7 +568,8 @@ class Core:
559
568
  no_change: bool = False,
560
569
  save_files_list_path: Optional[str] = None,
561
570
  save_manifest_tar_path: Optional[str] = None,
562
- base_paths: Optional[List[str]] = None
571
+ base_paths: Optional[List[str]] = None,
572
+ explicit_files: Optional[List[str]] = None
563
573
  ) -> Diff:
564
574
  """Create a new full scan and return with html_report_url.
565
575
 
@@ -570,6 +580,7 @@ class Core:
570
580
  save_files_list_path: Optional path to save submitted files list for debugging
571
581
  save_manifest_tar_path: Optional path to save manifest files tar.gz archive
572
582
  base_paths: List of base paths for the scan (optional)
583
+ explicit_files: Optional list of explicit files to use instead of discovering files
573
584
 
574
585
  Returns:
575
586
  Dict with full scan data including html_report_url
@@ -583,11 +594,15 @@ class Core:
583
594
  if no_change:
584
595
  return diff
585
596
 
586
- # Find manifest files from all paths
587
- all_files = []
588
- for path in paths:
589
- files = self.find_files(path)
590
- all_files.extend(files)
597
+ # Use explicit files if provided, otherwise find manifest files from all paths
598
+ if explicit_files is not None:
599
+ all_files = explicit_files
600
+ log.debug(f"Using {len(all_files)} explicit files instead of discovering files")
601
+ else:
602
+ all_files = []
603
+ for path in paths:
604
+ files = self.find_files(path)
605
+ all_files.extend(files)
591
606
 
592
607
  # Save submitted files list if requested
593
608
  if save_files_list_path and all_files:
@@ -955,7 +970,8 @@ class Core:
955
970
  no_change: bool = False,
956
971
  save_files_list_path: Optional[str] = None,
957
972
  save_manifest_tar_path: Optional[str] = None,
958
- base_paths: Optional[List[str]] = None
973
+ base_paths: Optional[List[str]] = None,
974
+ explicit_files: Optional[List[str]] = None
959
975
  ) -> Diff:
960
976
  """Create a new diff using the Socket SDK.
961
977
 
@@ -966,16 +982,21 @@ class Core:
966
982
  save_files_list_path: Optional path to save submitted files list for debugging
967
983
  save_manifest_tar_path: Optional path to save manifest files tar.gz archive
968
984
  base_paths: List of base paths for the scan (optional)
985
+ explicit_files: Optional list of explicit files to use instead of discovering files
969
986
  """
970
987
  log.debug(f"starting create_new_diff with no_change: {no_change}")
971
988
  if no_change:
972
989
  return Diff(id="NO_DIFF_RAN", diff_url="", report_url="")
973
990
 
974
- # Find manifest files from all paths
975
- all_files = []
976
- for path in paths:
977
- files = self.find_files(path)
978
- all_files.extend(files)
991
+ # Use explicit files if provided, otherwise find manifest files from all paths
992
+ if explicit_files is not None:
993
+ all_files = explicit_files
994
+ log.debug(f"Using {len(all_files)} explicit files instead of discovering files")
995
+ else:
996
+ all_files = []
997
+ for path in paths:
998
+ files = self.find_files(path)
999
+ all_files.extend(files)
979
1000
 
980
1001
  # Save submitted files list if requested
981
1002
  if save_files_list_path and all_files:
@@ -1317,8 +1338,9 @@ class Core:
1317
1338
  url=package.url
1318
1339
  )
1319
1340
 
1320
- if alert.type in self.config.security_policy:
1321
- action = self.config.security_policy[alert.type]['action']
1341
+ # Use action from API (from security policy, label policy, triage, etc.)
1342
+ if 'action' in alert_item and alert_item['action']:
1343
+ action = alert_item['action']
1322
1344
  setattr(issue_alert, action, True)
1323
1345
 
1324
1346
  if issue_alert.key not in alerts_collection:
@@ -416,7 +416,7 @@ class Messages:
416
416
  > **❗️ Caution**
417
417
  > **Review the following alerts detected in dependencies.**
418
418
  >
419
- > According to your organization's Security Policy, you **must** resolve all **"Block"** alerts before proceeding. It's recommended to resolve **"Warn"** alerts too.
419
+ > According to your organization's policies, you **must** resolve all **"Block"** alerts before proceeding. It's recommended to resolve **"Warn"** alerts too.
420
420
  > Learn more about [Socket for GitHub](https://socket.dev?utm_medium=gh).
421
421
 
422
422
  <!-- start-socket-updated-alerts-table -->
@@ -622,7 +622,7 @@ class Messages:
622
622
  @staticmethod
623
623
  def create_security_alert_table(diff: Diff, md: MdUtils) -> tuple[MdUtils, list, dict]:
624
624
  """
625
- Creates the detected issues table based on the Security Policy
625
+ Creates the detected issues table based on alert actions from the API
626
626
  :param diff: Diff - Diff report with the detected issues
627
627
  :param md: MdUtils - Main markdown variable
628
628
  :return:
@@ -794,7 +794,7 @@ class Messages:
794
794
  @staticmethod
795
795
  def create_console_security_alert_table(diff: Diff) -> PrettyTable:
796
796
  """
797
- Creates the detected issues table based on the Security Policy
797
+ Creates the detected issues table based on alert actions from the API
798
798
  :param diff: Diff - Diff report with the detected issues
799
799
  :return:
800
800
  """
@@ -25,7 +25,6 @@ class SocketConfig:
25
25
  org_slug: Optional[str] = None
26
26
  full_scan_path: Optional[str] = None
27
27
  repository_path: Optional[str] = None
28
- security_policy: Dict = None
29
28
  repo_visibility: Optional[str] = 'private'
30
29
  all_issues: Optional['AllIssues'] = None
31
30
  excluded_dirs: Set[str] = field(default_factory=lambda: default_exclude_dirs)
@@ -42,10 +41,6 @@ class SocketConfig:
42
41
 
43
42
  self._validate_api_url(self.api_url)
44
43
 
45
- # Initialize empty dict for security policy if None
46
- if self.security_policy is None:
47
- self.security_policy = {}
48
-
49
44
  # Initialize AllIssues if None
50
45
  if self.all_issues is None:
51
46
  self.all_issues = AllIssues()
@@ -70,6 +65,3 @@ class SocketConfig:
70
65
  self.full_scan_path = f"{base_path}/full-scans"
71
66
  self.repository_path = f"{base_path}/repos"
72
67
 
73
- def update_security_policy(self, policy: Dict) -> None:
74
- """Update security policy"""
75
- self.security_policy = policy
@@ -101,10 +101,11 @@ class ReachabilityAnalyzer:
101
101
  additional_params: Optional[List[str]] = None,
102
102
  allow_unverified: bool = False,
103
103
  enable_debug: bool = False,
104
+ use_only_pregenerated_sboms: bool = False,
104
105
  ) -> Dict[str, Any]:
105
106
  """
106
107
  Run reachability analysis.
107
-
108
+
108
109
  Args:
109
110
  org_slug: Socket organization slug
110
111
  target_directory: Directory to analyze
@@ -125,7 +126,8 @@ class ReachabilityAnalyzer:
125
126
  additional_params: Additional parameters to pass to coana CLI
126
127
  allow_unverified: Disable SSL certificate verification (sets NODE_TLS_REJECT_UNAUTHORIZED=0)
127
128
  enable_debug: Enable debug mode (passes -d flag to coana CLI)
128
-
129
+ use_only_pregenerated_sboms: Use only pre-generated CDX and SPDX files for the scan
130
+
129
131
  Returns:
130
132
  Dict containing scan_id and report_path
131
133
  """
@@ -179,7 +181,10 @@ class ReachabilityAnalyzer:
179
181
 
180
182
  if enable_debug:
181
183
  cmd.append("-d")
182
-
184
+
185
+ if use_only_pregenerated_sboms:
186
+ cmd.append("--use-only-pregenerated-sboms")
187
+
183
188
  # Add any additional parameters provided by the user
184
189
  if additional_params:
185
190
  cmd.extend(additional_params)
@@ -167,6 +167,8 @@ def main_code():
167
167
 
168
168
  # Variable to track if we need to override files with facts file
169
169
  facts_file_to_submit = None
170
+ # Variable to track SBOM files to submit when using --reach-use-only-pregenerated-sboms
171
+ sbom_files_to_submit = None
170
172
 
171
173
  # Git setup
172
174
  is_repo = False
@@ -230,12 +232,14 @@ def main_code():
230
232
  # Run reachability analysis if enabled
231
233
  if config.reach:
232
234
  from socketsecurity.core.tools.reachability import ReachabilityAnalyzer
233
-
235
+
234
236
  log.info("Starting reachability analysis...")
235
-
237
+
236
238
  # Find manifest files in scan paths (excluding .socket.facts.json to avoid circular dependency)
237
239
  log.info("Finding manifest files for reachability analysis...")
238
240
  manifest_files = []
241
+
242
+ # Always find all manifest files for the tar hash upload
239
243
  for scan_path in scan_paths:
240
244
  scan_manifests = core.find_files(scan_path)
241
245
  # Filter out .socket.facts.json files from manifest upload
@@ -289,7 +293,8 @@ def main_code():
289
293
  concurrency=config.reach_concurrency,
290
294
  additional_params=config.reach_additional_params,
291
295
  allow_unverified=config.allow_unverified,
292
- enable_debug=config.enable_debug
296
+ enable_debug=config.enable_debug,
297
+ use_only_pregenerated_sboms=config.reach_use_only_pregenerated_sboms
293
298
  )
294
299
 
295
300
  log.info(f"Reachability analysis completed successfully")
@@ -301,6 +306,17 @@ def main_code():
301
306
  if config.only_facts_file:
302
307
  facts_file_to_submit = os.path.abspath(output_path)
303
308
  log.info(f"Only-facts-file mode: will submit only {facts_file_to_submit}")
309
+
310
+ # If reach-use-only-pregenerated-sboms mode, submit CDX, SPDX, and facts file
311
+ if config.reach_use_only_pregenerated_sboms:
312
+ # Find only CDX and SPDX files for the final scan submission
313
+ sbom_files_to_submit = []
314
+ for scan_path in scan_paths:
315
+ sbom_files_to_submit.extend(core.find_sbom_files(scan_path))
316
+ # Use relative path for facts file
317
+ if os.path.exists(output_path):
318
+ sbom_files_to_submit.append(output_path)
319
+ log.info(f"Pre-generated SBOMs mode: will submit {len(sbom_files_to_submit)} files (CDX, SPDX, and facts file)")
304
320
 
305
321
  except Exception as e:
306
322
  log.error(f"Reachability analysis failed: {str(e)}")
@@ -331,6 +347,12 @@ def main_code():
331
347
  files_explicitly_specified = True
332
348
  log.debug(f"Overriding files to only submit facts file: {facts_file_to_submit}")
333
349
 
350
+ # Override files if reach-use-only-pregenerated-sboms mode is active
351
+ if sbom_files_to_submit:
352
+ specified_files = sbom_files_to_submit
353
+ files_explicitly_specified = True
354
+ log.debug(f"Overriding files to submit only SBOM files (CDX, SPDX, and facts): {sbom_files_to_submit}")
355
+
334
356
  # Determine files to check based on the new logic
335
357
  files_to_check = []
336
358
  force_api_mode = False
@@ -452,7 +474,7 @@ def main_code():
452
474
  log.info("Push initiated flow")
453
475
  if scm.check_event_type() == "diff":
454
476
  log.info("Starting comment logic for PR/MR event")
455
- diff = core.create_new_diff(scan_paths, params, no_change=should_skip_scan, save_files_list_path=config.save_submitted_files_list, save_manifest_tar_path=config.save_manifest_tar, base_paths=base_paths)
477
+ diff = core.create_new_diff(scan_paths, params, no_change=should_skip_scan, save_files_list_path=config.save_submitted_files_list, save_manifest_tar_path=config.save_manifest_tar, base_paths=base_paths, explicit_files=sbom_files_to_submit)
456
478
  comments = scm.get_comments_for_pr()
457
479
  log.debug("Removing comment alerts")
458
480
 
@@ -505,14 +527,14 @@ def main_code():
505
527
  )
506
528
  else:
507
529
  log.info("Starting non-PR/MR flow")
508
- diff = core.create_new_diff(scan_paths, params, no_change=should_skip_scan, save_files_list_path=config.save_submitted_files_list, save_manifest_tar_path=config.save_manifest_tar, base_paths=base_paths)
530
+ diff = core.create_new_diff(scan_paths, params, no_change=should_skip_scan, save_files_list_path=config.save_submitted_files_list, save_manifest_tar_path=config.save_manifest_tar, base_paths=base_paths, explicit_files=sbom_files_to_submit)
509
531
 
510
532
  output_handler.handle_output(diff)
511
-
533
+
512
534
  elif config.enable_diff and not force_api_mode:
513
535
  # New logic: --enable-diff forces diff mode even with --integration api (no SCM)
514
536
  log.info("Diff mode enabled without SCM integration")
515
- diff = core.create_new_diff(scan_paths, params, no_change=should_skip_scan, save_files_list_path=config.save_submitted_files_list, save_manifest_tar_path=config.save_manifest_tar, base_paths=base_paths)
537
+ diff = core.create_new_diff(scan_paths, params, no_change=should_skip_scan, save_files_list_path=config.save_submitted_files_list, save_manifest_tar_path=config.save_manifest_tar, base_paths=base_paths, explicit_files=sbom_files_to_submit)
516
538
  output_handler.handle_output(diff)
517
539
 
518
540
  elif config.enable_diff and force_api_mode:
@@ -530,12 +552,13 @@ def main_code():
530
552
  no_change=should_skip_scan,
531
553
  save_files_list_path=config.save_submitted_files_list,
532
554
  save_manifest_tar_path=config.save_manifest_tar,
533
- base_paths=base_paths
555
+ base_paths=base_paths,
556
+ explicit_files=sbom_files_to_submit
534
557
  )
535
558
  log.info(f"Full scan created with ID: {diff.id}")
536
559
  log.info(f"Full scan report URL: {diff.report_url}")
537
560
  output_handler.handle_output(diff)
538
-
561
+
539
562
  else:
540
563
  if force_api_mode:
541
564
  log.info("No Manifest files changed, creating Socket Report")
@@ -550,7 +573,8 @@ def main_code():
550
573
  no_change=should_skip_scan,
551
574
  save_files_list_path=config.save_submitted_files_list,
552
575
  save_manifest_tar_path=config.save_manifest_tar,
553
- base_paths=base_paths
576
+ base_paths=base_paths,
577
+ explicit_files=sbom_files_to_submit
554
578
  )
555
579
  log.info(f"Full scan created with ID: {diff.id}")
556
580
  log.info(f"Full scan report URL: {diff.report_url}")
@@ -561,7 +585,8 @@ def main_code():
561
585
  no_change=should_skip_scan,
562
586
  save_files_list_path=config.save_submitted_files_list,
563
587
  save_manifest_tar_path=config.save_manifest_tar,
564
- base_paths=base_paths
588
+ base_paths=base_paths,
589
+ explicit_files=sbom_files_to_submit
565
590
  )
566
591
  output_handler.handle_output(diff)
567
592
 
@@ -10,7 +10,6 @@ from socketdev.fullscans import (
10
10
  StreamDiffResponse,
11
11
  )
12
12
  from socketdev.repos import GetRepoResponse
13
- from socketdev.settings import OrgSecurityPolicyResponse
14
13
 
15
14
 
16
15
  @pytest.fixture
@@ -88,14 +87,7 @@ def stream_diff_response(data_dir, load_json):
88
87
  })
89
88
 
90
89
 
91
- @pytest.fixture
92
- def security_policy(data_dir, load_json):
93
- json_data = load_json(data_dir / "settings" / "security-policy.json")
94
- return OrgSecurityPolicyResponse.from_dict({
95
- "success": json_data["success"],
96
- "status": json_data["status"],
97
- "securityPolicyRules": json_data["securityPolicyRules"]
98
- })
90
+
99
91
 
100
92
 
101
93
  @pytest.fixture
@@ -146,13 +138,11 @@ def mock_sdk_with_responses(
146
138
  new_scan_metadata,
147
139
  new_scan_stream,
148
140
  stream_diff_response,
149
- security_policy,
150
141
  create_full_scan_response,
151
142
  ):
152
143
  sdk = mock_socket_sdk.return_value
153
144
 
154
145
  # Simple returns
155
- sdk.settings.get.return_value = security_policy
156
146
  sdk.fullscans.post.return_value = create_full_scan_response
157
147
 
158
148
  # Argument-based returns
@@ -33,11 +33,10 @@ class TestPackageAndAlerts:
33
33
  }
34
34
  })
35
35
 
36
- # Set up settings.get() to return empty security policy
36
+ # Set up settings.get() to return empty response
37
37
  mock.settings = Mock()
38
38
  settings_response = Mock()
39
39
  settings_response.success = True
40
- settings_response.security_policy = {}
41
40
  mock.settings.get = Mock(return_value=settings_response)
42
41
 
43
42
  return mock
@@ -48,7 +47,6 @@ class TestPackageAndAlerts:
48
47
  api_key="test-key",
49
48
  allow_unverified_ssl=False
50
49
  )
51
- config.security_policy = {} # Initialize with empty dict
52
50
  return config
53
51
 
54
52
  @pytest.fixture
@@ -135,34 +133,7 @@ class TestPackageAndAlerts:
135
133
  assert alert.type == "networkAccess"
136
134
  assert alert.severity == "high"
137
135
 
138
- def test_add_package_alerts_with_security_policy(self, core):
139
- """Test alerts are properly tagged based on security policy"""
140
- # Mock security policy in config
141
- core.config.security_policy = {
142
- "networkAccess": {"action": "error"}
143
- }
144
-
145
- package = Package(
146
- id="pkg:npm/test@1.0.0",
147
- name="test",
148
- version="1.0.0",
149
- type="npm",
150
- alerts=[{
151
- "type": "networkAccess",
152
- "key": "test-alert",
153
- "severity": "high"
154
- }],
155
- topLevelAncestors=[]
156
- )
157
-
158
- alerts_collection = {}
159
- packages = {package.id: package}
160
-
161
- result = core.add_package_alerts_to_collection(package, alerts_collection, packages)
162
-
163
- assert len(result) == 1
164
- alert = result["test-alert"][0]
165
- assert alert.error is True
136
+
166
137
 
167
138
  def test_get_capabilities_for_added_packages(self, core):
168
139
  """Test capability extraction from package alerts"""
@@ -7,13 +7,12 @@ def test_config_default_values():
7
7
 
8
8
  assert config.api_key == "test_key"
9
9
  assert config.api_url == "https://api.socket.dev/v0"
10
- assert config.timeout == 30
10
+ assert config.timeout == 1200
11
11
  assert config.allow_unverified_ssl is False
12
12
  assert config.org_id is None
13
13
  assert config.org_slug is None
14
14
  assert config.full_scan_path is None
15
15
  assert config.repository_path is None
16
- assert config.security_policy == {}
17
16
 
18
17
  def test_config_custom_values():
19
18
  """Test that config accepts custom values"""
@@ -67,14 +66,4 @@ def test_config_update_org_details():
67
66
  assert config.full_scan_path == "orgs/test-org/full-scans"
68
67
  assert config.repository_path == "orgs/test-org/repos"
69
68
 
70
- def test_config_update_security_policy():
71
- """Test updating security policy"""
72
- config = SocketConfig(api_key="test_key")
73
-
74
- test_policy = {
75
- "rule1": {"action": "block"},
76
- "rule2": {"action": "warn"}
77
- }
78
69
 
79
- config.security_policy = test_policy
80
- assert config.security_policy == test_policy