@mitre/hdf-converters 3.4.2 → 3.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.ts +50 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +344 -42
- package/dist/index.js.map +1 -1
- package/dist/register-all-WRR-vAZf.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { n as detectConverter, t as registerAllFingerprints } from "./register-a
|
|
|
2
2
|
import { flattenOverlays } from "@mitre/hdf-parsers";
|
|
3
3
|
import { buildCsv, buildXml, cvssScoreToSeverity, formatTimestamp, formatTimestampSeconds, impactToSeverity, normalizeHdfTimestamps, parseCsv, parseJSON, parsePurl, parseTimestamp, parseXml, parseXmlWithArrays, severityToImpact, sha256, stripHtml as stripHTML, trimUtcFraction } from "@mitre/hdf-utilities";
|
|
4
4
|
import { Applicability, AuthorizationStatus, CVSSSeverity, CategorizationLevel, ControlType, Ecosystem, EvidenceType, HashAlgorithm, IdentityType, Justification, MilestoneStatus, OverrideType, PlanType, ResultStatus, TargetType, VerificationMethodEnum, Version, createDescription, createMinimalBaseline, createRequirement, createResult, severityToImpact as severityToImpact$1 } from "@mitre/hdf-schema";
|
|
5
|
-
import { DEFAULT_COMPONENT_MANAGEMENT_NIST_TAGS, DEFAULT_REMEDIATION_NIST_TAGS, DEFAULT_STATIC_ANALYSIS_NIST_TAGS, DEFAULT_STATIC_ANALYSIS_NIST_TAGS as DEFAULT_STATIC_ANALYSIS_NIST_TAGS$1, awsConfigMappedRevisions, getAwsConfigNistControlByIdentifier, getAwsConfigNistControlByName, getAwsConfigNistControlsBySubstring, getCCINistMappings, getCurrentNistRevision, getCweNistControl, getNessusNistControl, getNiktoNistControl, getOwaspNistControl, getScoutsuiteNistControl, isNistStrict, nistToCci } from "@mitre/hdf-mappings";
|
|
5
|
+
import { DEFAULT_COMPONENT_MANAGEMENT_NIST_TAGS, DEFAULT_CONFIG_MANAGEMENT_NIST_TAGS, DEFAULT_REMEDIATION_NIST_TAGS, DEFAULT_STATIC_ANALYSIS_NIST_TAGS, DEFAULT_STATIC_ANALYSIS_NIST_TAGS as DEFAULT_STATIC_ANALYSIS_NIST_TAGS$1, awsConfigMappedRevisions, getAwsConfigNistControlByIdentifier, getAwsConfigNistControlByName, getAwsConfigNistControlsBySubstring, getCCINistMappings, getCurrentNistRevision, getCweNistControl, getHipcheckNistControls, getNessusNistControl, getNiktoNistControl, getOwaspNistControl, getScoutsuiteNistControl, isNistStrict, nistToCci } from "@mitre/hdf-mappings";
|
|
6
6
|
//#region shared/typescript/converterutil.ts
|
|
7
7
|
/**
|
|
8
8
|
* Shared utilities for TypeScript HDF converters.
|
|
@@ -753,30 +753,6 @@ function convertProfile(v1Profile) {
|
|
|
753
753
|
if (v1Profile.depends?.length) v2Baseline.depends = v1Profile.depends.map(convertDependency);
|
|
754
754
|
return v2Baseline;
|
|
755
755
|
}
|
|
756
|
-
/**
|
|
757
|
-
* Convert HDF v1.0 results to v2.0 format.
|
|
758
|
-
*
|
|
759
|
-
* Performs comprehensive transformation at all levels:
|
|
760
|
-
* - Top-level: version removed, profiles → baselines, platform → components
|
|
761
|
-
* - Baselines: sha256 → checksum, controls → requirements, field renaming
|
|
762
|
-
* - Requirements: snake_case → camelCase, status → effectiveStatus
|
|
763
|
-
* - Results: snake_case → camelCase for all fields
|
|
764
|
-
*
|
|
765
|
-
* @param v1Data - HDF v1.0 results object
|
|
766
|
-
* @returns HDF v2.0 results object
|
|
767
|
-
*
|
|
768
|
-
* @example
|
|
769
|
-
* ```typescript
|
|
770
|
-
* const v1 = {
|
|
771
|
-
* version: "1.0.0",
|
|
772
|
-
* platform: { name: "ubuntu", release: "20.04" },
|
|
773
|
-
* profiles: [...],
|
|
774
|
-
* statistics: {...}
|
|
775
|
-
* };
|
|
776
|
-
* const v2 = convertV1ToV2(v1);
|
|
777
|
-
* // v2 = { baselines: [...], components: [{...}], statistics: {...} }
|
|
778
|
-
* ```
|
|
779
|
-
*/
|
|
780
756
|
function convertV1ToV2(v1Data) {
|
|
781
757
|
validateInputSize(JSON.stringify(v1Data), "legacyhdf-to-hdf");
|
|
782
758
|
const v2 = {
|
|
@@ -973,7 +949,7 @@ function controlId(f) {
|
|
|
973
949
|
* the shared awsconfig mapping, falling back to the static analysis default
|
|
974
950
|
* bundle (matching the SAF CLI) when no config rule applies.
|
|
975
951
|
*/
|
|
976
|
-
function nistTags(group) {
|
|
952
|
+
function nistTags$1(group) {
|
|
977
953
|
if (group.length > 0 && productOf(group[0]) === "trivy" && trivyCVE(group[0])) return DEFAULT_REMEDIATION_NIST_TAGS$1;
|
|
978
954
|
const out = [];
|
|
979
955
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -981,10 +957,15 @@ function nistTags(group) {
|
|
|
981
957
|
seen.add(tag);
|
|
982
958
|
out.push(tag);
|
|
983
959
|
}
|
|
984
|
-
|
|
960
|
+
if (out.length > 0) return out;
|
|
961
|
+
if (group.length > 0 && isConfigRuleFinding(group[0])) return DEFAULT_CONFIG_MANAGEMENT_NIST_TAGS;
|
|
962
|
+
return DEFAULT_STATIC_ANALYSIS_NIST_TAGS;
|
|
963
|
+
}
|
|
964
|
+
function isConfigRuleFinding(f) {
|
|
965
|
+
return f.ProductFields?.["RelatedAWSResources:0/type"] === "AWS::Config::ConfigRule";
|
|
985
966
|
}
|
|
986
967
|
function configRuleNist(f) {
|
|
987
|
-
if (f
|
|
968
|
+
if (!isConfigRuleFinding(f)) return [];
|
|
988
969
|
const name = f.ProductFields?.["RelatedAWSResources:0/name"];
|
|
989
970
|
if (!name) return [];
|
|
990
971
|
return getAwsConfigNistControlsBySubstring(name);
|
|
@@ -1093,7 +1074,7 @@ function buildRequirement$17(id, group) {
|
|
|
1093
1074
|
label: "fix",
|
|
1094
1075
|
data: fix
|
|
1095
1076
|
});
|
|
1096
|
-
const nist = nistTags(group);
|
|
1077
|
+
const nist = nistTags$1(group);
|
|
1097
1078
|
const tags = nist.length > 0 ? buildNistCciTags(nist, nistToCci(nist)) : {};
|
|
1098
1079
|
const results = group.map(buildResult$2);
|
|
1099
1080
|
const req = createRequirement(id, primary.Title ?? "", descriptions, impact, results, { tags });
|
|
@@ -1252,7 +1233,7 @@ function convertResultGroup(ruleId, rule, sarifResults) {
|
|
|
1252
1233
|
const sourceLocation = firstResult.locations && firstResult.locations.length > 0 ? extractSourceLocation$1(firstResult.locations[0]) : void 0;
|
|
1253
1234
|
const results = [];
|
|
1254
1235
|
for (const sr of sarifResults) results.push(...convertSarifResultToHDFResults(sr));
|
|
1255
|
-
const descriptions = buildDescriptions$
|
|
1236
|
+
const descriptions = buildDescriptions$2(description, rule, firstResult);
|
|
1256
1237
|
const options = { tags: buildTags$3(firstResult, rule, ruleLevel, cweIds, nistControls, cciControls) };
|
|
1257
1238
|
if (sourceLocation) options.sourceLocation = sourceLocation;
|
|
1258
1239
|
const req = createRequirement(ruleId, title, descriptions, impact, results, options);
|
|
@@ -1429,7 +1410,7 @@ function extractBacktrace(codeFlows) {
|
|
|
1429
1410
|
}
|
|
1430
1411
|
return backtrace;
|
|
1431
1412
|
}
|
|
1432
|
-
function buildDescriptions$
|
|
1413
|
+
function buildDescriptions$2(defaultDesc, rule, result) {
|
|
1433
1414
|
const descriptions = [createDescription("default", defaultDesc)];
|
|
1434
1415
|
if (rule) {
|
|
1435
1416
|
if (rule.fullDescription?.text) descriptions.push(createDescription("rationale", rule.fullDescription.text));
|
|
@@ -3021,7 +3002,7 @@ function extractCwe(raw) {
|
|
|
3021
3002
|
const out = raw.filter((c) => CWE_ID_PATTERN.test(c));
|
|
3022
3003
|
return out.length === 0 ? void 0 : out;
|
|
3023
3004
|
}
|
|
3024
|
-
function buildEpss$
|
|
3005
|
+
function buildEpss$2(entries) {
|
|
3025
3006
|
if (!entries || entries.length === 0) return void 0;
|
|
3026
3007
|
const e = entries[0];
|
|
3027
3008
|
if (!e.date) return void 0;
|
|
@@ -3039,7 +3020,7 @@ function buildKev(k) {
|
|
|
3039
3020
|
if (k.notes) out.notes = k.notes;
|
|
3040
3021
|
return out;
|
|
3041
3022
|
}
|
|
3042
|
-
function convertMatchToRequirement(match, isIgnored) {
|
|
3023
|
+
function convertMatchToRequirement(match, isIgnored, targetName, startTime) {
|
|
3043
3024
|
const vuln = match.vulnerability;
|
|
3044
3025
|
const cveId = vuln.id;
|
|
3045
3026
|
const severity = vuln.severity;
|
|
@@ -3062,11 +3043,12 @@ function convertMatchToRequirement(match, isIgnored) {
|
|
|
3062
3043
|
status,
|
|
3063
3044
|
codeDesc: buildCodeDesc$8(match),
|
|
3064
3045
|
message,
|
|
3065
|
-
startTime
|
|
3046
|
+
startTime
|
|
3066
3047
|
};
|
|
3067
3048
|
const tags = buildNistCciTags(DEFAULT_STATIC_ANALYSIS_NIST_TAGS, nistToCci(DEFAULT_STATIC_ANALYSIS_NIST_TAGS));
|
|
3068
3049
|
const requirement = {
|
|
3069
3050
|
id: isIgnored ? `Grype-Ignored-Match/${cveId}` : `Grype/${cveId}`,
|
|
3051
|
+
title: `Grype found a vulnerability to ${cveId} in ${targetName}`,
|
|
3070
3052
|
impact,
|
|
3071
3053
|
results: [result],
|
|
3072
3054
|
tags,
|
|
@@ -3094,7 +3076,7 @@ function convertMatchToRequirement(match, isIgnored) {
|
|
|
3094
3076
|
requirement.affectedPackages = buildAffectedPackages(match);
|
|
3095
3077
|
const cwe = extractCwe(vuln.cwe);
|
|
3096
3078
|
if (cwe) requirement.cwe = cwe;
|
|
3097
|
-
const epss = buildEpss$
|
|
3079
|
+
const epss = buildEpss$2(vuln.epss);
|
|
3098
3080
|
if (epss) requirement.epss = epss;
|
|
3099
3081
|
const kev = buildKev(vuln.kev);
|
|
3100
3082
|
if (kev) requirement.kev = kev;
|
|
@@ -3105,19 +3087,21 @@ async function convertGrypeToHdf(input, converterVersion = "1.0.0") {
|
|
|
3105
3087
|
const resultsChecksum = await inputChecksum(input);
|
|
3106
3088
|
const grypeData = parseJSON(input);
|
|
3107
3089
|
const requirements = [];
|
|
3090
|
+
const targetName = grypeData.source?.target?.userInput || "Grype Scan";
|
|
3091
|
+
const scanTime = grypeData.descriptor?.timestamp ? parseTimestamp(grypeData.descriptor.timestamp) : null;
|
|
3092
|
+
const resultStart = scanTime ?? /* @__PURE__ */ new Date("0001-01-01T00:00:00Z");
|
|
3108
3093
|
if (grypeData.matches && grypeData.matches.length > 0) {
|
|
3109
3094
|
const { items: limitedMatches, truncated: truncatedMatches } = limitArray(grypeData.matches);
|
|
3110
3095
|
/* v8 ignore next -- truncation only triggers with >100K items */
|
|
3111
3096
|
if (truncatedMatches) console.warn(`WARNING: Input truncated at ${limitedMatches.length} match items (original: ${grypeData.matches.length})`);
|
|
3112
|
-
for (const match of limitedMatches) requirements.push(convertMatchToRequirement(match, false));
|
|
3097
|
+
for (const match of limitedMatches) requirements.push(convertMatchToRequirement(match, false, targetName, resultStart));
|
|
3113
3098
|
}
|
|
3114
3099
|
if (grypeData.ignoredMatches && grypeData.ignoredMatches.length > 0) {
|
|
3115
3100
|
const { items: limitedIgnored, truncated: truncatedIgnored } = limitArray(grypeData.ignoredMatches);
|
|
3116
3101
|
/* v8 ignore next -- truncation only triggers with >100K items */
|
|
3117
3102
|
if (truncatedIgnored) console.warn(`WARNING: Input truncated at ${limitedIgnored.length} ignoredMatch items (original: ${grypeData.ignoredMatches.length})`);
|
|
3118
|
-
for (const match of limitedIgnored) requirements.push(convertMatchToRequirement(match, true));
|
|
3103
|
+
for (const match of limitedIgnored) requirements.push(convertMatchToRequirement(match, true, targetName, resultStart));
|
|
3119
3104
|
}
|
|
3120
|
-
const targetName = grypeData.source?.target?.userInput || "Grype Scan";
|
|
3121
3105
|
if (requirements.length === 0) requirements.push(buildNoFindingsRequirement("grype-no-findings", `Grype scanned ${targetName} and reported zero vulnerable components.`, /* @__PURE__ */ new Date()));
|
|
3122
3106
|
const baseline = createMinimalBaseline(targetName, requirements, { resultsChecksum });
|
|
3123
3107
|
return buildHdfResults({
|
|
@@ -3130,7 +3114,190 @@ async function convertGrypeToHdf(input, converterVersion = "1.0.0") {
|
|
|
3130
3114
|
type: TargetType.Artifact,
|
|
3131
3115
|
name: targetName
|
|
3132
3116
|
}],
|
|
3133
|
-
timestamp:
|
|
3117
|
+
timestamp: scanTime ?? void 0
|
|
3118
|
+
});
|
|
3119
|
+
}
|
|
3120
|
+
//#endregion
|
|
3121
|
+
//#region converters/defectdojo-to-hdf/typescript/converter.ts
|
|
3122
|
+
function deriveStatus(f) {
|
|
3123
|
+
if (f.out_of_scope) return ResultStatus.NotApplicable;
|
|
3124
|
+
if (f.false_p) return ResultStatus.Failed;
|
|
3125
|
+
if (f.risk_accepted) return ResultStatus.Failed;
|
|
3126
|
+
if (f.is_mitigated) return ResultStatus.Passed;
|
|
3127
|
+
if (f.under_review) return ResultStatus.NotReviewed;
|
|
3128
|
+
return ResultStatus.Failed;
|
|
3129
|
+
}
|
|
3130
|
+
function triageTags(f) {
|
|
3131
|
+
return {
|
|
3132
|
+
"defectdojo/active": f.active ?? false,
|
|
3133
|
+
"defectdojo/verified": f.verified ?? false,
|
|
3134
|
+
"defectdojo/false_p": f.false_p ?? false,
|
|
3135
|
+
"defectdojo/is_mitigated": f.is_mitigated ?? false,
|
|
3136
|
+
"defectdojo/risk_accepted": f.risk_accepted ?? false,
|
|
3137
|
+
"defectdojo/out_of_scope": f.out_of_scope ?? false,
|
|
3138
|
+
"defectdojo/under_review": f.under_review ?? false
|
|
3139
|
+
};
|
|
3140
|
+
}
|
|
3141
|
+
function riskAcceptanceOwner(ar) {
|
|
3142
|
+
if (ar.owner_email) return {
|
|
3143
|
+
type: IdentityType.Email,
|
|
3144
|
+
identifier: ar.owner_email
|
|
3145
|
+
};
|
|
3146
|
+
if (ar.owner_username) return {
|
|
3147
|
+
type: IdentityType.Username,
|
|
3148
|
+
identifier: ar.owner_username
|
|
3149
|
+
};
|
|
3150
|
+
if (ar.owner !== void 0 && ar.owner !== null && `${ar.owner}` !== "") return {
|
|
3151
|
+
type: IdentityType.Simple,
|
|
3152
|
+
identifier: `defectdojo-user-${ar.owner}`
|
|
3153
|
+
};
|
|
3154
|
+
return {
|
|
3155
|
+
type: IdentityType.Simple,
|
|
3156
|
+
identifier: "defectdojo-risk-acceptance-owner"
|
|
3157
|
+
};
|
|
3158
|
+
}
|
|
3159
|
+
function buildWaiverOverride(ar) {
|
|
3160
|
+
let reason = ar.decision_details || ar.name || "";
|
|
3161
|
+
if (!reason) reason = "Risk accepted in DefectDojo";
|
|
3162
|
+
const appliedAt = (ar.created ? parseTimestamp(ar.created) : null) ?? /* @__PURE__ */ new Date();
|
|
3163
|
+
const oneYearOut = /* @__PURE__ */ new Date();
|
|
3164
|
+
oneYearOut.setTime(appliedAt.getTime());
|
|
3165
|
+
oneYearOut.setFullYear(oneYearOut.getFullYear() + 1);
|
|
3166
|
+
const expiresAt = (ar.expiration_date ? parseTimestamp(ar.expiration_date) : null) ?? oneYearOut;
|
|
3167
|
+
return {
|
|
3168
|
+
type: OverrideType.Waiver,
|
|
3169
|
+
status: ResultStatus.Passed,
|
|
3170
|
+
reason,
|
|
3171
|
+
appliedBy: riskAcceptanceOwner(ar),
|
|
3172
|
+
appliedAt,
|
|
3173
|
+
expiresAt
|
|
3174
|
+
};
|
|
3175
|
+
}
|
|
3176
|
+
function findingId(f) {
|
|
3177
|
+
return f.unique_id_from_tool || f.vuln_id_from_tool || `DefectDojo-Finding-${f.id}`;
|
|
3178
|
+
}
|
|
3179
|
+
function cveList(f) {
|
|
3180
|
+
return (f.vulnerability_ids ?? []).map((v) => v.vulnerability_id).filter(Boolean);
|
|
3181
|
+
}
|
|
3182
|
+
function cvssBand(score) {
|
|
3183
|
+
switch (cvssScoreToSeverity(score)) {
|
|
3184
|
+
case "critical": return CVSSSeverity.Critical;
|
|
3185
|
+
case "high": return CVSSSeverity.High;
|
|
3186
|
+
case "medium": return CVSSSeverity.Medium;
|
|
3187
|
+
case "low": return CVSSSeverity.Low;
|
|
3188
|
+
default: return CVSSSeverity.None;
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
function buildCvss$1(f) {
|
|
3192
|
+
const out = [];
|
|
3193
|
+
const add = (version, vector, score) => {
|
|
3194
|
+
if ((score === void 0 || score === null) && !vector) return;
|
|
3195
|
+
const entry = { version };
|
|
3196
|
+
if (score !== void 0 && score !== null) {
|
|
3197
|
+
entry.baseScore = score;
|
|
3198
|
+
entry.baseSeverity = cvssBand(score);
|
|
3199
|
+
}
|
|
3200
|
+
if (vector) entry.baseVector = vector;
|
|
3201
|
+
out.push(entry);
|
|
3202
|
+
};
|
|
3203
|
+
add(Version.The31, f.cvssv3, f.cvssv3_score);
|
|
3204
|
+
add(Version.The40, f.cvssv4, f.cvssv4_score);
|
|
3205
|
+
return out;
|
|
3206
|
+
}
|
|
3207
|
+
function buildEpss$1(f) {
|
|
3208
|
+
if (f.epss_score === void 0 || f.epss_score === null || !f.date) return void 0;
|
|
3209
|
+
return {
|
|
3210
|
+
score: f.epss_score,
|
|
3211
|
+
percentile: f.epss_percentile ?? 0,
|
|
3212
|
+
date: f.date
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3215
|
+
function nistTags(f) {
|
|
3216
|
+
return f.cwe && f.cwe > 0 ? mapCWEToNIST([`CWE-${f.cwe}`], DEFAULT_STATIC_ANALYSIS_NIST_TAGS) : DEFAULT_STATIC_ANALYSIS_NIST_TAGS;
|
|
3217
|
+
}
|
|
3218
|
+
function buildDescriptions$1(f) {
|
|
3219
|
+
const descs = [{
|
|
3220
|
+
label: "default",
|
|
3221
|
+
data: f.description || f.title || "No description provided."
|
|
3222
|
+
}];
|
|
3223
|
+
if (f.mitigation) descs.push({
|
|
3224
|
+
label: "fix",
|
|
3225
|
+
data: f.mitigation
|
|
3226
|
+
});
|
|
3227
|
+
if (f.impact) descs.push({
|
|
3228
|
+
label: "impact",
|
|
3229
|
+
data: f.impact
|
|
3230
|
+
});
|
|
3231
|
+
return descs;
|
|
3232
|
+
}
|
|
3233
|
+
function codeDesc(f) {
|
|
3234
|
+
const parts = [f.title];
|
|
3235
|
+
if (f.component_name) parts.push(`Component: ${f.component_name}${f.component_version ? "@" + f.component_version : ""}`);
|
|
3236
|
+
if (f.file_path) parts.push(`Location: ${f.file_path}${f.line !== void 0 && f.line !== null ? ":" + f.line : ""}`);
|
|
3237
|
+
const cves = cveList(f);
|
|
3238
|
+
if (cves.length > 0) parts.push(`CVE: ${cves.join(", ")}`);
|
|
3239
|
+
return parts.join(" | ");
|
|
3240
|
+
}
|
|
3241
|
+
function convertFinding(f) {
|
|
3242
|
+
const nist = nistTags(f);
|
|
3243
|
+
const tags = buildNistCciTags(nist, nistToCci(nist), triageTags(f));
|
|
3244
|
+
const result = {
|
|
3245
|
+
status: deriveStatus(f),
|
|
3246
|
+
codeDesc: codeDesc(f),
|
|
3247
|
+
startTime: (f.date ? parseTimestamp(f.date) : null) ?? /* @__PURE__ */ new Date()
|
|
3248
|
+
};
|
|
3249
|
+
const req = {
|
|
3250
|
+
id: findingId(f),
|
|
3251
|
+
impact: severityToImpact(f.severity),
|
|
3252
|
+
results: [result],
|
|
3253
|
+
tags,
|
|
3254
|
+
descriptions: buildDescriptions$1(f)
|
|
3255
|
+
};
|
|
3256
|
+
const controlType = deriveControlTypeFromTags(nist);
|
|
3257
|
+
if (controlType !== void 0) req.controlType = controlType;
|
|
3258
|
+
const cvss = buildCvss$1(f);
|
|
3259
|
+
if (cvss.length > 0) req.cvss = cvss;
|
|
3260
|
+
const epss = buildEpss$1(f);
|
|
3261
|
+
if (epss) req.epss = epss;
|
|
3262
|
+
if (f.cwe && f.cwe > 0) req.cwe = [`CWE-${f.cwe}`];
|
|
3263
|
+
const firstRisk = f.accepted_risks?.[0];
|
|
3264
|
+
if (f.risk_accepted && firstRisk) {
|
|
3265
|
+
req.statusOverrides = [buildWaiverOverride(firstRisk)];
|
|
3266
|
+
req.effectiveStatus = ResultStatus.Passed;
|
|
3267
|
+
req.disposition = OverrideType.Waiver;
|
|
3268
|
+
tags["defectdojo/decision"] = firstRisk.decision ?? "";
|
|
3269
|
+
}
|
|
3270
|
+
return req;
|
|
3271
|
+
}
|
|
3272
|
+
function scannerName(f) {
|
|
3273
|
+
return f.related_fields?.test?.test_type?.name || "DefectDojo";
|
|
3274
|
+
}
|
|
3275
|
+
async function convertDefectDojoToHdf(input, converterVersion = "0.1.0") {
|
|
3276
|
+
validateInputSize(input, "defectdojo");
|
|
3277
|
+
const resultsChecksum = await inputChecksum(input);
|
|
3278
|
+
const parsed = parseJSON(input);
|
|
3279
|
+
const findings = Array.isArray(parsed) ? parsed : parsed.results ?? [];
|
|
3280
|
+
const order = [];
|
|
3281
|
+
const byScanner = /* @__PURE__ */ new Map();
|
|
3282
|
+
for (const f of findings) {
|
|
3283
|
+
const name = scannerName(f);
|
|
3284
|
+
if (!byScanner.has(name)) {
|
|
3285
|
+
order.push(name);
|
|
3286
|
+
byScanner.set(name, []);
|
|
3287
|
+
}
|
|
3288
|
+
byScanner.get(name).push(convertFinding(f));
|
|
3289
|
+
}
|
|
3290
|
+
const baselines = order.map((name) => {
|
|
3291
|
+
const baseline = createMinimalBaseline(`DefectDojo: ${name}`, byScanner.get(name), { resultsChecksum });
|
|
3292
|
+
baseline.title = name;
|
|
3293
|
+
return baseline;
|
|
3294
|
+
});
|
|
3295
|
+
if (baselines.length === 0) baselines.push(createMinimalBaseline("DefectDojo", [buildNoFindingsRequirement("defectdojo-no-findings", "DefectDojo reported zero findings.", /* @__PURE__ */ new Date())], { resultsChecksum }));
|
|
3296
|
+
return buildHdfResults({
|
|
3297
|
+
generatorName: "defectdojo-to-hdf",
|
|
3298
|
+
converterVersion,
|
|
3299
|
+
toolName: "DefectDojo",
|
|
3300
|
+
baselines
|
|
3134
3301
|
});
|
|
3135
3302
|
}
|
|
3136
3303
|
//#endregion
|
|
@@ -3920,8 +4087,9 @@ function buildNotApplicableResult(rule) {
|
|
|
3920
4087
|
});
|
|
3921
4088
|
}
|
|
3922
4089
|
function buildRequirement$15(rule) {
|
|
3923
|
-
const
|
|
3924
|
-
const
|
|
4090
|
+
const rawNist = buildNistTags$3(rule.Source.SourceIdentifier, rule.ConfigRuleName);
|
|
4091
|
+
const nist = rawNist.length > 0 ? rawNist : DEFAULT_CONFIG_MANAGEMENT_NIST_TAGS;
|
|
4092
|
+
const tags = { nist };
|
|
3925
4093
|
const descriptions = [{
|
|
3926
4094
|
label: "default",
|
|
3927
4095
|
data: rule.Description
|
|
@@ -6882,6 +7050,140 @@ async function convertTrufflehogToHdf(input, converterVersion = "1.0.0") {
|
|
|
6882
7050
|
return serializeHdf(hdf);
|
|
6883
7051
|
}
|
|
6884
7052
|
//#endregion
|
|
7053
|
+
//#region converters/hipcheck-to-hdf/typescript/converter.ts
|
|
7054
|
+
/** "owner/name" when both are present, else whichever is non-empty (never a
|
|
7055
|
+
* bare "owner/" or "/name"). */
|
|
7056
|
+
function repoIdent(r) {
|
|
7057
|
+
const owner = r.repo_owner ?? "";
|
|
7058
|
+
const name = r.repo_name ?? "";
|
|
7059
|
+
if (owner && name) return `${owner}/${name}`;
|
|
7060
|
+
return name || owner;
|
|
7061
|
+
}
|
|
7062
|
+
/** Build NIST/CCI tags for an analysis name via the hipcheck mapping. */
|
|
7063
|
+
function analysisTags(name) {
|
|
7064
|
+
const nist = getHipcheckNistControls(name);
|
|
7065
|
+
if (nist.length === 0) return {
|
|
7066
|
+
tags: buildNistCciTags([], []),
|
|
7067
|
+
nist: []
|
|
7068
|
+
};
|
|
7069
|
+
return {
|
|
7070
|
+
tags: buildNistCciTags(nist, nistToCci(nist)),
|
|
7071
|
+
nist
|
|
7072
|
+
};
|
|
7073
|
+
}
|
|
7074
|
+
function applyClassification(req, nist) {
|
|
7075
|
+
const controlType = deriveControlTypeFromTags(nist);
|
|
7076
|
+
if (controlType !== void 0) req.controlType = controlType;
|
|
7077
|
+
req.verificationMethod = VerificationMethodEnum.Automated;
|
|
7078
|
+
}
|
|
7079
|
+
function buildAnalysisRequirement(a, status, startTime) {
|
|
7080
|
+
const { tags, nist } = analysisTags(a.name);
|
|
7081
|
+
const message = a.message ?? "";
|
|
7082
|
+
const descriptions = [{
|
|
7083
|
+
label: "default",
|
|
7084
|
+
data: message
|
|
7085
|
+
}];
|
|
7086
|
+
if (a.policy_expr) descriptions.push({
|
|
7087
|
+
label: "check",
|
|
7088
|
+
data: a.policy_expr
|
|
7089
|
+
});
|
|
7090
|
+
let resultMessage = message;
|
|
7091
|
+
if (a.concerns && a.concerns.length > 0) resultMessage = `${message}\nConcerns:\n- ${a.concerns.join("\n- ")}`;
|
|
7092
|
+
const result = {
|
|
7093
|
+
status,
|
|
7094
|
+
codeDesc: a.policy_expr ?? "",
|
|
7095
|
+
message: resultMessage,
|
|
7096
|
+
startTime
|
|
7097
|
+
};
|
|
7098
|
+
const req = createRequirement(a.name, a.name, descriptions, .5, [result], { tags });
|
|
7099
|
+
applyClassification(req, nist);
|
|
7100
|
+
return req;
|
|
7101
|
+
}
|
|
7102
|
+
function buildErroredRequirement(e, startTime) {
|
|
7103
|
+
const { tags, nist } = analysisTags(e.name);
|
|
7104
|
+
const msg = flattenError(e.error);
|
|
7105
|
+
const result = {
|
|
7106
|
+
status: ResultStatus.Error,
|
|
7107
|
+
codeDesc: "",
|
|
7108
|
+
message: msg,
|
|
7109
|
+
startTime
|
|
7110
|
+
};
|
|
7111
|
+
const req = createRequirement(e.name, e.name, [{
|
|
7112
|
+
label: "default",
|
|
7113
|
+
data: msg
|
|
7114
|
+
}], .5, [result], { tags });
|
|
7115
|
+
applyClassification(req, nist);
|
|
7116
|
+
return req;
|
|
7117
|
+
}
|
|
7118
|
+
/** Render Hipcheck's recursive error chain as "msg: source: ...". */
|
|
7119
|
+
function flattenError(e) {
|
|
7120
|
+
const parts = [];
|
|
7121
|
+
for (let cur = e; cur; cur = cur.source) if (cur.msg) parts.push(cur.msg);
|
|
7122
|
+
return parts.length > 0 ? parts.join(": ") : "unknown error";
|
|
7123
|
+
}
|
|
7124
|
+
/** Render a risk score without trailing zeros (0.42, 0.33, 0), matching Go. */
|
|
7125
|
+
function formatScore(f) {
|
|
7126
|
+
return String(f);
|
|
7127
|
+
}
|
|
7128
|
+
/** Render the overall recommendation as baseline summary prose. */
|
|
7129
|
+
function buildSummary$1(rec) {
|
|
7130
|
+
const base = `Hipcheck recommendation: ${rec.kind ?? ""} (risk score ${formatScore(rec.risk_score ?? 0)}, policy '${rec.risk_policy ?? ""}').`;
|
|
7131
|
+
if ((rec.kind ?? "").toLowerCase() !== "investigate") return base;
|
|
7132
|
+
const suffix = investigateReason(rec.reason);
|
|
7133
|
+
return suffix ? `${base} ${suffix}` : base;
|
|
7134
|
+
}
|
|
7135
|
+
/** Decode the polymorphic `reason` into a sentence, or "". */
|
|
7136
|
+
function investigateReason(reason) {
|
|
7137
|
+
if (reason === null || reason === void 0) return "";
|
|
7138
|
+
if (typeof reason === "string") {
|
|
7139
|
+
if (reason === "Policy") return "Investigation triggered because the risk score exceeded the policy threshold.";
|
|
7140
|
+
return `Investigation reason: ${reason}.`;
|
|
7141
|
+
}
|
|
7142
|
+
if (typeof reason === "object") {
|
|
7143
|
+
const failed = reason.FailedAnalyses;
|
|
7144
|
+
if (Array.isArray(failed) && failed.length > 0) return `Investigation forced by failed analyses: ${failed.join(", ")}.`;
|
|
7145
|
+
}
|
|
7146
|
+
return "";
|
|
7147
|
+
}
|
|
7148
|
+
/**
|
|
7149
|
+
* Converts a MITRE Hipcheck `hc check --format json` report to HDF Results.
|
|
7150
|
+
*
|
|
7151
|
+
* @param input - Hipcheck JSON report string
|
|
7152
|
+
* @returns HDF JSON string
|
|
7153
|
+
*/
|
|
7154
|
+
async function convertHipcheckToHdf(input, converterVersion = "1.0.0") {
|
|
7155
|
+
validateInputSize(input, "hipcheck");
|
|
7156
|
+
if (!input || input.trim().length === 0) throw new Error("hipcheck: empty input");
|
|
7157
|
+
const report = parseJSON(input);
|
|
7158
|
+
if (!report.hipcheck_version && !report.repo_name) throw new Error("hipcheck: input does not look like a Hipcheck report");
|
|
7159
|
+
const startTime = (report.analyzed_at ? parseTimestamp(report.analyzed_at) : void 0) ?? /* @__PURE__ */ new Date();
|
|
7160
|
+
const requirements = [];
|
|
7161
|
+
for (const a of report.passing ?? []) requirements.push(buildAnalysisRequirement(a, ResultStatus.Passed, startTime));
|
|
7162
|
+
for (const a of report.failing ?? []) requirements.push(buildAnalysisRequirement(a, ResultStatus.Failed, startTime));
|
|
7163
|
+
for (const e of report.errored ?? []) requirements.push(buildErroredRequirement(e, startTime));
|
|
7164
|
+
if (requirements.length === 0) requirements.push(buildNoFindingsRequirement("hipcheck-no-findings", `Hipcheck analyzed ${repoIdent(report)} and reported zero analyses.`, startTime));
|
|
7165
|
+
const summary = buildSummary$1(report.recommendation ?? {});
|
|
7166
|
+
const baseline = createMinimalBaseline("Hipcheck Scan", requirements, {
|
|
7167
|
+
title: `Hipcheck analysis of ${repoIdent(report)} @ ${report.repo_head ?? ""}`,
|
|
7168
|
+
summary,
|
|
7169
|
+
resultsChecksum: await inputChecksum(input)
|
|
7170
|
+
});
|
|
7171
|
+
const ident = repoIdent(report);
|
|
7172
|
+
return buildHdfResults({
|
|
7173
|
+
generatorName: "hipcheck-to-hdf",
|
|
7174
|
+
converterVersion,
|
|
7175
|
+
toolName: "Hipcheck",
|
|
7176
|
+
toolFormat: "JSON",
|
|
7177
|
+
toolVersion: report.hipcheck_version,
|
|
7178
|
+
baselines: [baseline],
|
|
7179
|
+
components: ident ? [{
|
|
7180
|
+
name: ident,
|
|
7181
|
+
type: TargetType.Repository
|
|
7182
|
+
}] : void 0,
|
|
7183
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
7184
|
+
});
|
|
7185
|
+
}
|
|
7186
|
+
//#endregion
|
|
6885
7187
|
//#region converters/burpsuite-to-hdf/typescript/converter.ts
|
|
6886
7188
|
const IMPACT_MAPPING$5 = {
|
|
6887
7189
|
"high": .7,
|
|
@@ -12748,6 +13050,6 @@ function substituteParams(text, overrides) {
|
|
|
12748
13050
|
return result;
|
|
12749
13051
|
}
|
|
12750
13052
|
//#endregion
|
|
12751
|
-
export { convertAsffToHdf, convertAwsConfigToHdf, convertBurpsuiteToHdf, convertCheckovToHdf, convertCklToHdf, convertCklbToHdf, convertConveyorToHdf, convertCsafVexToHdf, convertCyclonedxToHdf, convertCyclonedxVexToHdf, convertDbprotectToHdf, convertDeptrackToHdf, convertFortifyToHdf, convertGitlabToHdf, convertGosecToHdf, convertGrypeToHdf, convertHdfToAsff, convertHdfToCkl, convertHdfToCklb, convertHdfToCsafVex, convertHdfToCsv, convertHdfToCyclonedxVex, convertHdfToEcs, convertHdfToOcsf, convertHdfToOpenVex, convertHdfToOscalPoam, convertHdfToOscalSar, convertHdfToSplunk, convertHdfToXccdf, convertHdfToXml, convertIonchannelToHdf, convertJfrogXrayToHdf, convertJunitToHdf, convertMsftDefenderCloudToHdf, convertMsftDefenderDevopsToHdf, convertMsftDefenderEndpointToHdf, convertMsftSecureScoreToHdf, convertNessusToHdf, convertNetsparkerToHdf, convertNeuvectorToHdf, convertNiktoToHdf, convertOpenVexToHdf, convertOscalCatalogToHdf, convertOscalComponentToHdf, convertOscalPoamToHdf, convertOscalProfileToHdf, convertOscalSapToHdf, convertOscalSarToHdf, convertOscalSspToHdf, convertPrismaToHdf, convertSarifToHdf, convertScoutsuiteToHdf, convertSnykToHdf, convertSonarqubeToHdf, convertSplunkToHdf, convertTrufflehogToHdf, convertTwistlockToHdf, convertV1ToV2, convertVeracodeToHdf, convertXccdfResultsToHdf, convertZapToHdf, detectOscalDocumentType, isHDFV1 };
|
|
13053
|
+
export { convertAsffToHdf, convertAwsConfigToHdf, convertBurpsuiteToHdf, convertCheckovToHdf, convertCklToHdf, convertCklbToHdf, convertConveyorToHdf, convertCsafVexToHdf, convertCyclonedxToHdf, convertCyclonedxVexToHdf, convertDbprotectToHdf, convertDefectDojoToHdf, convertDeptrackToHdf, convertFortifyToHdf, convertGitlabToHdf, convertGosecToHdf, convertGrypeToHdf, convertHdfToAsff, convertHdfToCkl, convertHdfToCklb, convertHdfToCsafVex, convertHdfToCsv, convertHdfToCyclonedxVex, convertHdfToEcs, convertHdfToOcsf, convertHdfToOpenVex, convertHdfToOscalPoam, convertHdfToOscalSar, convertHdfToSplunk, convertHdfToXccdf, convertHdfToXml, convertHipcheckToHdf, convertIonchannelToHdf, convertJfrogXrayToHdf, convertJunitToHdf, convertMsftDefenderCloudToHdf, convertMsftDefenderDevopsToHdf, convertMsftDefenderEndpointToHdf, convertMsftSecureScoreToHdf, convertNessusToHdf, convertNetsparkerToHdf, convertNeuvectorToHdf, convertNiktoToHdf, convertOpenVexToHdf, convertOscalCatalogToHdf, convertOscalComponentToHdf, convertOscalPoamToHdf, convertOscalProfileToHdf, convertOscalSapToHdf, convertOscalSarToHdf, convertOscalSspToHdf, convertPrismaToHdf, convertSarifToHdf, convertScoutsuiteToHdf, convertSnykToHdf, convertSonarqubeToHdf, convertSplunkToHdf, convertTrufflehogToHdf, convertTwistlockToHdf, convertV1ToV2, convertVeracodeToHdf, convertXccdfResultsToHdf, convertZapToHdf, detectOscalDocumentType, isHDFV1 };
|
|
12752
13054
|
|
|
12753
13055
|
//# sourceMappingURL=index.js.map
|