socketsecurity 1.0.1__tar.gz → 1.0.3__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 (23) hide show
  1. {socketsecurity-1.0.1/socketsecurity.egg-info → socketsecurity-1.0.3}/PKG-INFO +1 -1
  2. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/__init__.py +1 -1
  3. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/__init__.py +16 -5
  4. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/github.py +36 -0
  5. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/messages.py +21 -9
  6. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/scm_comments.py +24 -17
  7. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/socketcli.py +13 -5
  8. {socketsecurity-1.0.1 → socketsecurity-1.0.3/socketsecurity.egg-info}/PKG-INFO +1 -1
  9. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/LICENSE +0 -0
  10. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/README.md +0 -0
  11. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/pyproject.toml +0 -0
  12. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/setup.cfg +0 -0
  13. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/classes.py +0 -0
  14. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/exceptions.py +0 -0
  15. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/git_interface.py +0 -0
  16. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/gitlab.py +0 -0
  17. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/issues.py +0 -0
  18. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity/core/licenses.py +0 -0
  19. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity.egg-info/SOURCES.txt +0 -0
  20. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity.egg-info/dependency_links.txt +0 -0
  21. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity.egg-info/entry_points.txt +0 -0
  22. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity.egg-info/requires.txt +0 -0
  23. {socketsecurity-1.0.1 → socketsecurity-1.0.3}/socketsecurity.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: socketsecurity
3
- Version: 1.0.1
3
+ Version: 1.0.3
4
4
  Summary: Socket Security CLI for CI/CD
5
5
  Author-email: Douglas Coburn <douglas@socket.dev>
6
6
  Maintainer-email: Douglas Coburn <douglas@socket.dev>
@@ -1,2 +1,2 @@
1
1
  __author__ = 'socket.dev'
2
- __version__ = '1.0.1'
2
+ __version__ = '1.0.3'
@@ -548,11 +548,13 @@ class Core:
548
548
  head_packages = Core.create_sbom_dict(head_scan)
549
549
  new_scan_alerts = {}
550
550
  head_scan_alerts = {}
551
-
551
+ consolidated = []
552
552
  for package_id in new_packages:
553
553
  purl, package = Core.create_purl(package_id, new_packages)
554
- if package_id not in head_packages and package.direct:
554
+ base_purl = f"{purl.ecosystem}/{purl.name}@{purl.version}"
555
+ if package_id not in head_packages and package.direct and base_purl not in consolidated:
555
556
  diff.new_packages.append(purl)
557
+ consolidated.append(base_purl)
556
558
  new_scan_alerts = Core.create_issue_alerts(package, new_scan_alerts, new_packages)
557
559
  for package_id in head_packages:
558
560
  purl, package = Core.create_purl(package_id, head_packages)
@@ -633,18 +635,27 @@ class Core:
633
635
  :param alerts: List of new alerts that are only in the new Full Scan
634
636
  :return:
