@@ -18,7 +18,7 @@ class Messages:
18
18
def map_severity_to_sarif (severity : str ) -> str :
19
19
"""
20
20
Map Socket severity levels to SARIF levels (GitHub code scanning).
21
-
21
+
22
22
'low' -> 'note'
23
23
'medium' or 'middle' -> 'warning'
24
24
'high' or 'critical' -> 'error'
@@ -37,31 +37,35 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
37
37
"""
38
38
Finds the line number and snippet of code for the given package/version in a manifest file.
39
39
Returns a 2-tuple: (line_number, snippet_or_message).
40
+
41
+ Supports:
42
+ 1) JSON-based manifest files (package-lock.json, Pipfile.lock, composer.lock)
43
+ - Locates a dictionary entry with the matching package & version
44
+ - Does a rough line-based search to find the actual line in the raw text
45
+ 2) Text-based (requirements.txt, package.json, yarn.lock, etc.)
46
+ - Uses compiled regex patterns to detect a match line by line
40
47
"""
48
+ # Extract just the file name to detect manifest type
41
49
file_type = Path (manifest_file ).name
42
- logging .debug ("Processing manifest file: %s" , manifest_file )
43
-
50
+ logging .debug ("Processing file: %s" , manifest_file )
51
+
44
52
# ----------------------------------------------------
45
53
# 1) JSON-based manifest files
46
54
# ----------------------------------------------------
47
55
if file_type in ["package-lock.json" , "Pipfile.lock" , "composer.lock" ]:
48
56
try :
49
57
with open (manifest_file , "r" , encoding = "utf-8" ) as f :
50
58
raw_text = f .read ()
51
- logging .debug ("Raw text length: %d" , len (raw_text ))
52
- try :
53
- data = json .loads (raw_text )
54
- except json .JSONDecodeError :
55
- data = {}
56
- logging .debug ("JSON decode failed for %s" , manifest_file )
57
-
59
+ logging .debug ("Read %d characters from %s" , len (raw_text ), manifest_file )
60
+ data = json .loads (raw_text )
58
61
packages_dict = (
59
62
data .get ("packages" )
60
63
or data .get ("default" )
61
64
or data .get ("dependencies" )
62
65
or {}
63
66
)
64
- logging .debug ("Packages dict keys: %s" , list (packages_dict .keys ()))
67
+ logging .debug ("Found package keys: %s" , list (packages_dict .keys ()))
68
+
65
69
found_key = None
66
70
found_info = None
67
71
for key , value in packages_dict .items ():
@@ -75,17 +79,18 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
75
79
needle_key = f'"{ found_key } ":'
76
80
needle_version = f'"version": "{ packageversion } "'
77
81
lines = raw_text .splitlines ()
78
- logging .debug ("Total lines: %d" , len (lines ))
82
+ logging .debug ("Total lines in %s : %d" , manifest_file , len (lines ))
79
83
for i , line in enumerate (lines , start = 1 ):
80
84
if (needle_key in line ) or (needle_version in line ):
81
- logging .debug ("Found match at line %d: %s" , i , line .strip ())
85
+ logging .debug ("Match found at line %d in %s : %s" , i , manifest_file , line .strip ())
82
86
return i , line .strip ()
83
87
return 1 , f'"{ found_key } ": { found_info } '
84
88
else :
85
89
return 1 , f"{ packagename } { packageversion } (not found in { manifest_file } )"
86
- except (FileNotFoundError , json .JSONDecodeError ):
90
+ except (FileNotFoundError , json .JSONDecodeError ) as e :
91
+ logging .error ("Error reading JSON from %s: %s" , manifest_file , e )
87
92
return 1 , f"Error reading { manifest_file } "
88
-
93
+
89
94
# ----------------------------------------------------
90
95
# 2) Text-based / line-based manifests
91
96
# ----------------------------------------------------
@@ -123,7 +128,7 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
123
128
for line_number , line_content in enumerate (lines , start = 1 ):
124
129
line_main = line_content .split (";" , 1 )[0 ].strip ()
125
130
if re .search (searchstring , line_main , re .IGNORECASE ):
126
- logging .debug ("Match found in %s at line %d: %s" , manifest_file , line_number , line_content .strip ())
131
+ logging .debug ("Match found at line %d in %s : %s" , line_number , manifest_file , line_content .strip ())
127
132
return line_number , line_content .strip ()
128
133
except FileNotFoundError :
129
134
return 1 , f"{ manifest_file } not found"
@@ -167,7 +172,7 @@ def create_security_comment_sarif(diff) -> dict:
167
172
"""
168
173
Create SARIF-compliant output from the diff report, including dynamic URL generation
169
174
based on manifest type and improved <br/> formatting for GitHub SARIF display.
170
-
175
+
171
176
This function now:
172
177
- Accepts multiple manifest files from alert.introduced_by or alert.manifests.
173
178
- Generates one SARIF location per manifest file.
@@ -216,12 +221,12 @@ def create_security_comment_sarif(diff) -> dict:
216
221
logging .debug ("Alert %s manifest_files before fallback: %s" , rule_id , manifest_files )
217
222
if not manifest_files :
218
223
manifest_files = ["requirements.txt" ]
219
- logging .debug ("Alert %s: Falling back to manifest_files : %s" , rule_id , manifest_files )
224
+ logging .debug ("Alert %s falling back to: %s" , rule_id , manifest_files )
220
225
221
- logging .debug ("Alert %s: Using manifest_file for URL: %s" , rule_id , manifest_files [0 ])
226
+ logging .debug ("Alert %s using manifest_file for URL: %s" , rule_id , manifest_files [0 ])
222
227
socket_url = Messages .get_manifest_type_url (manifest_files [0 ], pkg_name , pkg_version )
223
228
short_desc = (f"{ alert .props .get ('note' , '' )} <br/><br/>Suggested Action:<br/>{ alert .suggestion } "
224
- f"<br/><a href=\" { socket_url } \" >{ socket_url } </a>" )
229
+ f"<br/><a href=\" { socket_url } \" >{ socket_url } </a>" )
225
230
full_desc = "{} - {}" .format (alert .title , alert .description .replace ('\r \n ' , '<br/>' ))
226
231
227
232
if rule_id not in rules_map :
@@ -241,7 +246,7 @@ def create_security_comment_sarif(diff) -> dict:
241
246
for mf in manifest_files :
242
247
line_number , line_content = Messages .find_line_in_file (pkg_name , pkg_version , mf )
243
248
if line_number < 1 :
244
- line_number = 1
249
+ line_number = 1 # Ensure SARIF compliance.
245
250
logging .debug ("Alert %s: Manifest %s, line %d: %s" , rule_id , mf , line_number , line_content )
246
251
locations .append ({
247
252
"physicalLocation" : {
@@ -264,7 +269,7 @@ def create_security_comment_sarif(diff) -> dict:
264
269
sarif_data ["runs" ][0 ]["results" ] = results_list
265
270
266
271
return sarif_data
267
-
272
+
268
273
@staticmethod
269
274
def create_security_comment_json (diff : Diff ) -> dict :
270
275
scan_failed = False
0 commit comments