@mitre/hdf-converters 2.6.21 → 2.6.24

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.
Files changed (67) hide show
  1. package/lib/index.d.ts +2 -1
  2. package/lib/index.js +4 -2
  3. package/lib/index.js.map +1 -1
  4. package/lib/package.json +4 -4
  5. package/lib/src/asff-mapper/asff-mapper.d.ts +106 -0
  6. package/lib/src/asff-mapper/asff-mapper.js +462 -0
  7. package/lib/src/asff-mapper/asff-mapper.js.map +1 -0
  8. package/lib/src/asff-mapper/case-firewall-manager.d.ts +1 -0
  9. package/lib/src/asff-mapper/case-firewall-manager.js +27 -0
  10. package/lib/src/asff-mapper/case-firewall-manager.js.map +1 -0
  11. package/lib/src/asff-mapper/case-hdf2asff.d.ts +1 -0
  12. package/lib/src/asff-mapper/case-hdf2asff.js +192 -0
  13. package/lib/src/asff-mapper/case-hdf2asff.js.map +1 -0
  14. package/lib/src/asff-mapper/case-prowler.d.ts +1 -0
  15. package/lib/src/asff-mapper/case-prowler.js +39 -0
  16. package/lib/src/asff-mapper/case-prowler.js.map +1 -0
  17. package/lib/src/asff-mapper/case-security-hub.d.ts +1 -0
  18. package/lib/src/asff-mapper/case-security-hub.js +136 -0
  19. package/lib/src/asff-mapper/case-security-hub.js.map +1 -0
  20. package/lib/src/asff-mapper/case-trivy.d.ts +1 -0
  21. package/lib/src/asff-mapper/case-trivy.js +71 -0
  22. package/lib/src/asff-mapper/case-trivy.js.map +1 -0
  23. package/lib/src/base-converter.js +8 -12
  24. package/lib/src/base-converter.js.map +1 -1
  25. package/lib/src/burpsuite-mapper.js +2 -2
  26. package/lib/src/burpsuite-mapper.js.map +1 -1
  27. package/lib/src/converters-from-hdf/asff/transformers.js +8 -4
  28. package/lib/src/converters-from-hdf/asff/transformers.js.map +1 -1
  29. package/lib/src/converters-from-hdf/splunk/reverse-splunk-mapper.d.ts +2 -2
  30. package/lib/src/converters-from-hdf/splunk/reverse-splunk-mapper.js +2 -2
  31. package/lib/src/converters-from-hdf/splunk/reverse-splunk-mapper.js.map +1 -1
  32. package/lib/src/converters-from-hdf/splunk/splunk-profile-types.d.ts +1 -1
  33. package/lib/src/converters-from-hdf/splunk/splunk-report-types.d.ts +2 -1
  34. package/lib/src/fortify-mapper.js +1 -3
  35. package/lib/src/fortify-mapper.js.map +1 -1
  36. package/lib/src/ionchannel-mapper.d.ts +27 -0
  37. package/lib/src/ionchannel-mapper.js +268 -0
  38. package/lib/src/ionchannel-mapper.js.map +1 -0
  39. package/lib/src/jfrog-xray-mapper.js +2 -2
  40. package/lib/src/jfrog-xray-mapper.js.map +1 -1
  41. package/lib/src/mappings/ScoutsuiteNistMapping.js +3 -3
  42. package/lib/src/mappings/ScoutsuiteNistMapping.js.map +1 -1
  43. package/lib/src/nessus-mapper.js +8 -3
  44. package/lib/src/nessus-mapper.js.map +1 -1
  45. package/lib/src/netsparker-mapper.js +2 -2
  46. package/lib/src/netsparker-mapper.js.map +1 -1
  47. package/lib/src/prisma-mapper.js +2 -2
  48. package/lib/src/prisma-mapper.js.map +1 -1
  49. package/lib/src/sarif-mapper.js +8 -4
  50. package/lib/src/sarif-mapper.js.map +1 -1
  51. package/lib/src/snyk-mapper.d.ts +3 -1
  52. package/lib/src/snyk-mapper.js +25 -19
  53. package/lib/src/snyk-mapper.js.map +1 -1
  54. package/lib/src/splunk-mapper.d.ts +3 -2
  55. package/lib/src/splunk-mapper.js +5 -5
  56. package/lib/src/splunk-mapper.js.map +1 -1
  57. package/lib/src/utils/global.d.ts +4 -2
  58. package/lib/src/utils/global.js +11 -6
  59. package/lib/src/utils/global.js.map +1 -1
  60. package/lib/src/xccdf-results-mapper.js +2 -2
  61. package/lib/src/xccdf-results-mapper.js.map +1 -1
  62. package/lib/src/zap-mapper.js +2 -8
  63. package/lib/src/zap-mapper.js.map +1 -1
  64. package/package.json +4 -4
  65. package/lib/src/asff-mapper.d.ts +0 -25
  66. package/lib/src/asff-mapper.js +0 -887
  67. package/lib/src/asff-mapper.js.map +0 -1
