socketsecurity 1.0.1__tar.gz → 1.0.2__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.2}/PKG-INFO +1 -1
  2. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/__init__.py +1 -1
  3. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/__init__.py +16 -5
  4. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/github.py +36 -0
  5. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/messages.py +19 -9
  6. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/scm_comments.py +19 -13
  7. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/socketcli.py +13 -5
  8. {socketsecurity-1.0.1 → socketsecurity-1.0.2/socketsecurity.egg-info}/PKG-INFO +1 -1
  9. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/LICENSE +0 -0
  10. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/README.md +0 -0
  11. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/pyproject.toml +0 -0
  12. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/setup.cfg +0 -0
  13. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/classes.py +0 -0
  14. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/exceptions.py +0 -0
  15. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/git_interface.py +0 -0
  16. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/gitlab.py +0 -0
  17. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/issues.py +0 -0
  18. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity/core/licenses.py +0 -0
  19. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity.egg-info/SOURCES.txt +0 -0
  20. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity.egg-info/dependency_links.txt +0 -0
  21. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity.egg-info/entry_points.txt +0 -0
  22. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/socketsecurity.egg-info/requires.txt +0 -0
  23. {socketsecurity-1.0.1 → socketsecurity-1.0.2}/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.2
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.2'
@@ -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
  ]
@@ -276,7 +276,7 @@ class Messages:
276
276
  )
277
277
  for alert in diff.new_alerts:
278
278
  alert: Issue
279
- manifest_str, sources = Messages.create_sources(alert, "console")
279
+ manifest_str, source_str = Messages.create_sources(alert, "console")
280
280
  if alert.error:
281
281
  state = "block"
282
282
  elif alert.warn:
@@ -288,7 +288,7 @@ class Messages:
288
288
  row = [
289
289
  alert.title,
290
290
  alert.url,
291
- ", ".join(sources),
291
+ source_str,
292
292
  manifest_str,
293
293
  state
294
294
  ]
@@ -296,18 +296,28 @@ class Messages:
296
296
  return alert_table
297
297
 
298
298
  @staticmethod
299
- def create_sources(alert: Issue, style="md") -> [str, list]:
299
+ def create_sources(alert: Issue, style="md") -> [str, str]:
300
300
  sources = []
301
301
  manifests = []
302
302
  for source, manifest in alert.introduced_by:
303
- sources.append(source)
304
303
  if style == "md":
305
- manifests.append(f"<li>{manifest}</li>")
304
+ add_str = f"<li>{manifest}</li>"
305
+ source_str = f"<li>{source}</li>"
306
306
  else:
307
- manifests.append(manifest)
307
+ add_str = f"{manifest};"
308
+ source_str = f"{source};"
309
+ if source_str not in sources:
310
+ sources.append(source_str)
311
+ if add_str not in manifests:
312
+ manifests.append(add_str)
308
313
  manifest_list = "".join(manifests)
314
+ source_list = "".join(sources)
315
+ source_list = source_list.rstrip(";")
316
+ manifest_list = manifest_list.rstrip(";")
309
317
  if style == "md":
310
318
  manifest_str = f"<ul>{manifest_list}</ul>"
319
+ sources_str = f"<ul>{source_list}</ul>"
311
320
  else:
312
321
  manifest_str = manifest_list
313
- return manifest_str, sources
322
+ sources_str = source_list
323
+ return manifest_str, sources_str
@@ -49,16 +49,20 @@ class Comments:
49
49
  comment: Comment
50
50
  first_line = comment.body_list[0]
51
51
  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)
52
+ try:
53
+ first_line = first_line.lstrip("@")
54
+ _, command = first_line.split("SocketSecurity ")
55
+ command = command.strip()
56
+ if command == "ignore-all":
57
+ ignore_all = True
58
+ else:
59
+ command = command.lstrip("ignore").strip()
60
+ name, version = command.split("@")
61
+ data = (name, version)
62
+ ignore_commands.append(data)
63
+ except Exception as error:
64
+ log.error(f"Unable to process ignore command for {comment}")
65
+ log.error(error)
62
66
  return ignore_all, ignore_commands
63
67
 
64
68
  @staticmethod
@@ -71,7 +75,7 @@ class Comments:
71
75
  @staticmethod
72
76
  def is_heading_line(line) -> bool:
73
77
  is_heading_line = True
74
- if line != "|Alert|Package|Introduced by|Manifest File|" and ":---" not in line:
78
+ if line != "|Alert|Package|Introduced by|Manifest File|CI|" and ":---" not in line:
75
79
  is_heading_line = False
76
80
  return is_heading_line
77
81
 
@@ -86,10 +90,12 @@ class Comments:
86
90
  start = True
87
91
  lines.append(line)
88
92
  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("|")
93
+ title, package, introduced_by, manifest, ci = line.lstrip("|").rstrip("|").split("|")
90
94
  details, _ = package.split("](")
91
95
  ecosystem, details = details.split("/", 1)
96
+ ecosystem = ecosystem.lstrip("[")
92
97
  pkg_name, pkg_version = details.split("@")
98
+ pkg_name = f"{ecosystem}/{pkg_name}"
93
99
  ignore = False
94
100
  for name, version in ignore_commands:
95
101
  if ignore_all or Comments.is_ignore(pkg_name, pkg_version, name, version):
@@ -114,7 +120,7 @@ class Comments:
114
120
  socket_comments["security"] = comment
115
121
  elif "socket-overview-comment-actions" in comment.body:
116
122
  socket_comments["overview"] = comment
117
- elif "SocketSecurity ignore" in comment.body:
123
+ elif "SocketSecurity ignore".lower() in comment.body.lower():
118
124
  if "ignore" not in socket_comments:
119
125
  socket_comments["ignore"] = []
120
126
  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.2
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