| 37 | } |
| 38 | |
| 39 | picojson::array SarifReport::serializeRules() const |
| 40 | { |
| 41 | picojson::array ret; |
| 42 | std::set<std::string> ruleIds; |
| 43 | for (const auto& finding : mFindings) { |
| 44 | // github only supports findings with locations |
| 45 | if (finding.callStack.empty()) |
| 46 | continue; |
| 47 | if (ruleIds.insert(finding.id).second) { |
| 48 | // setting name and description to empty strings will make github default |
| 49 | // to the instance specific violation message and not rule description, |
| 50 | // this makes it so not all the violations have the same description. |
| 51 | picojson::object rule; |
| 52 | rule["id"] = picojson::value(finding.id); |
| 53 | // rule.name |
| 54 | rule["name"] = picojson::value(""); |
| 55 | // rule.shortDescription.text |
| 56 | picojson::object shortDescription; |
| 57 | shortDescription["text"] = picojson::value(""); |
| 58 | rule["shortDescription"] = picojson::value(shortDescription); |
| 59 | // rule.fullDescription.text |
| 60 | picojson::object fullDescription; |
| 61 | fullDescription["text"] = picojson::value(""); |
| 62 | rule["fullDescription"] = picojson::value(fullDescription); |
| 63 | // rule.help.text |
| 64 | picojson::object help; |
| 65 | help["text"] = picojson::value(""); |
| 66 | rule["help"] = picojson::value(help); |
| 67 | // rule.properties.precision, rule.properties.problem.severity |
| 68 | picojson::object properties; |
| 69 | properties["precision"] = picojson::value(sarifPrecision(finding)); |
| 70 | // rule.properties.security-severity, rule.properties.tags |
| 71 | picojson::array tags; |
| 72 | |
| 73 | // If we have a CWE ID, treat it as security-related (CWE is the authoritative source for security weaknesses) |
| 74 | if (finding.cwe.id > 0) { |
| 75 | double securitySeverity = 0; |
| 76 | if (finding.severity == Severity::error && !ErrorLogger::isCriticalErrorId(finding.id)) { |
| 77 | securitySeverity = 9.9; // critical = 9.0+ |
| 78 | } |
| 79 | else if (finding.severity == Severity::warning) { |
| 80 | securitySeverity = 8.5; // high = 7.0 to 8.9 |
| 81 | } |
| 82 | else if (finding.severity == Severity::performance || finding.severity == Severity::portability || |
| 83 | finding.severity == Severity::style) { |
| 84 | securitySeverity = 5.5; // medium = 4.0 to 6.9 |
| 85 | } |
| 86 | else if (finding.severity == Severity::information || finding.severity == Severity::internal || |
| 87 | finding.severity == Severity::debug || finding.severity == Severity::none) { |
| 88 | securitySeverity = 2.0; // low = 0.1 to 3.9 |
| 89 | } |
| 90 | if (securitySeverity > 0.0) { |
| 91 | std::ostringstream ss; |
| 92 | ss << securitySeverity; |
| 93 | properties["security-severity"] = picojson::value(ss.str()); |
| 94 | tags.emplace_back("external/cwe/cwe-" + std::to_string(finding.cwe.id)); |
| 95 | tags.emplace_back("security"); |
| 96 | } |
nothing calls this directly
no test coverage detected