package/lib/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- export * from './src/asff-mapper';
1
+ export { ASFFResults } from './src/asff-mapper/asff-mapper';
2
2
  export * from './src/aws-config-mapper';
3
3
  export * from './src/burpsuite-mapper';
4
4
  export * from './src/converters-from-hdf/asff/reverse-asff-mapper';
5
5
  export * from './src/converters-from-hdf/splunk/reverse-splunk-mapper';
6
6
  export * from './src/dbprotect-mapper';
7
7
  export * from './src/fortify-mapper';
8
+ export * from './src/ionchannel-mapper';
8
9
  export * from './src/jfrog-xray-mapper';
9
10
  export * as AwsConfigMappingData from './src/mappings/AwsConfigMappingData';
10
11
  export * as CciNistMappingData from './src/mappings/CciNistMappingData';
package/lib/index.js CHANGED
@@ -26,14 +26,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
26
26
  return result;
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.ScoutsuiteNistMappingData = exports.OWaspNistMappingData = exports.NiktoNistMappingData = exports.NessusPluginNistMappingData = exports.CweNistMappingData = exports.CciNistMappingData = exports.AwsConfigMappingData = void 0;
30
- __exportStar(require("./src/asff-mapper"), exports);
29
+ exports.ScoutsuiteNistMappingData = exports.OWaspNistMappingData = exports.NiktoNistMappingData = exports.NessusPluginNistMappingData = exports.CweNistMappingData = exports.CciNistMappingData = exports.AwsConfigMappingData = exports.ASFFResults = void 0;
30
+ var asff_mapper_1 = require("./src/asff-mapper/asff-mapper");
31
+ Object.defineProperty(exports, "ASFFResults", { enumerable: true, get: function () { return asff_mapper_1.ASFFResults; } });
31
32
  __exportStar(require("./src/aws-config-mapper"), exports);
32
33
  __exportStar(require("./src/burpsuite-mapper"), exports);
33
34
  __exportStar(require("./src/converters-from-hdf/asff/reverse-asff-mapper"), exports);
34
35
  __exportStar(require("./src/converters-from-hdf/splunk/reverse-splunk-mapper"), exports);
35
36
  __exportStar(require("./src/dbprotect-mapper"), exports);
36
37
  __exportStar(require("./src/fortify-mapper"), exports);
38
+ __exportStar(require("./src/ionchannel-mapper"), exports);
37
39
  __exportStar(require("./src/jfrog-xray-mapper"), exports);
38
40
  exports.AwsConfigMappingData = __importStar(require("./src/mappings/AwsConfigMappingData"));
