def tweak_severity(tool_name, issue_dict): """ Tweak severity for certain tools. TODO: Remove this method somehow since this has to be done by issue.py :param tool_name: :param issue_dict: :return: """ rule_id = issue_dict["test_id"] rule_name = issue_dict["test_name"] issue_severity = issue_dict["issue_severity"] if tool_name in [ "staticcheck", "psalm", "phpstan", "source-js", "source-php", "audit-php", ]: if issue_severity in ["HIGH", "CRITICAL"]: return "MEDIUM" return "LOW" if tool_name in [ "checkov", "source-tf", "source-yaml", "source-serverless", "source-arm", "source-aws", "source-k8s", "source-dockerfile", ]: cis_rule = cis.get_rule(rule_id) if not cis_rule: cis_rule = cis.get_rule(rule_name) if cis_rule: return "CRITICAL" if cis_rule.get("scored") else "HIGH" return issue_severity
def get_help( rule_id, rule_obj=None, tool_name=None, owasp_category=None, cwe_category=None ): """ Method to find remediation text for the given rule, tool and categories :param rule_id: Rule id :param rule_obj: Rule object from the SARIF file :param tool_name: Full name of the tool :param owasp_category: OWASP category :param cwe_category: CWE category :return: Help text in markdown format """ desc = "" if rules_message_map.get(rule_id): return rules_message_map.get(rule_id) cis_rule = get_rule(rule_id) if cis_rule: cis_desc = cis_rule.get("text", "").strip() if cis_desc and not cis_desc.endswith("."): cis_desc = cis_desc + "." rem_text = cis_rule.get( "remediation", f"Refer to the provider documentation for the configuration options available.{IAC_LINKS}", ) rationale_text = cis_rule.get("rationale", "") if rationale_text: rationale_text += "\n" desc = f"""CIS Benchmark: **{cis_rule.get("id", "")}**\n\n{cis_desc}\n\n{rationale_text}## Remediation\n\n{rem_text}""" if cis_rule.get("help_url"): help_urls = "\n- ".join(cis_rule.get("help_url")) desc = desc + f"""\n\n## Additional information\n\n- {help_urls}""" return desc else: desc = rule_obj.get("fullDescription", {}).get("text") if desc: desc = desc.replace("'", "`") helpUri = rule_obj.get("helpUri") if helpUri and "slscan" not in helpUri: desc += "\n\n## Additional information\n\n" if rule_obj.get("name"): desc += f"""**[{rule_obj.get("name")}]({helpUri})**""" else: desc += f"**[{rule_id}]({helpUri})**" if "CKV_" in rule_id: desc += IAC_LINKS return desc
def convert_sarif(app_name, repo_context, sarif_files, findings_fname): """ Method to convert sarif to findings json :param app_name: Application name :param sarif_file: :param findings_fname: :return: """ finding_id = 1 findings_list = [] rule_id_owasp_cache = {} for sf in sarif_files: with open(sf, mode="r") as report_file: report_data = None try: report_data = json.loads(report_file.read()) # skip this file if the data is empty if not report_data or not report_data.get("runs"): continue # Iterate through all the runs for run in report_data["runs"]: results = run.get("results") if not results: continue tool_name = run.get("tool", {}).get("driver", {}).get("name") rules = { r["id"]: r for r in run.get("tool", {}).get("driver", {}).get("rules") if r and r.get("id") } for result in results: rule_id = result.get("ruleId", "") rule = rules.get(rule_id) if not rule: continue owasp_category = rule_id_owasp_cache.get(rule_id, "") if not owasp_category: # Check the config for any available owasp category mapping for rok, rov in config.get("rules_owasp_category").items(): if ( rok.upper() == rule_id.upper() or rok.upper() in rule_id.upper() ): rule_id_owasp_cache[rule_id] = rov owasp_category = rov category = rule.get("name") if not category: category = rule_id desc = get_help( rule_id, rule_obj=rule, tool_name=tool_name, owasp_category=owasp_category, ) short_desc = rule.get("shortDescription", {}).get("text") if not short_desc: short_desc = result.get("message", {}).get("text") ngsev = convert_severity( result.get("properties", {})["issue_severity"] ) # Populate tags tags = [] if "CWE" in rule_id: tags.append( { "key": "cwe_category", "value": rule_id.replace("CWE-", ""), "shiftleft_managed": True, } ) if "CKV_" in rule_id or "CIS_" in rule_id or "AWS" in rule_id: cis_rule = cis.get_rule(rule_id) if cis_rule: tags.append( { "key": "cis_category", "value": cis_rule.get("id", ""), "shiftleft_managed": False, } ) if cis_rule.get("scored"): tags.append( { "key": "cis_status", "value": "SCORED", "shiftleft_managed": False, } ) for location in result.get("locations"): filename = location["physicalLocation"]["artifactLocation"][ "uri" ] lineno = location.get("physicalLocation", {})["region"][ "startLine" ] end_lineno = location.get("physicalLocation", {})[ "contextRegion" ]["endLine"] finding = { "app": app_name, "type": "extscan", "title": result.get("message", {})["text"], "description": desc, "internal_id": "{}/{}".format( rule_id, utils.calculate_line_hash( filename, lineno, end_lineno, location.get("physicalLocation", {})["region"][ "snippet" ]["text"], short_desc, ), ), "severity": ngsev, "owasp_category": owasp_category, "category": category, "details": { "repoContext": repo_context, "name": result.get("message", {})["text"], "tags": ",".join(rule["properties"]["tags"]), "fileName": filename, "DATA_TYPE": "OSS_SCAN", "lineNumber": lineno, "ruleId": rule_id, "ruleName": rule.get("name"), "contextText": location.get("physicalLocation", {})[ "region" ]["snippet"]["text"], "snippetText": location.get("physicalLocation", {})[ "contextRegion" ]["snippet"]["text"], }, "tags": tags, } findings_list.append(finding) finding_id = finding_id + 1 except Exception as e: LOG.debug(e) continue with open(findings_fname, mode="w") as out_file: json.dump({"findings": findings_list}, out_file)
def test_k8s_rule(): data = get_rule("DefaultServiceAccount") assert data
def test_aws_rule(): data = get_rule("SecurityGroupUnrestrictedIngress22") assert data