@@ -64,11 +64,10 @@ def add_header(self) -> None:
6464 self .sections .extend ([
6565 "# 🔍 CodeQL Security Analysis Report" ,
6666 "\n ## Scan Details" ,
67- f"**Scan Type**: CodeQL Static Analysis" ,
68- f"**Scan Date**: { datetime .utcnow ().strftime ('%Y-%m-%d %H:%M:%S UTC' )} " ,
69- f"**Operating System**: { platform .system ()} { platform .release ()} " ,
70- f"**Analysis Tool**: CodeQL { codeql_version } " ,
71- f"**Repository**: { os .path .basename (os .getcwd ())} " ,
67+ f"**Scan Type**: CodeQL Static Analysis\n " ,
68+ f"**Scan Date**: { datetime .utcnow ().strftime ('%Y-%m-%d %H:%M:%S UTC' )} \n " ,
69+ f"**Operating System**: { platform .system ()} { platform .release ()} \n " ,
70+ f"**Analysis Tool**: CodeQL" ,
7271 "\n ---\n "
7372 ])
7473
@@ -79,18 +78,45 @@ def add_tool_info(self) -> None:
7978 self .sections .extend ([
8079 "\n ## 🛠️ Analysis Details" ,
8180 f"- **Tool**: { tool .get ('name' , 'CodeQL' )} " ,
82- f"- **Version**: { tool .get ('version' , 'N/A' )} " ,
83- f"- **Language**: { tool .get ('language' , 'N/A' )} "
81+ f"- **Version**: { tool .get ('semanticVersion' , tool .get ('version' , 'N/A' ))} " ,
8482 ])
8583
84+ # Map artifact index to language
85+ artifact_lang = {}
86+ for notification in tool .get ('notifications' , []):
87+ lang = notification .get ('properties' , {}).get ('languageDisplayName' )
88+ locations = notification .get ('locations' , [])
89+ for loc in locations :
90+ idx = loc .get ('physicalLocation' , {}).get ('artifactLocation' , {}).get ('index' )
91+ if lang and idx is not None :
92+ artifact_lang [idx ] = lang
93+
94+
95+
8696 def add_summary (self ) -> None :
87- severity_count = {'error' : 0 , 'warning' : 0 , 'note' : 0 , 'none' : 0 }
97+ severity_count = {
98+ 'error' : 0 ,
99+ 'warning' : 0 ,
100+ 'note' : 0 ,
101+ 'none' : 0
102+ }
88103 total_issues = 0
89104
90105 for run in self .data .get ('runs' , []):
106+ # Collect rules from driver and all extensions
107+ rules = {rule ['id' ]: rule for rule in run .get ('tool' , {}).get ('driver' , {}).get ('rules' , [])}
108+ for ext in run .get ('tool' , {}).get ('extensions' , []):
109+ for rule in ext .get ('rules' , []):
110+ rules [rule ['id' ]] = rule
111+
91112 for result in run .get ('results' , []):
92- level = result .get ('level' , 'none' ).lower ()
93- severity_count [level ] = severity_count .get (level , 0 ) + 1
113+ rule_id = result .get ('ruleId' , 'unknown' )
114+ rule = rules .get (rule_id , {})
115+ rule_severity = rule .get ('properties' , {}).get ('problem.severity' , 'none' )
116+ level = result .get ('level' , rule_severity ).lower ()
117+ if level not in severity_count :
118+ severity_count [level ] = 0
119+ severity_count [level ] += 1
94120 total_issues += 1
95121
96122 self .sections .extend ([
@@ -99,10 +125,11 @@ def add_summary(self) -> None:
99125 "\n ### Severity Breakdown"
100126 ])
101127
102- for severity , count in severity_count .items ():
103- if count > 0 :
104- emoji = self .formatter .get_emoji (severity )
105- self .sections .append (f"- { emoji } **{ severity .title ()} **: { count } " )
128+ for severity in ['error' , 'warning' , 'note' , 'none' ]:
129+ count = severity_count .get (severity , 0 )
130+ emoji = self .formatter .get_emoji (severity )
131+ self .sections .append (f"- { emoji } **{ severity .title ()} **: { count } " )
132+
106133
107134 def add_query_info (self ) -> None :
108135 self .sections .append ("\n ## 📝 Query Information" )
@@ -142,14 +169,18 @@ def add_findings(self) -> None:
142169 ])
143170
144171 for run in self .data .get ('runs' , []):
172+ # Collect rules from driver and all extensions
145173 rules = {rule ['id' ]: rule for rule in run .get ('tool' , {}).get ('driver' , {}).get ('rules' , [])}
174+ for ext in run .get ('tool' , {}).get ('extensions' , []):
175+ for rule in ext .get ('rules' , []):
176+ rules [rule ['id' ]] = rule
146177
147178 for result in run .get ('results' , []):
148179 rule_id = result .get ('ruleId' , 'unknown' )
149180 rule = rules .get (rule_id , {})
150181 rule_name = rule .get ('name' , rule_id )
151182
152- # ✅ New logic to fallback to rule severity if result.level is missing
183+ # Fallback to rule severity if result.level is missing
153184 rule_severity = rule .get ('properties' , {}).get ('problem.severity' , 'none' )
154185 severity = result .get ('level' , rule_severity )
155186
@@ -160,7 +191,6 @@ def add_findings(self) -> None:
160191 self .sections .append (
161192 f"| { emoji } { severity .title ()} | { rule_name } | { location } | { message } |"
162193 )
163-
164194 def _format_location (self , locations : List [Dict ]) -> str :
165195 if not locations :
166196 return "N/A"
0 commit comments