slither.utils.command_line
1import argparse 2import enum 3import json 4import os 5import re 6import logging 7from collections import defaultdict 8from typing import Dict, List, Type, Union 9 10from crytic_compile.cryticparser.defaults import ( 11 DEFAULTS_FLAG_IN_CONFIG as DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE, 12) 13 14from slither.detectors.abstract_detector import classification_txt, AbstractDetector 15from slither.printers.abstract_printer import AbstractPrinter 16from slither.utils.colors import yellow, red 17from slither.utils.myprettytable import MyPrettyTable 18 19logger = logging.getLogger("Slither") 20 21DEFAULT_JSON_OUTPUT_TYPES = ["detectors", "printers"] 22JSON_OUTPUT_TYPES = [ 23 "compilations", 24 "console", 25 "detectors", 26 "printers", 27 "list-detectors", 28 "list-printers", 29] 30 31 32class FailOnLevel(enum.Enum): 33 PEDANTIC = "pedantic" 34 LOW = "low" 35 MEDIUM = "medium" 36 HIGH = "high" 37 NONE = "none" 38 39 40# Those are the flags shared by the command line and the config file 41defaults_flag_in_config = { 42 "codex": False, 43 "codex_contracts": "all", 44 "codex_model": "text-davinci-003", 45 "codex_temperature": 0, 46 "codex_max_tokens": 300, 47 "codex_log": False, 48 "detectors_to_run": "all", 49 "printers_to_run": None, 50 "detectors_to_exclude": None, 51 "detectors_to_include": None, 52 "exclude_dependencies": False, 53 "exclude_informational": False, 54 "exclude_optimization": False, 55 "exclude_low": False, 56 "exclude_medium": False, 57 "exclude_high": False, 58 "fail_on": FailOnLevel.PEDANTIC, 59 "json": None, 60 "sarif": None, 61 "json-types": ",".join(DEFAULT_JSON_OUTPUT_TYPES), 62 "disable_color": False, 63 "filter_paths": None, 64 "include_paths": None, 65 "generate_patches": False, 66 # debug command 67 "skip_assembly": False, 68 "legacy_ast": False, 69 "zip": None, 70 "zip_type": "lzma", 71 "show_ignored_findings": False, 72 "no_fail": False, 73 "sarif_input": "export.sarif", 74 "sarif_triage": "export.sarif.sarifexplorer", 75 "triage_database": "slither.db.json", 76 **DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE, 77} 78 79 80def read_config_file(args: argparse.Namespace) -> None: 81 # No config file was provided as an argument 82 if args.config_file is None: 83 # Check whether the default config file is present 84 if os.path.exists("slither.config.json"): 85 # The default file exists, use it 86 args.config_file = "slither.config.json" 87 else: 88 return 89 90 if os.path.isfile(args.config_file): 91 try: 92 with open(args.config_file, encoding="utf8") as f: 93 config = json.load(f) 94 for key, elem in config.items(): 95 if key not in defaults_flag_in_config: 96 logger.info( 97 yellow(f"{args.config_file} has an unknown key: {key} : {elem}") 98 ) 99 continue 100 if getattr(args, key) == defaults_flag_in_config[key]: 101 setattr(args, key, elem) 102 except json.decoder.JSONDecodeError as e: 103 logger.error(red(f"Impossible to read {args.config_file}, please check the file {e}")) 104 else: 105 logger.error(red(f"File {args.config_file} is not a file or does not exist")) 106 logger.error(yellow("Falling back to the default settings...")) 107 108 109def output_to_markdown( 110 detector_classes: List[Type[AbstractDetector]], 111 printer_classes: List[Type[AbstractPrinter]], 112 filter_wiki: str, 113) -> None: 114 def extract_help(cls: Union[Type[AbstractDetector], Type[AbstractPrinter]]) -> str: 115 if cls.WIKI == "": 116 return cls.HELP 117 return f"[{cls.HELP}]({cls.WIKI})" 118 119 detectors_list = [] 120 print(filter_wiki) 121 for detector in detector_classes: 122 argument = detector.ARGUMENT 123 # dont show the backdoor example 124 if argument == "backdoor": 125 continue 126 if not filter_wiki in detector.WIKI: 127 continue 128 help_info = extract_help(detector) 129 impact = detector.IMPACT 130 confidence = classification_txt[detector.CONFIDENCE] 131 detectors_list.append((argument, help_info, impact, confidence)) 132 133 # Sort by impact, confidence, and name 134 detectors_list = sorted( 135 detectors_list, key=lambda element: (element[2], element[3], element[0]) 136 ) 137 idx = 1 138 for (argument, help_info, impact, confidence) in detectors_list: 139 print(f"{idx} | `{argument}` | {help_info} | {classification_txt[impact]} | {confidence}") 140 idx = idx + 1 141 142 print() 143 printers_list = [] 144 for printer in printer_classes: 145 argument = printer.ARGUMENT 146 help_info = extract_help(printer) 147 printers_list.append((argument, help_info)) 148 149 # Sort by impact, confidence, and name 150 printers_list = sorted(printers_list, key=lambda element: (element[0])) 151 idx = 1 152 for (argument, help_info) in printers_list: 153 print(f"{idx} | `{argument}` | {help_info}") 154 idx = idx + 1 155 156 157def get_level(l: str) -> int: 158 tab = l.count("\t") + 1 159 if l.replace("\t", "").startswith(" -"): 160 tab = tab + 1 161 if l.replace("\t", "").startswith("-"): 162 tab = tab + 1 163 return tab 164 165 166def convert_result_to_markdown(txt: str) -> str: 167 # -1 to remove the last \n 168 lines = txt[0:-1].split("\n") 169 ret = [] 170 level = 0 171 for l in lines: 172 next_level = get_level(l) 173 prefix = "<li>" 174 if next_level < level: 175 prefix = "</ul>" * (level - next_level) + prefix 176 if next_level > level: 177 prefix = "<ul>" * (next_level - level) + prefix 178 level = next_level 179 ret.append(prefix + l) 180 181 return "".join(ret) 182 183 184def output_results_to_markdown( 185 all_results: List[Dict], checklistlimit: str, show_ignored_findings: bool 186) -> None: 187 checks = defaultdict(list) 188 info: Dict = defaultdict(dict) 189 for results_ in all_results: 190 checks[results_["check"]].append(results_) 191 info[results_["check"]] = { 192 "impact": results_["impact"], 193 "confidence": results_["confidence"], 194 } 195 196 if not show_ignored_findings: 197 print( 198 "**THIS CHECKLIST IS NOT COMPLETE**. Use `--show-ignored-findings` to show all the results." 199 ) 200 201 print("Summary") 202 for check_ in checks: 203 print( 204 f" - [{check_}](#{check_}) ({len(checks[check_])} results) ({info[check_]['impact']})" 205 ) 206 207 counter = 0 208 for (check, results) in checks.items(): 209 print(f"## {check}") 210 print(f'Impact: {info[check]["impact"]}') 211 print(f'Confidence: {info[check]["confidence"]}') 212 additional = False 213 if checklistlimit and len(results) > 5: 214 results = results[0:5] 215 additional = True 216 for result in results: 217 print(" - [ ] ID-" + f"{counter}") 218 counter = counter + 1 219 print(result["markdown"]) 220 if result["first_markdown_element"]: 221 print(result["first_markdown_element"]) 222 print("\n") 223 if additional: 224 print(f"**More results were found, check [{checklistlimit}]({checklistlimit})**") 225 226 227def output_wiki(detector_classes: List[Type[AbstractDetector]], filter_wiki: str) -> None: 228 229 # Sort by impact, confidence, and name 230 detectors_list = sorted( 231 detector_classes, 232 key=lambda element: (element.IMPACT, element.CONFIDENCE, element.ARGUMENT), 233 ) 234 235 for detector in detectors_list: 236 argument = detector.ARGUMENT 237 # dont show the backdoor example 238 if argument == "backdoor": 239 continue 240 if not filter_wiki in detector.WIKI: 241 continue 242 check = detector.ARGUMENT 243 impact = classification_txt[detector.IMPACT] 244 confidence = classification_txt[detector.CONFIDENCE] 245 title = detector.WIKI_TITLE 246 description = detector.WIKI_DESCRIPTION 247 exploit_scenario = detector.WIKI_EXPLOIT_SCENARIO 248 recommendation = detector.WIKI_RECOMMENDATION 249 250 print(f"\n## {title}") 251 print("### Configuration") 252 print(f"* Check: `{check}`") 253 print(f"* Severity: `{impact}`") 254 print(f"* Confidence: `{confidence}`") 255 print("\n### Description") 256 print(description) 257 if exploit_scenario: 258 print("\n### Exploit Scenario:") 259 print(exploit_scenario) 260 print("\n### Recommendation") 261 print(recommendation) 262 263 264def output_detectors(detector_classes: List[Type[AbstractDetector]]) -> None: 265 detectors_list = [] 266 for detector in detector_classes: 267 argument = detector.ARGUMENT 268 # dont show the backdoor example 269 if argument == "backdoor": 270 continue 271 help_info = detector.HELP 272 impact = detector.IMPACT 273 confidence = classification_txt[detector.CONFIDENCE] 274 detectors_list.append((argument, help_info, impact, confidence)) 275 table = MyPrettyTable(["Num", "Check", "What it Detects", "Impact", "Confidence"]) 276 277 # Sort by impact, confidence, and name 278 detectors_list = sorted( 279 detectors_list, key=lambda element: (element[2], element[3], element[0]) 280 ) 281 idx = 1 282 for (argument, help_info, impact, confidence) in detectors_list: 283 table.add_row([str(idx), argument, help_info, classification_txt[impact], confidence]) 284 idx = idx + 1 285 print(table) 286 287 288# pylint: disable=too-many-locals 289def output_detectors_json( 290 detector_classes: List[Type[AbstractDetector]], 291) -> List[Dict]: 292 detectors_list = [] 293 for detector in detector_classes: 294 argument = detector.ARGUMENT 295 # dont show the backdoor example 296 if argument == "backdoor": 297 continue 298 help_info = detector.HELP 299 impact = detector.IMPACT 300 confidence = classification_txt[detector.CONFIDENCE] 301 wiki_url = detector.WIKI 302 wiki_description = detector.WIKI_DESCRIPTION 303 wiki_exploit_scenario = detector.WIKI_EXPLOIT_SCENARIO 304 wiki_recommendation = detector.WIKI_RECOMMENDATION 305 detectors_list.append( 306 ( 307 argument, 308 help_info, 309 impact, 310 confidence, 311 wiki_url, 312 wiki_description, 313 wiki_exploit_scenario, 314 wiki_recommendation, 315 ) 316 ) 317 318 # Sort by impact, confidence, and name 319 detectors_list = sorted( 320 detectors_list, key=lambda element: (element[2], element[3], element[0]) 321 ) 322 idx = 1 323 table = [] 324 for ( 325 argument, 326 help_info, 327 impact, 328 confidence, 329 wiki_url, 330 description, 331 exploit, 332 recommendation, 333 ) in detectors_list: 334 table.append( 335 { 336 "index": idx, 337 "check": argument, 338 "title": help_info, 339 "impact": classification_txt[impact], 340 "confidence": confidence, 341 "wiki_url": wiki_url, 342 "description": description, 343 "exploit_scenario": exploit, 344 "recommendation": recommendation, 345 } 346 ) 347 idx = idx + 1 348 return table 349 350 351def output_printers(printer_classes: List[Type[AbstractPrinter]]) -> None: 352 printers_list = [] 353 for printer in printer_classes: 354 argument = printer.ARGUMENT 355 help_info = printer.HELP 356 printers_list.append((argument, help_info)) 357 table = MyPrettyTable(["Num", "Printer", "What it Does"]) 358 359 # Sort by impact, confidence, and name 360 printers_list = sorted(printers_list, key=lambda element: (element[0])) 361 idx = 1 362 for (argument, help_info) in printers_list: 363 # Clean multi line HELP info 364 table.add_row([str(idx), argument, " ".join(x.strip() for x in help_info.splitlines())]) 365 idx = idx + 1 366 367 print(table) 368 369 370def output_printers_json(printer_classes: List[Type[AbstractPrinter]]) -> List[Dict]: 371 printers_list = [] 372 for printer in printer_classes: 373 argument = printer.ARGUMENT 374 help_info = printer.HELP 375 376 printers_list.append((argument, help_info)) 377 378 # Sort by name 379 printers_list = sorted(printers_list, key=lambda element: (element[0])) 380 idx = 1 381 table = [] 382 for (argument, help_info) in printers_list: 383 table.append({"index": idx, "check": argument, "title": help_info}) 384 idx = idx + 1 385 return table 386 387 388def check_and_sanitize_markdown_root(markdown_root: str) -> str: 389 # Regex to check whether the markdown_root is a GitHub URL 390 match = re.search( 391 r"(https://)github.com/([a-zA-Z-]+)([:/][A-Za-z0-9_.-]+[:/]?)([A-Za-z0-9_.-]*)(.*)", 392 markdown_root, 393 ) 394 if match: 395 if markdown_root[-1] != "/": 396 logger.warning("Appending '/' in markdown_root url for better code referencing") 397 markdown_root = markdown_root + "/" 398 399 if not match.group(4): 400 logger.warning( 401 "Appending 'master/tree/' in markdown_root url for better code referencing" 402 ) 403 markdown_root = markdown_root + "master/tree/" 404 elif match.group(4) == "tree": 405 logger.warning( 406 "Replacing 'tree' with 'blob' in markdown_root url for better code referencing" 407 ) 408 positions = match.span(4) 409 markdown_root = f"{markdown_root[:positions[0]]}blob{markdown_root[positions[1]:]}" 410 411 return markdown_root
logger =
<Logger Slither (WARNING)>
DEFAULT_JSON_OUTPUT_TYPES =
['detectors', 'printers']
JSON_OUTPUT_TYPES =
['compilations', 'console', 'detectors', 'printers', 'list-detectors', 'list-printers']
class
FailOnLevel(enum.Enum):
33class FailOnLevel(enum.Enum): 34 PEDANTIC = "pedantic" 35 LOW = "low" 36 MEDIUM = "medium" 37 HIGH = "high" 38 NONE = "none"
An enumeration.
PEDANTIC =
<FailOnLevel.PEDANTIC: 'pedantic'>
LOW =
<FailOnLevel.LOW: 'low'>
MEDIUM =
<FailOnLevel.MEDIUM: 'medium'>
HIGH =
<FailOnLevel.HIGH: 'high'>
NONE =
<FailOnLevel.NONE: 'none'>
Inherited Members
- enum.Enum
- name
- value
defaults_flag_in_config =
{'codex': False, 'codex_contracts': 'all', 'codex_model': 'text-davinci-003', 'codex_temperature': 0, 'codex_max_tokens': 300, 'codex_log': False, 'detectors_to_run': 'all', 'printers_to_run': None, 'detectors_to_exclude': None, 'detectors_to_include': None, 'exclude_dependencies': False, 'exclude_informational': False, 'exclude_optimization': False, 'exclude_low': False, 'exclude_medium': False, 'exclude_high': False, 'fail_on': <FailOnLevel.PEDANTIC: 'pedantic'>, 'json': None, 'sarif': None, 'json-types': 'detectors,printers', 'disable_color': False, 'filter_paths': None, 'include_paths': None, 'generate_patches': False, 'skip_assembly': False, 'legacy_ast': False, 'zip': None, 'zip_type': 'lzma', 'show_ignored_findings': False, 'no_fail': False, 'sarif_input': 'export.sarif', 'sarif_triage': 'export.sarif.sarifexplorer', 'triage_database': 'slither.db.json', 'compile_force_framework': None, 'compile_remove_metadata': False, 'compile_custom_build': None, 'solc': 'solc', 'solc_remaps': None, 'solc_args': None, 'solc_disable_warnings': False, 'solc_working_dir': None, 'solc_solcs_select': None, 'solc_solcs_bin': None, 'solc_standard_json': False, 'solc_force_legacy_json': False, 'truffle_version': None, 'truffle_ignore_compile': False, 'truffle_build_directory': 'build/contracts', 'truffle_overwrite_config': False, 'truffle_overwrite_version': None, 'embark_ignore_compile': False, 'embark_overwrite_config': False, 'brownie_ignore_compile': False, 'dapp_ignore_compile': False, 'etherlime_ignore_compile': False, 'etherlime_compile_arguments': None, 'etherscan_only_source_code': False, 'etherscan_only_bytecode': False, 'etherscan_api_key': None, 'etherscan_export_directory': 'etherscan-contracts', 'waffle_ignore_compile': False, 'waffle_config_file': None, 'npx_disable': False, 'ignore_compile': False, 'skip_clean': False, 'buidler_ignore_compile': False, 'buidler_cache_directory': 'cache', 'buidler_skip_directory_name_fix': False, 'hardhat_ignore_compile': False, 'hardhat_cache_directory': None, 'hardhat_artifacts_directory': None, 'foundry_ignore_compile': False, 'foundry_out_directory': 'out', 'foundry_compile_all': False, 'export_dir': 'crytic-export', 'compile_libraries': None}
def
read_config_file(args: argparse.Namespace) -> None:
81def read_config_file(args: argparse.Namespace) -> None: 82 # No config file was provided as an argument 83 if args.config_file is None: 84 # Check whether the default config file is present 85 if os.path.exists("slither.config.json"): 86 # The default file exists, use it 87 args.config_file = "slither.config.json" 88 else: 89 return 90 91 if os.path.isfile(args.config_file): 92 try: 93 with open(args.config_file, encoding="utf8") as f: 94 config = json.load(f) 95 for key, elem in config.items(): 96 if key not in defaults_flag_in_config: 97 logger.info( 98 yellow(f"{args.config_file} has an unknown key: {key} : {elem}") 99 ) 100 continue 101 if getattr(args, key) == defaults_flag_in_config[key]: 102 setattr(args, key, elem) 103 except json.decoder.JSONDecodeError as e: 104 logger.error(red(f"Impossible to read {args.config_file}, please check the file {e}")) 105 else: 106 logger.error(red(f"File {args.config_file} is not a file or does not exist")) 107 logger.error(yellow("Falling back to the default settings..."))
def
output_to_markdown( detector_classes: List[Type[slither.detectors.abstract_detector.AbstractDetector]], printer_classes: List[Type[slither.printers.abstract_printer.AbstractPrinter]], filter_wiki: str) -> None:
110def output_to_markdown( 111 detector_classes: List[Type[AbstractDetector]], 112 printer_classes: List[Type[AbstractPrinter]], 113 filter_wiki: str, 114) -> None: 115 def extract_help(cls: Union[Type[AbstractDetector], Type[AbstractPrinter]]) -> str: 116 if cls.WIKI == "": 117 return cls.HELP 118 return f"[{cls.HELP}]({cls.WIKI})" 119 120 detectors_list = [] 121 print(filter_wiki) 122 for detector in detector_classes: 123 argument = detector.ARGUMENT 124 # dont show the backdoor example 125 if argument == "backdoor": 126 continue 127 if not filter_wiki in detector.WIKI: 128 continue 129 help_info = extract_help(detector) 130 impact = detector.IMPACT 131 confidence = classification_txt[detector.CONFIDENCE] 132 detectors_list.append((argument, help_info, impact, confidence)) 133 134 # Sort by impact, confidence, and name 135 detectors_list = sorted( 136 detectors_list, key=lambda element: (element[2], element[3], element[0]) 137 ) 138 idx = 1 139 for (argument, help_info, impact, confidence) in detectors_list: 140 print(f"{idx} | `{argument}` | {help_info} | {classification_txt[impact]} | {confidence}") 141 idx = idx + 1 142 143 print() 144 printers_list = [] 145 for printer in printer_classes: 146 argument = printer.ARGUMENT 147 help_info = extract_help(printer) 148 printers_list.append((argument, help_info)) 149 150 # Sort by impact, confidence, and name 151 printers_list = sorted(printers_list, key=lambda element: (element[0])) 152 idx = 1 153 for (argument, help_info) in printers_list: 154 print(f"{idx} | `{argument}` | {help_info}") 155 idx = idx + 1
def
get_level(l: str) -> int:
def
convert_result_to_markdown(txt: str) -> str:
167def convert_result_to_markdown(txt: str) -> str: 168 # -1 to remove the last \n 169 lines = txt[0:-1].split("\n") 170 ret = [] 171 level = 0 172 for l in lines: 173 next_level = get_level(l) 174 prefix = "<li>" 175 if next_level < level: 176 prefix = "</ul>" * (level - next_level) + prefix 177 if next_level > level: 178 prefix = "<ul>" * (next_level - level) + prefix 179 level = next_level 180 ret.append(prefix + l) 181 182 return "".join(ret)
def
output_results_to_markdown( all_results: List[Dict], checklistlimit: str, show_ignored_findings: bool) -> None:
185def output_results_to_markdown( 186 all_results: List[Dict], checklistlimit: str, show_ignored_findings: bool 187) -> None: 188 checks = defaultdict(list) 189 info: Dict = defaultdict(dict) 190 for results_ in all_results: 191 checks[results_["check"]].append(results_) 192 info[results_["check"]] = { 193 "impact": results_["impact"], 194 "confidence": results_["confidence"], 195 } 196 197 if not show_ignored_findings: 198 print( 199 "**THIS CHECKLIST IS NOT COMPLETE**. Use `--show-ignored-findings` to show all the results." 200 ) 201 202 print("Summary") 203 for check_ in checks: 204 print( 205 f" - [{check_}](#{check_}) ({len(checks[check_])} results) ({info[check_]['impact']})" 206 ) 207 208 counter = 0 209 for (check, results) in checks.items(): 210 print(f"## {check}") 211 print(f'Impact: {info[check]["impact"]}') 212 print(f'Confidence: {info[check]["confidence"]}') 213 additional = False 214 if checklistlimit and len(results) > 5: 215 results = results[0:5] 216 additional = True 217 for result in results: 218 print(" - [ ] ID-" + f"{counter}") 219 counter = counter + 1 220 print(result["markdown"]) 221 if result["first_markdown_element"]: 222 print(result["first_markdown_element"]) 223 print("\n") 224 if additional: 225 print(f"**More results were found, check [{checklistlimit}]({checklistlimit})**")
def
output_wiki( detector_classes: List[Type[slither.detectors.abstract_detector.AbstractDetector]], filter_wiki: str) -> None:
228def output_wiki(detector_classes: List[Type[AbstractDetector]], filter_wiki: str) -> None: 229 230 # Sort by impact, confidence, and name 231 detectors_list = sorted( 232 detector_classes, 233 key=lambda element: (element.IMPACT, element.CONFIDENCE, element.ARGUMENT), 234 ) 235 236 for detector in detectors_list: 237 argument = detector.ARGUMENT 238 # dont show the backdoor example 239 if argument == "backdoor": 240 continue 241 if not filter_wiki in detector.WIKI: 242 continue 243 check = detector.ARGUMENT 244 impact = classification_txt[detector.IMPACT] 245 confidence = classification_txt[detector.CONFIDENCE] 246 title = detector.WIKI_TITLE 247 description = detector.WIKI_DESCRIPTION 248 exploit_scenario = detector.WIKI_EXPLOIT_SCENARIO 249 recommendation = detector.WIKI_RECOMMENDATION 250 251 print(f"\n## {title}") 252 print("### Configuration") 253 print(f"* Check: `{check}`") 254 print(f"* Severity: `{impact}`") 255 print(f"* Confidence: `{confidence}`") 256 print("\n### Description") 257 print(description) 258 if exploit_scenario: 259 print("\n### Exploit Scenario:") 260 print(exploit_scenario) 261 print("\n### Recommendation") 262 print(recommendation)
def
output_detectors( detector_classes: List[Type[slither.detectors.abstract_detector.AbstractDetector]]) -> None:
265def output_detectors(detector_classes: List[Type[AbstractDetector]]) -> None: 266 detectors_list = [] 267 for detector in detector_classes: 268 argument = detector.ARGUMENT 269 # dont show the backdoor example 270 if argument == "backdoor": 271 continue 272 help_info = detector.HELP 273 impact = detector.IMPACT 274 confidence = classification_txt[detector.CONFIDENCE] 275 detectors_list.append((argument, help_info, impact, confidence)) 276 table = MyPrettyTable(["Num", "Check", "What it Detects", "Impact", "Confidence"]) 277 278 # Sort by impact, confidence, and name 279 detectors_list = sorted( 280 detectors_list, key=lambda element: (element[2], element[3], element[0]) 281 ) 282 idx = 1 283 for (argument, help_info, impact, confidence) in detectors_list: 284 table.add_row([str(idx), argument, help_info, classification_txt[impact], confidence]) 285 idx = idx + 1 286 print(table)
def
output_detectors_json( detector_classes: List[Type[slither.detectors.abstract_detector.AbstractDetector]]) -> List[Dict]:
290def output_detectors_json( 291 detector_classes: List[Type[AbstractDetector]], 292) -> List[Dict]: 293 detectors_list = [] 294 for detector in detector_classes: 295 argument = detector.ARGUMENT 296 # dont show the backdoor example 297 if argument == "backdoor": 298 continue 299 help_info = detector.HELP 300 impact = detector.IMPACT 301 confidence = classification_txt[detector.CONFIDENCE] 302 wiki_url = detector.WIKI 303 wiki_description = detector.WIKI_DESCRIPTION 304 wiki_exploit_scenario = detector.WIKI_EXPLOIT_SCENARIO 305 wiki_recommendation = detector.WIKI_RECOMMENDATION 306 detectors_list.append( 307 ( 308 argument, 309 help_info, 310 impact, 311 confidence, 312 wiki_url, 313 wiki_description, 314 wiki_exploit_scenario, 315 wiki_recommendation, 316 ) 317 ) 318 319 # Sort by impact, confidence, and name 320 detectors_list = sorted( 321 detectors_list, key=lambda element: (element[2], element[3], element[0]) 322 ) 323 idx = 1 324 table = [] 325 for ( 326 argument, 327 help_info, 328 impact, 329 confidence, 330 wiki_url, 331 description, 332 exploit, 333 recommendation, 334 ) in detectors_list: 335 table.append( 336 { 337 "index": idx, 338 "check": argument, 339 "title": help_info, 340 "impact": classification_txt[impact], 341 "confidence": confidence, 342 "wiki_url": wiki_url, 343 "description": description, 344 "exploit_scenario": exploit, 345 "recommendation": recommendation, 346 } 347 ) 348 idx = idx + 1 349 return table
def
output_printers( printer_classes: List[Type[slither.printers.abstract_printer.AbstractPrinter]]) -> None:
352def output_printers(printer_classes: List[Type[AbstractPrinter]]) -> None: 353 printers_list = [] 354 for printer in printer_classes: 355 argument = printer.ARGUMENT 356 help_info = printer.HELP 357 printers_list.append((argument, help_info)) 358 table = MyPrettyTable(["Num", "Printer", "What it Does"]) 359 360 # Sort by impact, confidence, and name 361 printers_list = sorted(printers_list, key=lambda element: (element[0])) 362 idx = 1 363 for (argument, help_info) in printers_list: 364 # Clean multi line HELP info 365 table.add_row([str(idx), argument, " ".join(x.strip() for x in help_info.splitlines())]) 366 idx = idx + 1 367 368 print(table)
def
output_printers_json( printer_classes: List[Type[slither.printers.abstract_printer.AbstractPrinter]]) -> List[Dict]:
371def output_printers_json(printer_classes: List[Type[AbstractPrinter]]) -> List[Dict]: 372 printers_list = [] 373 for printer in printer_classes: 374 argument = printer.ARGUMENT 375 help_info = printer.HELP 376 377 printers_list.append((argument, help_info)) 378 379 # Sort by name 380 printers_list = sorted(printers_list, key=lambda element: (element[0])) 381 idx = 1 382 table = [] 383 for (argument, help_info) in printers_list: 384 table.append({"index": idx, "check": argument, "title": help_info}) 385 idx = idx + 1 386 return table
def
check_and_sanitize_markdown_root(markdown_root: str) -> str:
389def check_and_sanitize_markdown_root(markdown_root: str) -> str: 390 # Regex to check whether the markdown_root is a GitHub URL 391 match = re.search( 392 r"(https://)github.com/([a-zA-Z-]+)([:/][A-Za-z0-9_.-]+[:/]?)([A-Za-z0-9_.-]*)(.*)", 393 markdown_root, 394 ) 395 if match: 396 if markdown_root[-1] != "/": 397 logger.warning("Appending '/' in markdown_root url for better code referencing") 398 markdown_root = markdown_root + "/" 399 400 if not match.group(4): 401 logger.warning( 402 "Appending 'master/tree/' in markdown_root url for better code referencing" 403 ) 404 markdown_root = markdown_root + "master/tree/" 405 elif match.group(4) == "tree": 406 logger.warning( 407 "Replacing 'tree' with 'blob' in markdown_root url for better code referencing" 408 ) 409 positions = match.span(4) 410 markdown_root = f"{markdown_root[:positions[0]]}blob{markdown_root[positions[1]:]}" 411 412 return markdown_root