Skip to content

Commit c2a8b51

Browse files
obarreraOrlando Barrera II
and
Orlando Barrera II
authored
Orlando/sarif package link (#49)
* Improved file line number glob. Added link to socket.dev for package alert. * Updated version * Removed -1 ftom sarif * Added the Socket Package link to the alert info * Fixed the package info link * Fixed the package url link * Update messages.py * Update messages.py --------- Co-authored-by: Orlando Barrera II <[email protected]>
1 parent 7ddb453 commit c2a8b51

File tree

2 files changed

+55
-40
lines changed

2 files changed

+55
-40
lines changed

Diff for: socketsecurity/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
__author__ = 'socket.dev'
2-
__version__ = '1.0.44'
2+
__version__ = '1.0.47'

Diff for: socketsecurity/core/messages.py

+54-39
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
8282
needle_key = f'"{found_key}":' # e.g. "node_modules/axios":
8383
needle_version = f'"version": "{packageversion}"'
8484
lines = raw_text.splitlines()
85-
best_line = -1
85+
best_line = 1
8686
snippet = None
8787

8888
for i, line in enumerate(lines, start=1):
@@ -97,10 +97,10 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
9797
else:
9898
return 1, f'"{found_key}": {found_info}'
9999
else:
100-
return -1, f"{packagename} {packageversion} (not found in {manifest_file})"
100+
return 1, f"{packagename} {packageversion} (not found in {manifest_file})"
101101

102102
except (FileNotFoundError, json.JSONDecodeError):
103-
return -1, f"Error reading {manifest_file}"
103+
return 1, f"Error reading {manifest_file}"
104104

105105
# ----------------------------------------------------
106106
# 2) Text-based / line-based manifests
@@ -148,28 +148,49 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
148148
return line_number, line_content.strip()
149149

150150
except FileNotFoundError:
151-
return -1, f"{manifest_file} not found"
151+
return 1, f"{manifest_file} not found"
152152
except Exception as e:
153-
return -1, f"Error reading {manifest_file}: {e}"
153+
return 1, f"Error reading {manifest_file}: {e}"
154154

155-
return -1, f"{packagename} {packageversion} (not found)"
155+
return 1, f"{packagename} {packageversion} (not found)"
156156

157157
@staticmethod
158-
def create_security_comment_sarif(diff: Diff) -> dict:
158+
def get_manifest_type_url(manifest_file: str, pkg_name: str, pkg_version: str) -> str:
159159
"""
160-
Create SARIF-compliant output from the diff report, including line references
161-
and a link to the Socket docs in the fullDescription. Also converts any \r\n
162-
into <br/> so they render properly in GitHub's SARIF display.
160+
Determine the correct URL path based on the manifest file type.
163161
"""
164-
# Check if there's a blocking error in new alerts
165-
scan_failed = False
166-
if len(diff.new_alerts) == 0:
167-
for alert in diff.new_alerts:
168-
if alert.error:
169-
scan_failed = True
170-
break
162+
manifest_to_url_prefix = {
163+
"package.json": "npm",
164+
"package-lock.json": "npm",
165+
"yarn.lock": "npm",
166+
"pnpm-lock.yaml": "npm",
167+
"requirements.txt": "pypi",
168+
"pyproject.toml": "pypi",
169+
"Pipfile": "pypi",
170+
"go.mod": "go",
171+
"go.sum": "go",
172+
"pom.xml": "maven",
173+
"build.gradle": "maven",
174+
".csproj": "nuget",
175+
".fsproj": "nuget",
176+
"paket.dependencies": "nuget",
177+
"Cargo.toml": "cargo",
178+
"Gemfile": "rubygems",
179+
"Gemfile.lock": "rubygems",
180+
"composer.json": "composer",
181+
"vcpkg.json": "vcpkg",
182+
}
183+
184+
file_type = Path(manifest_file).name
185+
url_prefix = manifest_to_url_prefix.get(file_type, "unknown")
186+
return f"https://socket.dev/{url_prefix}/package/{pkg_name}/alerts/{pkg_version}"
171187

172-
# Basic SARIF skeleton
188+
@staticmethod
189+
def create_security_comment_sarif(diff) -> dict:
190+
"""
191+
Create SARIF-compliant output from the diff report, including dynamic URL generation
192+
based on manifest type and improved <br/> formatting for GitHub SARIF display.
193+
"""
173194
sarif_data = {
174195
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
175196
"version": "2.1.0",
@@ -196,40 +217,34 @@ def create_security_comment_sarif(diff: Diff) -> dict:
196217
rule_id = f"{pkg_name}=={pkg_version}"
197218
severity = alert.severity
198219

199-
# Convert any \r\n in short desc to <br/> so they display properly
200-
short_desc_raw = f"{alert.props.get('note', '')}\r\n\r\nSuggested Action:\r\n{alert.suggestion}"
201-
short_desc = short_desc_raw.replace("\r\n", "<br/>")
202-
203-
# Build link to Socket docs, e.g. "https://socket.dev/npm/package/foo/alerts/1.2.3"
204-
socket_url = f"https://socket.dev/npm/package/{pkg_name}/alerts/{pkg_version}"
205-
206-
# Also convert \r\n in the main description to <br/>, then append the Socket docs link
207-
base_desc = alert.description.replace("\r\n", "<br/>")
208-
full_desc_raw = f"{alert.title} - {base_desc}<br/>{socket_url}"
209-
210-
# Identify the manifest file and line
220+
# Generate the correct URL for the alert based on manifest type
211221
introduced_list = alert.introduced_by
212-
if introduced_list and isinstance(introduced_list[0], list) and len(introduced_list[0]) > 1:
213-
manifest_file = introduced_list[0][1]
214-
else:
215-
manifest_file = alert.manifests or "requirements.txt"
222+
manifest_file = introduced_list[0][1] if introduced_list and isinstance(introduced_list[0], list) else alert.manifests or "requirements.txt"
223+
socket_url = Messages.get_manifest_type_url(manifest_file, pkg_name, pkg_version)
224+
225+
# Prepare descriptions with <br/> replacements
226+
short_desc = f"{alert.props.get('note', '')}<br/><br/>Suggested Action:<br/>{alert.suggestion}<br/><a href=\"{socket_url}\">{socket_url}</a>"
227+
full_desc = f"{alert.title} - {alert.description.replace('\r\n', '<br/>')}"
216228

229+
# Identify the line and snippet in the manifest file
217230
line_number, line_content = Messages.find_line_in_file(pkg_name, pkg_version, manifest_file)
231+
if line_number < 1:
232+
line_number = 1 # Ensure SARIF compliance
218233

219-
# If not already defined, create a rule for this package
234+
# Create the rule if not already defined
220235
if rule_id not in rules_map:
221236
rules_map[rule_id] = {
222237
"id": rule_id,
223238
"name": f"{pkg_name}=={pkg_version}",
224239
"shortDescription": {"text": f"Alert generated for {rule_id} by Socket Security"},
225-
"fullDescription": {"text": full_desc_raw},
226-
"helpUri": alert.url,
240+
"fullDescription": {"text": full_desc},
241+
"helpUri": socket_url,
227242
"defaultConfiguration": {
228243
"level": Messages.map_severity_to_sarif(severity)
229244
},
230245
}
231246

232-
# Create a SARIF "result" referencing the line where we found the match
247+
# Add the SARIF result
233248
result_obj = {
234249
"ruleId": rule_id,
235250
"message": {"text": short_desc},
@@ -247,7 +262,7 @@ def create_security_comment_sarif(diff: Diff) -> dict:
247262
}
248263
results_list.append(result_obj)
249264

250-
# Attach our rules and results to the SARIF data
265+
# Attach rules and results
251266
sarif_data["runs"][0]["tool"]["driver"]["rules"] = list(rules_map.values())
252267
sarif_data["runs"][0]["results"] = results_list
253268

0 commit comments

Comments
 (0)