635
637
  """
638
+ consolidated_alerts = []
636
639
  for alert_key in new_scan_alerts:
637
640
  if alert_key not in head_scan_alerts:
638
641
  new_alerts = new_scan_alerts[alert_key]
639
642
  for alert in new_alerts:
643
+ alert: Issue
644
+ alert_str = f"{alert.purl},{alert.manifests},{alert.type}"
640
645
  if alert.error or alert.warn:
641
- alerts.append(alert)
646
+ if alert_str not in consolidated_alerts:
647
+ alerts.append(alert)
648
+ consolidated_alerts.append(alert_str)
642
649
  else:
643
650
  new_alerts = new_scan_alerts[alert_key]
644
651
  head_alerts = head_scan_alerts[alert_key]
645
652
  for alert in new_alerts:
646
- if alert not in head_alerts and (alert.error or alert.warn):
647
- alerts.append(alert)
653
+ alert: Issue
654
+ alert_str = f"{alert.purl},{alert.manifests},{alert.type}"
655
+ if alert not in head_alerts and alert_str not in consolidated_alerts:
656
+ if alert.error or alert.warn:
657
+ alerts.append(alert)
658
+ consolidated_alerts.append(alert_str)
648
659
  return alerts
649
660
 
650
661
  @staticmethod
@@ -207,4 +207,40 @@ class Github:
207
207
  if security_alert is not None:
208
208
  security_alert: Comment
209
209
  new_body = Comments.process_security_comment(security_alert, comments)
210
+ Github.handle_ignore_reactions(comments)
210
211
  Github.update_comment(new_body, str(security_alert.id))
212
+
213
+ @staticmethod
214
+ def handle_ignore_reactions(comments: dict) -> None:
215
+ for comment in comments["ignore"]:
216
+ comment: Comment
217
+ if "SocketSecurity ignore" in comment.body:
218
+ if not Github.comment_reaction_exists(comment.id):
219
+ Github.post_reaction(comment.id)
220
+
221
+ @staticmethod
222
+ def post_reaction(comment_id: int) -> None:
223
+ repo = github_repository.rsplit("/", 1)[1]
224
+ path = f"repos/{github_repository_owner}/{repo}/issues/comments/{comment_id}/reactions"
225
+ payload = {
226
+ "content": "+1"
227
+ }
228
+ payload = json.dumps(payload)
229
+ do_request(path, payload=payload, method="POST", headers=headers, base_url=github_api_url)
230
+
231
+ @staticmethod
232
+ def comment_reaction_exists(comment_id: int) -> bool:
233
+ repo = github_repository.rsplit("/", 1)[1]
234
+ path = f"repos/{github_repository_owner}/{repo}/issues/comments/{comment_id}/reactions"
235
+ response = do_request(path, headers=headers, base_url=github_api_url)
236
+ exists = False
237
+ try:
238
+ data = response.json()
239
+ for reaction in data:
240
+ content = reaction.get("content")
241
+ if content is not None and content == ":thumbsup:":
242
+ exists = True
243
+ except Exception as error:
244
+ log.error(f"Unable to get reaction for {comment_id} for PR {pr_number}")
245
+ log.error(error)
246
+ return exists
@@ -148,7 +148,7 @@ class Messages:
148
148
  ignore = f"`SocketSecurity ignore {alert.purl}`"
149
149
  if ignore not in ignore_commands:
150
150
  ignore_commands.append(ignore)
151
- manifest_str, sources = Messages.create_sources(alert, "console")
151
+ manifest_str, source_str = Messages.create_sources(alert)
152
152
  purl_url = f"[{alert.purl}]({alert.url})"
153
153
  if alert.error:
154
154
  emoji = ':no_entry_sign:'
@@ -157,7 +157,7 @@ class Messages:
157
157
  row = [
158
158
  alert.title,
159
159
  purl_url,
160
- ", ".join(sources),
160
+ source_str,
161
161
  manifest_str,
162
162
  emoji
163
163
  ]
@@ -269,6 +269,7 @@ class Messages:
269
269
  [
270
270
  "Alert",
271
271
  "Package",
272
+ "url",
272
273
  "Introduced by",
273
274
  "Manifest File",
274
275
  "CI Status"
@@ -276,7 +277,7 @@ class Messages:
276
277
  )
277
278
  for alert in diff.new_alerts:
278
279
  alert: Issue
279
- manifest_str, sources = Messages.create_sources(alert, "console")
280
+ manifest_str, source_str = Messages.create_sources(alert, "console")
280
281
  if alert.error:
281
282
  state = "block"
282
283
  elif alert.warn:
@@ -287,8 +288,9 @@ class Messages:
287
288
  state = "ignore"
288
289
  row = [
289
290
  alert.title,
291
+ alert.purl,
290
292
  alert.url,
291
- ", ".join(sources),
293
+ source_str,
292
294
  manifest_str,
293
295
  state
294
296
  ]
@@ -296,18 +298,28 @@ class Messages:
296
298
  return alert_table
297
299
 
298
300
  @staticmethod
299
- def create_sources(alert: Issue, style="md") -> [str, list]:
301
+ def create_sources(alert: Issue, style="md") -> [str, str]:
300
302
  sources = []
301
303
  manifests = []
302
304
  for source, manifest in alert.introduced_by:
303
- sources.append(source)
304
305
  if style == "md":
305
- manifests.append(f"<li>{manifest}</li>")
306
+ add_str = f"<li>{manifest}</li>"
307
+ source_str = f"<li>{source}</li>"
306
308
  else:
307
- manifests.append(manifest)
309
+ add_str = f"{manifest};"
310
+ source_str = f"{source};"
311
+ if source_str not in sources:
312
+ sources.append(source_str)
313
+ if add_str not in manifests:
314
+ manifests.append(add_str)
308
315
  manifest_list = "".join(manifests)
316
+ source_list = "".join(sources)
317
+ source_list = source_list.rstrip(";")
318
+ manifest_list = manifest_list.rstrip(";")
309
319
  if style == "md":
310
320
  manifest_str = f"<ul>{manifest_list}</ul>"
321
+ sources_str = f"<ul>{source_list}</ul>"
311
322
  else:
312
323
  manifest_str = manifest_list
313
- return manifest_str, sources
324
+ sources_str = source_list
325
+ return manifest_str, sources_str
@@ -31,12 +31,13 @@ class Comments:
31
31
  if ignore_all:
32
32
  break
33
33
  else:
34
- purl = f"{alert.pkg_name}, {alert.pkg_version}"
35
- purl_star = f"{alert.pkg_name}, *"
34
+ full_name = f"{alert.pkg_type}/{alert.pkg_name}"
35
+ purl = (full_name, alert.pkg_version)
36
+ purl_star = (full_name, "*")
36
37
  if purl in ignore_commands or purl_star in ignore_commands:
37
- print(f"Alerts for {alert.pkg_name}@{alert.pkg_version} ignored")
38
+ log.info(f"Alerts for {alert.pkg_name}@{alert.pkg_version} ignored")
38
39
  else:
39
- print(f"Adding alert {alert.type} for {alert.pkg_name}@{alert.pkg_version}")
40
+ log.info(f"Adding alert {alert.type} for {alert.pkg_name}@{alert.pkg_version}")
40
41
  alerts.append(alert)
41
42
  return alerts
42
43
 
@@ -49,16 +50,20 @@ class Comments:
49
50
  comment: Comment
50
51
  first_line = comment.body_list[0]
51
52
  if not ignore_all and "SocketSecurity ignore" in first_line:
52
- first_line = first_line.lstrip("@")
53
- _, command = first_line.split("SocketSecurity ")
54
- command = command.strip()
55
- if command == "ignore-all":
56
- ignore_all = True
57
- else:
58
- command = command.lstrip("ignore").strip()
59
- name, version = command.split("@")
60
- data = f"{name}, {version}"
61
- ignore_commands.append(data)
53
+ try:
54
+ first_line = first_line.lstrip("@")
55
+ _, command = first_line.split("SocketSecurity ")
56
+ command = command.strip()
57
+ if command == "ignore-all":
58
+ ignore_all = True
59
+ else:
60
+ command = command.lstrip("ignore").strip()
61
+ name, version = command.split("@")
62
+ data = (name, version)
63
+ ignore_commands.append(data)
64
+ except Exception as error:
65
+ log.error(f"Unable to process ignore command for {comment}")
66
+ log.error(error)
62
67
  return ignore_all, ignore_commands
63
68
 
64
69
  @staticmethod
@@ -71,7 +76,7 @@ class Comments:
71
76
  @staticmethod
72
77
  def is_heading_line(line) -> bool:
73
78
  is_heading_line = True
74
- if line != "|Alert|Package|Introduced by|Manifest File|" and ":---" not in line:
79
+ if line != "|Alert|Package|Introduced by|Manifest File|CI|" and ":---" not in line:
75
80
  is_heading_line = False
76
81
  return is_heading_line
77
82
 
@@ -86,10 +91,12 @@ class Comments:
86
91
  start = True
87
92
  lines.append(line)
88
93
  elif start and "end-socket-alerts-table" not in line and not Comments.is_heading_line(line) and line != '':
89
- title, package, introduced_by, manifest = line.lstrip("|").rstrip("|").split("|")
94
+ title, package, introduced_by, manifest, ci = line.lstrip("|").rstrip("|").split("|")
90
95
  details, _ = package.split("](")
91
96
  ecosystem, details = details.split("/", 1)
97
+ ecosystem = ecosystem.lstrip("[")
92
98
  pkg_name, pkg_version = details.split("@")
99
+ pkg_name = f"{ecosystem}/{pkg_name}"
93
100
  ignore = False
94
101
  for name, version in ignore_commands:
95
102
  if ignore_all or Comments.is_ignore(pkg_name, pkg_version, name, version):
@@ -114,7 +121,7 @@ class Comments:
114
121
  socket_comments["security"] = comment
115
122
  elif "socket-overview-comment-actions" in comment.body:
116
123
  socket_comments["overview"] = comment
117
- elif "SocketSecurity ignore" in comment.body:
124
+ elif "SocketSecurity ignore".lower() in comment.body_list[0].lower():
118
125
  if "ignore" not in socket_comments:
119
126
  socket_comments["ignore"] = []
120
127
  socket_comments["ignore"].append(comment)
@@ -5,7 +5,7 @@ from socketsecurity.core.classes import FullScanParams, Diff, Package, Alert
5
5
  from socketsecurity.core.messages import Messages
6
6
  from socketsecurity.core.scm_comments import Comments
7
7
  from socketsecurity.core.git_interface import Git
8
- from git import InvalidGitRepositoryError
8
+ from git import InvalidGitRepositoryError, NoSuchPathError
9
9
  import os
10
10
  import sys
11
11
  import logging
@@ -245,6 +245,8 @@ def main_code():
245
245
  except InvalidGitRepositoryError:
246
246
  is_repo = False
247
247
  pass
248
+ except NoSuchPathError:
249
+ raise Exception(f"Unable to find path {target_path}")
248
250
  # git_repo = None
249
251
  if repo is None:
250
252
  log.info("Repo name needs to be set")
@@ -306,11 +308,17 @@ def main_code():
306
308
  new_security_comment = True
307
309
  new_overview_comment = True
308
310
  if len(diff.new_alerts) == 0 or disable_security_issue:
309
- new_security_comment = False
310
- log.debug("No new alerts or security issue comment disabled")
311
+ if security_comment is None or security_comment == "":
312
+ new_security_comment = False
313
+ log.debug("No new alerts or security issue comment disabled")
314
+ else:
315
+ log.debug("Updated security comment with no new alerts")
311
316
  if (len(diff.new_packages) == 0 and len(diff.removed_packages) == 0) or disable_overview:
312
- new_overview_comment = False
313
- log.debug("No new/removed packages or Dependency Overview comment disabled")
317
+ if overview_comment is None or overview_comment == "":
318
+ new_overview_comment = False
319
+ log.debug("No new/removed packages or Dependency Overview comment disabled")
320
+ else:
321
+ log.debug("Updated overview comment with no dependencies")
314
322
  log.debug(f"Adding comments for {scm_type}")
315
323
  scm.add_socket_comments(
316
324
  security_comment,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: socketsecurity
3
- Version: 1.0.1
3
+ Version: 1.0.3
4
4
  Summary: Socket Security CLI for CI/CD
5
5
  Author-email: Douglas Coburn <douglas@socket.dev>
6
6
  Maintainer-email: Douglas Coburn <douglas@socket.dev>
File without changes
File without changes
File without changes