39
41
  exports.CciNistMappingData = __importStar(require("./src/mappings/CciNistMappingData"));
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,0DAAwC;AACxC,yDAAuC;AACvC,qFAAmE;AACnE,yFAAuE;AACvE,yDAAuC;AACvC,uDAAqC;AACrC,0DAAwC;AACxC,4FAA4E;AAC5E,wFAAwE;AACxE,wFAAwE;AACxE,0GAA0F;AAC1F,4FAA4E;AAC5E,4FAA4E;AAC5E,sGAAsF;AACtF,sDAAoC;AACpC,0DAAwC;AACxC,qDAAmC;AACnC,sDAAoC;AACpC,qDAAmC;AACnC,0DAAwC;AACxC,oDAAkC;AAClC,yDAAuC;AACvC,sDAAoC;AACpC,6DAA2C;AAC3C,mDAAiC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6DAA0D;AAAlD,0GAAA,WAAW,OAAA;AACnB,0DAAwC;AACxC,yDAAuC;AACvC,qFAAmE;AACnE,yFAAuE;AACvE,yDAAuC;AACvC,uDAAqC;AACrC,0DAAwC;AACxC,0DAAwC;AACxC,4FAA4E;AAC5E,wFAAwE;AACxE,wFAAwE;AACxE,0GAA0F;AAC1F,4FAA4E;AAC5E,4FAA4E;AAC5E,sGAAsF;AACtF,sDAAoC;AACpC,0DAAwC;AACxC,qDAAmC;AACnC,sDAAoC;AACpC,qDAAmC;AACnC,0DAAwC;AACxC,oDAAkC;AAClC,yDAAuC;AACvC,sDAAoC;AACpC,6DAA2C;AAC3C,mDAAiC"}
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mitre/hdf-converters",
3
- "version": "2.6.21",
3
+ "version": "2.6.24",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Converter util library used to transform various scan results into HDF format",
6
6
  "files": [
@@ -26,12 +26,12 @@
26
26
  "@types/papaparse": "^5.3.2",
27
27
  "@types/xml2js": "^0.4.9",
28
28
  "aws-sdk": "^2.1046.0",
29
- "axios": "^0.26.0",
29
+ "axios": "^0.27.2",
30
30
  "csv2json": "^2.0.2",
31
31
  "fast-xml-parser": "^3.21.1",
32
32
  "html-entities": "^2.3.2",
33
33
  "htmlparser2": "^7.1.2",
34
- "inspecjs": "^2.6.17",
34
+ "inspecjs": "^2.6.24",
35
35
  "lodash": "^4.17.21",
36
36
  "moment": "^2.29.1",
37
37
  "papaparse": "^5.3.1",
@@ -41,7 +41,7 @@
41
41
  "devDependencies": {
42
42
  "@types/jest": "^27.0.0",
43
43
  "@types/lodash": "^4.14.161",
44
- "@types/node": "^15.0.1",
44
+ "@types/node": "^17.0.25",
45
45
  "htmlparser2": "^7.1.2",
46
46
  "jest": "^27.0.6",
47
47
  "quicktype": "^15.0.260",
@@ -0,0 +1,106 @@
1
+ import { ExecJSON } from 'inspecjs';
2
+ import { BaseConverter } from '../base-converter';
3
+ export declare enum SpecialCasing {
4
+ FirewallManager = "AWS Firewall Manager",
5
+ Prowler = "Prowler",
6
+ SecurityHub = "AWS Security Hub",
7
+ Trivy = "Aqua Trivy",
8
+ HDF2ASFF = "MITRE SAF HDF2ASFF",
9
+ Default = "Default"
10
+ }
11
+ export declare function consolidate(context: ASFFMapper, input: unknown[], file: Record<string, unknown>): ExecJSON.Control[];
12
+ export declare class ASFFMapper extends BaseConverter {
13
+ meta: Record<string, string | undefined> | undefined;
14
+ supportingDocs: Map<SpecialCasing, Record<string, Record<string, unknown>>>;
15
+ defaultMappings: {
16
+ platform: {
17
+ name: string;
18
+ release: string;
19
+ target_id: {
20
+ transformer: (record: Record<string, unknown>) => string;
21
+ };
22
+ };
23
+ version: string;
24
+ statistics: {
25
+ duration: null;
26
+ };
27
+ profiles: {
28
+ name: {
29
+ transformer: () => string;
30
+ };
31
+ version: string;
32
+ title: {
33
+ transformer: () => string;
34
+ };
35
+ maintainer: null;
36
+ summary: string;
37
+ license: null;
38
+ copyright: null;
39
+ copyright_email: null;
40
+ supports: never[];
41
+ attributes: never[];
42
+ depends: never[];
43
+ groups: never[];
44
+ status: string;
45
+ controls: {
46
+ path: string;
47
+ key: string;
48
+ arrayTransformer: (input: unknown[], file: Record<string, unknown>) => ExecJSON.Control[];
49
+ id: {
50
+ transformer: (finding: Record<string, unknown>) => string;
51
+ };
52
+ title: {
53
+ transformer: (finding: Record<string, unknown>) => string;
54
+ };
55
+ desc: {
56
+ path: string;
57
+ transformer: (input: string) => string;
58
+ };
59
+ impact: {
60
+ transformer: (finding: Record<string, unknown>) => number;
61
+ };
62
+ tags: {
63
+ transformer: (finding: Record<string, unknown>) => Record<string, unknown> | undefined;
64
+ nist: {
65
+ transformer: (finding: Record<string, unknown>) => string[];
66
+ };
67
+ };
68
+ descriptions: {
69
+ data: {
70
+ path: string;
71
+ transformer: (input: Record<string, string>) => string;
72
+ };
73
+ label: string;
74
+ }[];
75
+ refs: {
76
+ transformer: (finding: Record<string, unknown>) => Record<string, unknown>;
77
+ }[];
78
+ source_location: {};
79
+ code: string;
80
+ results: {
81
+ status: {
82
+ transformer: (finding: Record<string, unknown>) => ExecJSON.ControlResultStatus;
83
+ };
84
+ code_desc: {
85
+ transformer: (finding: Record<string, unknown>) => string;
86
+ };
87
+ transformer: (finding: Record<string, unknown>) => Record<string, unknown>;
88
+ start_time: {
89
+ transformer: (finding: Record<string, unknown>) => string;
90
+ };
91
+ }[];
92
+ }[];
93
+ sha256: string;
94
+ }[];
95
+ };
96
+ statusReason(finding: unknown): string | undefined;
97
+ setMappings(): void;
98
+ constructor(asff: Record<string, unknown>, supportingDocs: Map<SpecialCasing, Record<string, Record<string, unknown>>>, meta?: Record<string, string | undefined> | undefined);
99
+ }
100
+ export declare class ASFFResults {
101
+ data: Record<string, Record<string, unknown>[]>;
102
+ meta: Record<string, string | undefined> | undefined;
103
+ supportingDocs: Map<SpecialCasing, Record<string, Record<string, unknown>>>;
104
+ constructor(asffJson: string, securityhubStandardsJsonArray?: undefined | string[], meta?: Record<string, string | undefined> | undefined);
105
+ toHdf(): Record<string, ExecJSON.Execution>;
106
+ }
@@ -0,0 +1,462 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ASFFResults = exports.ASFFMapper = exports.consolidate = exports.SpecialCasing = void 0;
7
+ const html_entities_1 = require("html-entities");
8
+ const inspecjs_1 = require("inspecjs");
9
+ const lodash_1 = __importDefault(require("lodash"));
10
+ const package_json_1 = require("../../package.json");
11
+ const base_converter_1 = require("../base-converter");
12
+ const global_1 = require("../utils/global");
13
+ const case_firewall_manager_1 = require("./case-firewall-manager");
14
+ const case_hdf2asff_1 = require("./case-hdf2asff");
15
+ const case_prowler_1 = require("./case-prowler");
16
+ const case_security_hub_1 = require("./case-security-hub");
17
+ const case_trivy_1 = require("./case-trivy");
18
+ const IMPACT_MAPPING = new Map([
19
+ ['CRITICAL', 0.9],
20
+ ['HIGH', 0.7],
21
+ ['MEDIUM', 0.5],
22
+ ['LOW', 0.3],
23
+ ['INFORMATIONAL', 0.0]
24
+ ]);
25
+ const SEVERITY_LABEL = 'Severity.Label';
26
+ const COMPLIANCE_STATUS = 'Compliance.Status';
27
+ var SpecialCasing;
28
+ (function (SpecialCasing) {
29
+ SpecialCasing["FirewallManager"] = "AWS Firewall Manager";
30
+ SpecialCasing["Prowler"] = "Prowler";
31
+ SpecialCasing["SecurityHub"] = "AWS Security Hub";
32
+ SpecialCasing["Trivy"] = "Aqua Trivy";
33
+ SpecialCasing["HDF2ASFF"] = "MITRE SAF HDF2ASFF";
34
+ SpecialCasing["Default"] = "Default";
35
+ })(SpecialCasing = exports.SpecialCasing || (exports.SpecialCasing = {}));
36
+ function whichSpecialCase(finding) {
37
+ const productArn = lodash_1.default.get(finding, 'ProductArn');
38
+ if (productArn.match(/^arn:[^:]+:securityhub:[^:]+:[^:]*:product\/aws\/firewall-manager$/)) {
39
+ return SpecialCasing.FirewallManager;
40
+ }
41
+ else if (productArn.match(/^arn:[^:]+:securityhub:[^:]+:[^:]*:product\/prowler\/prowler$/)) {
42
+ return SpecialCasing.Prowler;
43
+ }
44
+ else if (productArn.match(/^arn:[^:]+:securityhub:[^:]+:[^:]*:product\/aws\/securityhub$/)) {
45
+ return SpecialCasing.SecurityHub;
46
+ }
47
+ else if (productArn.match(/^arn:[^:]+:securityhub:[^:]+:[^:]*:product\/aquasecurity\/aquasecurity$/)) {
48
+ return SpecialCasing.Trivy;
49
+ }
50
+ else if (lodash_1.default.some(lodash_1.default.get(finding, 'FindingProviderFields.Types'), (type) => {
51
+ const version = type.split('/')[2].split('-')[0];
52
+ const [major, minor, patch] = version.split('.');
53
+ if (parseInt(major) > 1 &&
54
+ parseInt(minor) > 5 &&
55
+ parseInt(patch) > 20) {
56
+ return lodash_1.default.startsWith(type, 'MITRE/SAF/');
57
+ }
58
+ else {
59
+ return false;
60
+ }
61
+ })) {
62
+ return SpecialCasing.HDF2ASFF;
63
+ }
64
+ else {
65
+ return SpecialCasing.Default;
66
+ }
67
+ }
68
+ const SPECIAL_CASE_MAPPING = new Map([
69
+ [SpecialCasing.FirewallManager, (0, case_firewall_manager_1.getFirewallManager)()],
70
+ [SpecialCasing.Prowler, (0, case_prowler_1.getProwler)()],
71
+ [SpecialCasing.SecurityHub, (0, case_security_hub_1.getSecurityHub)()],
72
+ [SpecialCasing.Trivy, (0, case_trivy_1.getTrivy)()],
73
+ [SpecialCasing.HDF2ASFF, (0, case_hdf2asff_1.getHDF2ASFF)()]
74
+ ]);
75
+ function externalProductHandler(context, product, data, func, defaultVal) {
76
+ var _a;
77
+ if (product !== SpecialCasing.Default &&
78
+ lodash_1.default.has(SPECIAL_CASE_MAPPING.get(product), func)) {
79
+ let keywords = {};
80
+ if (context.supportingDocs.has(product)) {
81
+ keywords = { ...context.supportingDocs.get(product) };
82
+ }
83
+ return (_a = lodash_1.default.get(SPECIAL_CASE_MAPPING.get(product), func)) === null || _a === void 0 ? void 0 : _a.apply(context, [
84
+ data,
85
+ keywords
86
+ ]);
87
+ }
88
+ else {
89
+ if (typeof defaultVal === 'function') {
90
+ return defaultVal();
91
+ }
92
+ else {
93
+ return defaultVal;
94
+ }
95
+ }
96
+ }
97
+ function handleIdGroup(context, idGroup) {
98
+ const [id, data] = idGroup;
99
+ const group = data.map((d) => d[0]);
100
+ const findings = data.map((d) => d[1]);
101
+ const productInfo = lodash_1.default.get(findings[0], 'ProductArn')
102
+ .split(':')
103
+ .slice(-1)[0]
104
+ .split('/');
105
+ const productName = externalProductHandler(context, whichSpecialCase(findings[0]), findings, 'productName', (0, html_entities_1.encode)(`${productInfo[1]}/${productInfo[2]}`));
106
+ const hasNoTitlePrefix = externalProductHandler(context, whichSpecialCase(findings[0]), null, 'doesNotHaveFindingTitlePrefix', false);
107
+ const titlePrefix = hasNoTitlePrefix ? '' : `${productName}: `;
108
+ const waiverData = externalProductHandler(context, whichSpecialCase(findings[0]), group, 'waiverData', {});
109
+ return {
110
+ id: id,
111
+ title: `${titlePrefix}${lodash_1.default.uniq(group.map((d) => d.title)).join(';')}`,
112
+ tags: lodash_1.default.mergeWith({}, ...group.map((d) => d.tags), (acc, cur) => {
113
+ if (acc === undefined || cur === undefined) {
114
+ return acc || cur;
115
+ }
116
+ else {
117
+ return Array.isArray(acc) || Array.isArray(cur)
118
+ ? lodash_1.default.uniq(lodash_1.default.concat([], acc, cur))
119
+ : acc;
120
+ }
121
+ }),
122
+ impact: Math.max(...group.map((d) => d.impact)),
123
+ desc: externalProductHandler(context, whichSpecialCase(findings[0]), group, 'desc', lodash_1.default.uniq(group.map((d) => d.desc)).join('\n')),
124
+ descriptions: group
125
+ .map((d) => d.descriptions)
126
+ .flat()
127
+ .filter((element, index, arr) => element &&
128
+ element.data !== '' &&
129
+ index ===
130
+ arr.findIndex((e) => e !== null && e !== undefined && e.data === element.data)),
131
+ refs: group
132
+ .map((d) => d.refs)
133
+ .flat()
134
+ .filter((element) => lodash_1.default.get(element, 'url') !== undefined),
135
+ source_location: (() => {
136
+ const locs = lodash_1.default.uniq(group.map((d) => d.source_location)).filter((loc) => Object.keys(loc || {}).length !== 0);
137
+ if (locs.length === 0) {
138
+ return {};
139
+ }
140
+ else if (locs.length === 1) {
141
+ return locs[0];
142
+ }
143
+ else {
144
+ return { ref: JSON.stringify(locs) };
145
+ }
146
+ })(),
147
+ ...(Object.keys(waiverData || {}).length !== 0 && {
148
+ waiver_data: waiverData
149
+ }),
150
+ code: externalProductHandler(context, whichSpecialCase(findings[0]), group, 'code', JSON.stringify({ Findings: findings }, null, 2)),
151
+ results: group.map((d) => d.results).flat()
152
+ };
153
+ }
154
+ function consolidate(context, input, file) {
155
+ const allFindings = lodash_1.default.get(file, 'Findings');
156
+ if (input.length !== allFindings.length) {
157
+ throw new Error('The number of generated controls should be the same as the number of findings while consolidating.');
158
+ }
159
+ const idGroups = lodash_1.default.groupBy(lodash_1.default.zip(input, allFindings), (value) => {
160
+ const [hdfControl, asffFinding] = value;
161
+ return externalProductHandler(context, whichSpecialCase(asffFinding), asffFinding, 'subfindingsId', lodash_1.default.get(hdfControl, 'id'));
162
+ });
163
+ return Object.entries(idGroups || {}).map((idGroup) => handleIdGroup(context, idGroup));
164
+ }
165
+ exports.consolidate = consolidate;
166
+ function wrapWithFindingsObject(output) {
167
+ if (!lodash_1.default.has(output, 'Findings')) {
168
+ if (Array.isArray(output)) {
169
+ output = { Findings: output };
170
+ }
171
+ else {
172
+ output = { Findings: [output] };
173
+ }
174
+ }
175
+ return output;
176
+ }
177
+ function fixFileInput(asffJson) {
178
+ let output = {};
179
+ try {
180
+ output = JSON.parse(asffJson);
181
+ }
182
+ catch {
183
+ const fixedInput = `[${asffJson
184
+ .trim()
185
+ .replace(/}\n/g, '},\n')
186
+ .replace(/\},\n\$/g, '')}]`;
187
+ output = JSON.parse(fixedInput);
188
+ }
189
+ return wrapWithFindingsObject(output);
190
+ }
191
+ class ASFFMapper extends base_converter_1.BaseConverter {
192
+ constructor(asff, supportingDocs, meta = undefined) {
193
+ super(asff);
194
+ this.defaultMappings = {
195
+ platform: {
196
+ name: 'Heimdall Tools',
197
+ release: package_json_1.version,
198
+ target_id: {
199
+ transformer: (record) => {
200
+ const productInfo = lodash_1.default.get(record, 'Findings[0].ProductArn')
201
+ .split(':')
202
+ .slice(-1)[0]
203
+ .split('/');
204
+ const defaultTargetId = `${productInfo[1]} | ${productInfo[2]}`;
205
+ return externalProductHandler(this, whichSpecialCase(lodash_1.default.get(record, 'Findings[0]')), [lodash_1.default.get(record, 'Findings[0]'), record.Findings], 'productName', (0, html_entities_1.encode)(defaultTargetId));
206
+ }
207
+ }
208
+ },
209
+ version: package_json_1.version,
210
+ statistics: {
211
+ duration: null
212
+ },
213
+ profiles: [
214
+ {
215
+ name: {
216
+ transformer: () => {
217
+ var _a;
218
+ return ((_a = this.meta) === null || _a === void 0 ? void 0 : _a.name) || 'AWS Security Finding Format';
219
+ }
220
+ },
221
+ version: '',
222
+ title: {
223
+ transformer: () => {
224
+ return lodash_1.default.get(this.meta, 'title') || 'ASFF Findings';
225
+ }
226
+ },
227
+ maintainer: null,
228
+ summary: '',
229
+ license: null,
230
+ copyright: null,
231
+ copyright_email: null,
232
+ supports: [],
233
+ attributes: [],
234
+ depends: [],
235
+ groups: [],
236
+ status: 'loaded',
237
+ controls: [
238
+ {
239
+ path: 'Findings',
240
+ key: 'id',
241
+ arrayTransformer: consolidate.bind(this, this),
242
+ id: {
243
+ transformer: (finding) => externalProductHandler(this, whichSpecialCase(finding), finding, 'findingId', (0, html_entities_1.encode)(lodash_1.default.get(finding, 'GeneratorId')))
244
+ },
245
+ title: {
246
+ transformer: (finding) => externalProductHandler(this, whichSpecialCase(finding), finding, 'findingTitle', (0, html_entities_1.encode)(lodash_1.default.get(finding, 'Title')))
247
+ },
248
+ desc: {
249
+ path: 'Description',
250
+ transformer: (input) => (0, html_entities_1.encode)(input)
251
+ },
252
+ impact: {
253
+ transformer: (finding) => {
254
+ let impact;
255
+ if (lodash_1.default.get(finding, 'Workflow.Status') === 'SUPPRESSED') {
256
+ impact = 'INFORMATIONAL';
257
+ }
258
+ else {
259
+ const defaultFunc = () => lodash_1.default.get(finding, SEVERITY_LABEL)
260
+ ? lodash_1.default.get(finding, SEVERITY_LABEL)
261
+ : lodash_1.default.get(finding, 'Severity.Normalized') /
262
+ 100.0;
263
+ impact = externalProductHandler(this, whichSpecialCase(finding), finding, 'findingImpact', defaultFunc);
264
+ }
265
+ return typeof impact === 'string'
266
+ ? IMPACT_MAPPING.get(impact) || 0
267
+ : impact;
268
+ }
269
+ },
270
+ tags: {
271
+ transformer: (finding) => externalProductHandler(this, whichSpecialCase(finding), finding, 'findingTags', {}),
272
+ nist: {
273
+ transformer: (finding) => {
274
+ const tags = externalProductHandler(this, whichSpecialCase(finding), finding, 'findingNistTag', []);
275
+ if (tags.length === 0) {
276
+ return global_1.DEFAULT_STATIC_CODE_ANALYSIS_NIST_TAGS;
277
+ }
278
+ else {
279
+ return tags;
280
+ }
281
+ }
282
+ }
283
+ },
284
+ descriptions: [
285
+ {
286
+ data: {
287
+ path: 'Remediation.Recommendation',
288
+ transformer: (input) => {
289
+ const data = [];
290
+ if (lodash_1.default.has(input, 'Text')) {
291
+ data.push(lodash_1.default.get(input, 'Text'));
292
+ }
293
+ if (lodash_1.default.has(input, 'Url')) {
294
+ data.push(lodash_1.default.get(input, 'Url'));
295
+ }
296
+ return data.join('\n');
297
+ }
298
+ },
299
+ label: 'fix'
300
+ }
301
+ ],
302
+ refs: [
303
+ {
304
+ transformer: (finding) => {
305
+ return {
306
+ ...(lodash_1.default.has(finding, 'SourceUrl') && {
307
+ url: {
308
+ path: 'SourceUrl'
309
+ }
310
+ })
311
+ };
312
+ }
313
+ }
314
+ ],
315
+ source_location: {},
316
+ code: '',
317
+ results: [
318
+ {
319
+ status: {
320
+ transformer: (finding) => {
321
+ const defaultFunc = () => {
322
+ if (lodash_1.default.has(finding, COMPLIANCE_STATUS)) {
323
+ switch (lodash_1.default.get(finding, COMPLIANCE_STATUS)) {
324
+ case 'PASSED':
325
+ return inspecjs_1.ExecJSON.ControlResultStatus.Passed;
326
+ case 'WARNING':
327
+ return inspecjs_1.ExecJSON.ControlResultStatus.Skipped;
328
+ case 'FAILED':
329
+ return inspecjs_1.ExecJSON.ControlResultStatus.Failed;
330
+ case 'NOT_AVAILABLE':
331
+ return inspecjs_1.ExecJSON.ControlResultStatus.Skipped;
332
+ default:
333
+ return inspecjs_1.ExecJSON.ControlResultStatus.Error;
334
+ }
335
+ }
336
+ else {
337
+ return inspecjs_1.ExecJSON.ControlResultStatus.Skipped;
338
+ }
339
+ };
340
+ return externalProductHandler(this, whichSpecialCase(finding), finding, 'subfindingsStatus', defaultFunc);
341
+ }
342
+ },
343
+ code_desc: {
344
+ transformer: (finding) => {
345
+ let output = externalProductHandler(this, whichSpecialCase(finding), finding, 'subfindingsCodeDesc', '');
346
+ if (output) {
347
+ output += '; ';
348
+ }
349
+ const resources = lodash_1.default.get(finding, 'Resources')
350
+ .map((resource) => {
351
+ let hash = `Type: ${(0, html_entities_1.encode)(lodash_1.default.get(resource, 'Type'))}, Id: ${(0, html_entities_1.encode)(lodash_1.default.get(resource, 'Id'))}`;
352
+ if (lodash_1.default.has(resource, 'Partition')) {
353
+ hash += `, Partition: ${(0, html_entities_1.encode)(lodash_1.default.get(resource, 'Partition'))}`;
354
+ }
355
+ if (lodash_1.default.has(resource, 'Region')) {
356
+ hash += `, Region: ${(0, html_entities_1.encode)(lodash_1.default.get(resource, 'Region'))}`;
357
+ }
358
+ return hash;
359
+ })
360
+ .join(', ');
361
+ output += `Resources: [${resources}]`;
362
+ return output;
363
+ }
364
+ },
365
+ transformer: (finding) => {
366
+ const message = (() => {
367
+ const defaultFunc = () => {
368
+ const statusReason = this.statusReason(finding);
369
+ switch (lodash_1.default.get(finding, COMPLIANCE_STATUS)) {
370
+ case undefined:
371
+ return undefined;
372
+ case 'PASSED':
373
+ return statusReason;
374
+ case 'WARNING':
375
+ return undefined;
376
+ case 'FAILED':
377
+ return statusReason;
378
+ case 'NOT_AVAILABLE':
379
+ return undefined;
380
+ default:
381
+ return statusReason;
382
+ }
383
+ };
384
+ return externalProductHandler(this, whichSpecialCase(finding), finding, 'subfindingsMessage', defaultFunc);
385
+ })();
386
+ const skipMessage = (() => {
387
+ const statusReason = this.statusReason(finding);
388
+ switch (lodash_1.default.get(finding, COMPLIANCE_STATUS)) {
389
+ case undefined:
390
+ return statusReason;
391
+ case 'PASSED':
392
+ return undefined;
393
+ case 'WARNING':
394
+ return statusReason;
395
+ case 'FAILED':
396
+ return undefined;
397
+ case 'NOT_AVAILABLE':
398
+ return statusReason;
399
+ default:
400
+ return undefined;
401
+ }
402
+ })();
403
+ return {
404
+ ...(message !== undefined && { message }),
405
+ ...(skipMessage !== undefined && {
406
+ skip_message: skipMessage
407
+ })
408
+ };
409
+ },
410
+ start_time: {
411
+ transformer: (finding) => lodash_1.default.get(finding, 'LastObservedAt') ||
412
+ lodash_1.default.get(finding, 'UpdatedAt')
413
+ }
414
+ }
415
+ ]
416
+ }
417
+ ],
418
+ sha256: ''
419
+ }
420
+ ]
421
+ };
422
+ this.meta = meta;
423
+ this.supportingDocs = supportingDocs;
424
+ this.setMappings();
425
+ }
426
+ statusReason(finding) {
427
+ var _a;
428
+ return (_a = lodash_1.default.get(finding, 'Compliance.StatusReasons')) === null || _a === void 0 ? void 0 : _a.map((reason) => Object.entries(reason || {}).map(([key, value]) => {
429
+ return `${(0, html_entities_1.encode)(key)}: ${(0, html_entities_1.encode)(value)}`;
430
+ })).flat().join('\n');
431
+ }
432
+ setMappings() {
433
+ this.mappings = externalProductHandler(this, whichSpecialCase(lodash_1.default.get(this.data, 'Findings[0]')), this, 'mapping', this.defaultMappings);
434
+ }
435
+ }
436
+ exports.ASFFMapper = ASFFMapper;
437
+ class ASFFResults {
438
+ constructor(asffJson, securityhubStandardsJsonArray = undefined, meta = undefined) {
439
+ this.meta = meta;
440
+ this.supportingDocs = new Map();
441
+ this.supportingDocs.set(SpecialCasing.SecurityHub, lodash_1.default.get(SPECIAL_CASE_MAPPING.get(SpecialCasing.SecurityHub), 'securityhubSupportingDocs', (standards) => {
442
+ throw new Error(`supportingDocs function should've been defined: ${standards}`);
443
+ })(securityhubStandardsJsonArray));
444
+ const findings = lodash_1.default.get(fixFileInput(asffJson), 'Findings');
445
+ this.data = lodash_1.default.groupBy(findings, (finding) => {
446
+ const productInfo = lodash_1.default.get(finding, 'ProductArn')
447
+ .split(':')
448
+ .slice(-1)[0]
449
+ .split('/');
450
+ const defaultFilename = `${productInfo[1]} | ${productInfo[2]}.json`;
451
+ return externalProductHandler(this, whichSpecialCase(finding), [finding, findings], 'filename', (0, html_entities_1.encode)(defaultFilename));
452
+ });
453
+ }
454
+ toHdf() {
455
+ return lodash_1.default.mapValues(this.data, (val) => {
456
+ const wrapped = wrapWithFindingsObject(val);
457
+ return new ASFFMapper(externalProductHandler(this, whichSpecialCase(lodash_1.default.get(wrapped, 'Findings[0]')), wrapped, 'preprocessingASFF', wrapped), externalProductHandler(this, whichSpecialCase(lodash_1.default.get(wrapped, 'Findings[0]')), [wrapped, this.supportingDocs], 'supportingDocs', this.supportingDocs), externalProductHandler(this, whichSpecialCase(lodash_1.default.get(wrapped, 'Findings[0]')), undefined, 'meta', this.meta)).toHdf();
458
+ });
459
+ }
460
+ }
461
+ exports.ASFFResults = ASFFResults;
462
+ //# sourceMappingURL=asff-mapper.js.map