@mitre/inspec-objects 2.0.4 → 2.1.0

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.
@@ -19,7 +19,7 @@ const logging_1 = require("../utilities/logging");
19
19
  * will be returned
20
20
  */
21
21
  function searchTree(aTree, fCompair, bGreedy) {
22
- let oNode; // always the current node
22
+ let oNode; // always the current node
23
23
  const aInnerTree = []; // will contain the inner children
24
24
  const aReturnNodes = []; // the nodes array which will returned
25
25
  // 1. loop through all root nodes, store tree content locally so we don't touch the tree structure
@@ -39,7 +39,7 @@ function searchTree(aTree, fCompair, bGreedy) {
39
39
  // find other objects, 1. check all properties of the node if they are arrays
40
40
  for (const keysNode in oNode) {
41
41
  // true if the property is an array
42
- if (oNode[keysNode] instanceof Array) {
42
+ if (Array.isArray(oNode[keysNode])) {
43
43
  // 2. push all array object to aInnerTree to search in those later
44
44
  for (let i = 0; i < oNode[keysNode].length; i++) {
45
45
  aInnerTree.push(oNode[keysNode][i]);
@@ -62,17 +62,17 @@ function searchTree(aTree, fCompair, bGreedy) {
62
62
  */
63
63
  function extractAllCriteriaRefs(initialCriteria) {
64
64
  const criteriaRefs = [];
65
- initialCriteria.forEach(criteria => {
66
- var _a;
67
- (_a = criteria.criterion) === null || _a === void 0 ? void 0 : _a.forEach((criterion) => {
68
- if (criterion['@_test_ref']) {
69
- criteriaRefs.push(criterion['@_test_ref']);
65
+ for (const criteria of initialCriteria) {
66
+ if (criteria.criterion)
67
+ for (const criterion of criteria.criterion) {
68
+ if (criterion['@_test_ref']) {
69
+ criteriaRefs.push(criterion['@_test_ref']);
70
+ }
70
71
  }
71
- });
72
72
  if (criteria.criteria) {
73
73
  criteriaRefs.push(...extractAllCriteriaRefs(criteria.criteria));
74
74
  }
75
- });
75
+ }
76
76
  return criteriaRefs;
77
77
  }
78
78
  /**
@@ -94,7 +94,6 @@ function extractAllCriteriaRefs(initialCriteria) {
94
94
  * criteria references and resolved values, or `undefined` if no OVAL string is provided.
95
95
  */
96
96
  function processOVAL(oval) {
97
- var _a;
98
97
  const logger = (0, logging_1.createWinstonLogger)('ts-inspec-objects');
99
98
  if (!oval) {
100
99
  return undefined;
@@ -106,18 +105,15 @@ function processOVAL(oval) {
106
105
  for (const definition of definitionList.definition) {
107
106
  extractedDefinitions[definition['@_id']] = definition;
108
107
  extractedDefinitions[definition['@_id']].criteriaRefs = extractAllCriteriaRefs(definition.criteria);
109
- extractedDefinitions[definition['@_id']].resolvedValues = (_a = extractedDefinitions[definition['@_id']].criteriaRefs) === null || _a === void 0 ? void 0 : _a.map((criteriaRef) => {
108
+ extractedDefinitions[definition['@_id']].resolvedValues = extractedDefinitions[definition['@_id']].criteriaRefs?.map((criteriaRef) => {
110
109
  // Extract the original criteria from the oval file
111
110
  const foundCriteriaRefererence = searchTree(parsed.oval_definitions[0].tests, (oNode) => oNode['@_id'] === criteriaRef, false)[0];
112
111
  const foundObjects = [];
113
112
  const foundStates = [];
114
113
  if (foundCriteriaRefererence) {
115
114
  if (foundCriteriaRefererence.object) {
116
- foundCriteriaRefererence.object.forEach((object) => {
117
- if (!object['@_object_ref']) {
118
- logger.warn(`Found object without object_ref in test ${criteriaRef}`);
119
- }
120
- else {
115
+ for (const object of foundCriteriaRefererence.object) {
116
+ if (object['@_object_ref']) {
121
117
  const objectRef = object['@_object_ref'];
122
118
  const foundObjectReference = searchTree(parsed.oval_definitions[0].objects, (oNode) => oNode['@_id'] === objectRef, false)[0];
123
119
  if (foundObjectReference) {
@@ -127,14 +123,14 @@ function processOVAL(oval) {
127
123
  logger.warn(`Could not find object ${objectRef} for test ${criteriaRef}`);
128
124
  }
129
125
  }
130
- });
126
+ else {
127
+ logger.warn(`Found object without object_ref in test ${criteriaRef}`);
128
+ }
129
+ }
131
130
  }
132
131
  if (foundCriteriaRefererence.state) {
133
- foundCriteriaRefererence.state.forEach((state) => {
134
- if (!state['@_state_ref']) {
135
- logger.warn(`Found state without state_ref in test ${criteriaRef}`);
136
- }
137
- else {
132
+ for (const state of foundCriteriaRefererence.state) {
133
+ if (state['@_state_ref']) {
138
134
  const stateRef = state['@_state_ref'];
139
135
  const foundStateReference = searchTree(parsed.oval_definitions[0].states, (oNode) => oNode['@_id'] === stateRef, false)[0];
140
136
  if (foundStateReference) {
@@ -144,11 +140,14 @@ function processOVAL(oval) {
144
140
  logger.warn(`Could not find state ${stateRef} for test ${criteriaRef}`);
145
141
  }
146
142
  }
147
- });
143
+ else {
144
+ logger.warn(`Found state without state_ref in test ${criteriaRef}`);
145
+ }
146
+ }
148
147
  }
149
148
  }
150
149
  return { ...foundCriteriaRefererence, resolvedObjects: foundObjects, resolvedStates: foundStates };
151
- }).filter((value) => value);
150
+ }).filter(Boolean);
152
151
  }
153
152
  }
154
153
  }
@@ -1,6 +1,6 @@
1
1
  import Profile from '../objects/profile';
2
- import { BenchmarkGroup, BenchmarkRule, RuleComplexCheck } from '../types/xccdf';
3
2
  import { OvalDefinitionValue } from '../types/oval';
3
+ import { BenchmarkGroup, BenchmarkRule, RuleComplexCheck } from '../types/xccdf';
4
4
  export type GroupContextualizedRule = BenchmarkRule & {
5
5
  group: Omit<BenchmarkGroup, 'Rule' | 'Group'>;
6
6
  };
@@ -4,13 +4,13 @@ exports.extractAllRules = extractAllRules;
4
4
  exports.extractAllComplexChecks = extractAllComplexChecks;
5
5
  exports.processXCCDF = processXCCDF;
6
6
  const tslib_1 = require("tslib");
7
- const profile_1 = tslib_1.__importDefault(require("../objects/profile"));
8
- const xccdf_1 = require("../utilities/xccdf");
9
- const control_1 = tslib_1.__importDefault(require("../objects/control"));
7
+ const htmlfy_1 = require("htmlfy");
10
8
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
11
- const CciNistMappingData_1 = require("../mappings/CciNistMappingData");
12
- const pretty_1 = tslib_1.__importDefault(require("pretty"));
9
+ const cci_nist_mapping_data_1 = require("../mappings/cci-nist-mapping-data");
10
+ const control_1 = tslib_1.__importDefault(require("../objects/control"));
11
+ const profile_1 = tslib_1.__importDefault(require("../objects/profile"));
13
12
  const logging_1 = require("../utilities/logging");
13
+ const xccdf_1 = require("../utilities/xccdf");
14
14
  /**
15
15
  * Extracts all rules from the given benchmark groups, including nested groups.
16
16
  *
@@ -19,19 +19,19 @@ const logging_1 = require("../utilities/logging");
19
19
  */
20
20
  function extractAllRules(groups) {
21
21
  const rules = [];
22
- groups.forEach((group) => {
22
+ for (const group of groups) {
23
23
  if (group.Rule) {
24
24
  rules.push(...(group.Rule.map((rule) => {
25
25
  return {
26
26
  ...rule,
27
- group: lodash_1.default.omit(group, ['Rule', 'Group'])
27
+ group: lodash_1.default.omit(group, ['Rule', 'Group']),
28
28
  };
29
29
  })));
30
30
  }
31
31
  if (group.Group) {
32
32
  rules.push(...extractAllRules(group.Group));
33
33
  }
34
- });
34
+ }
35
35
  return rules;
36
36
  }
37
37
  /**
@@ -47,10 +47,10 @@ function extractAllRules(groups) {
47
47
  function extractAllComplexChecks(complexCheck) {
48
48
  const complexChecks = [lodash_1.default.omit(complexCheck, 'complex-check')];
49
49
  if (complexCheck['complex-check']) {
50
- complexChecks.push(...complexCheck['complex-check'].map((subComplexCheck) => lodash_1.default.omit(subComplexCheck, 'complex-check')));
51
- complexCheck['complex-check'].forEach((subComplexCheck) => {
50
+ complexChecks.push(...complexCheck['complex-check'].map(subComplexCheck => lodash_1.default.omit(subComplexCheck, 'complex-check')));
51
+ for (const subComplexCheck of complexCheck['complex-check']) {
52
52
  complexChecks.push(...extractAllComplexChecks(subComplexCheck));
53
- });
53
+ }
54
54
  }
55
55
  return complexChecks;
56
56
  }
@@ -70,9 +70,9 @@ function extractAllComplexChecks(complexCheck) {
70
70
  function ensureDecodedXMLStringValue(input, defaultValue) {
71
71
  return lodash_1.default.isString(input)
72
72
  ? input
73
- : lodash_1.default.isArray(input)
73
+ : (lodash_1.default.isArray(input)
74
74
  ? lodash_1.default.get(input, '[0].#text', defaultValue)
75
- : lodash_1.default.get(input, '#text', defaultValue);
75
+ : lodash_1.default.get(input, '#text', defaultValue));
76
76
  }
77
77
  /**
78
78
  * Processes an XCCDF (Extensible Configuration Checklist Description Format) XML
@@ -101,31 +101,31 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
101
101
  // Variable used to store the profile data.
102
102
  // The name is the benchmark Id, title and summary are from benchmark.
103
103
  const profile = new profile_1.default({
104
- //name: parsedXML.Benchmark[0]['@_id'],
104
+ // name: parsedXML.Benchmark[0]['@_id'],
105
105
  // title: (parsedXML.Benchmark[0].title[0] as FrontMatter)['#text'],
106
106
  // summary: (parsedXML.Benchmark[0].description[0] as RationaleElement)['#text']
107
107
  name: Array.isArray(parsedXML.Benchmark[0]['@_id'])
108
- ? parsedXML.Benchmark[0]['@_id'].map(n => n['@_id']).join(' ') === ''
108
+ ? (parsedXML.Benchmark[0]['@_id'].map(n => n['@_id']).join(' ') === ''
109
109
  ? parsedXML.Benchmark[0]['@_id'].map(n => n).join(' ')
110
- : parsedXML.Benchmark[0]['@_id'].join(' ')
110
+ : parsedXML.Benchmark[0]['@_id'].join(' '))
111
111
  : parsedXML.Benchmark[0]['@_id'],
112
112
  title: Array.isArray(parsedXML.Benchmark[0].title)
113
- ? parsedXML.Benchmark[0].title.map(t => t['#text']).join(' ') === ''
113
+ ? (parsedXML.Benchmark[0].title.map(t => t['#text']).join(' ') === ''
114
114
  ? parsedXML.Benchmark[0].title.map(t => t).join(' ')
115
- : parsedXML.Benchmark[0].title.map(t => t['#text']).join(' ')
115
+ : parsedXML.Benchmark[0].title.map(t => t['#text']).join(' '))
116
116
  : parsedXML.Benchmark[0].title,
117
117
  summary: Array.isArray(parsedXML.Benchmark[0].description)
118
118
  ? parsedXML.Benchmark[0].description.map(d => d['#text']).join(' ') === ''
119
+ // eslint-disable-next-line unicorn/no-nested-ternary
119
120
  ? parsedXML.Benchmark[0].description.map(d => d['p'] || '').join(' ') === ''
120
121
  ? parsedXML.Benchmark[0].description.map(d => d).join(' ')
121
122
  : parsedXML.Benchmark[0].description.map(d => d['p'] || '').join(' ')
122
123
  : parsedXML.Benchmark[0].description.map(d => d['#text']).join(' ')
123
- : parsedXML.Benchmark[0].description
124
+ : parsedXML.Benchmark[0].description,
124
125
  });
125
126
  // Process each rule, extracting the necessary
126
127
  // data and save it to the profile variable.
127
- rules.forEach(rule => {
128
- var _a, _b, _c;
128
+ for (const rule of rules) {
129
129
  // The description tag contains the following tags:
130
130
  // "FalsePositives", "FalseNegatives", "Documentable", "Mitigations",
131
131
  // "SeverityOverrideGuidance", "PotentialImpacts", "ThirdPartyTools",
@@ -137,12 +137,12 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
137
137
  }
138
138
  else {
139
139
  if (typeof lodash_1.default.get(rule.description, '[0].p') === 'string') {
140
- extractedDescription = (0, pretty_1.default)(lodash_1.default.get(rule.description, '[0].p'));
140
+ extractedDescription = (0, htmlfy_1.prettify)(lodash_1.default.get(rule.description, '[0].p'));
141
141
  }
142
142
  else {
143
143
  if (Array.isArray(lodash_1.default.get(rule.description, '[0].p'))) {
144
144
  const joinedDescriptions = lodash_1.default.get(rule.description, '[0].p');
145
- extractedDescription = (0, pretty_1.default)(joinedDescriptions.join('\n\n'));
145
+ extractedDescription = (0, htmlfy_1.prettify)(joinedDescriptions.join('\n\n'));
146
146
  extractedDescription = (0, xccdf_1.removeHtmlTags)(extractedDescription).replace('\n', ' ');
147
147
  }
148
148
  else if (Array.isArray(rule.description)) {
@@ -161,25 +161,23 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
161
161
  const control = new control_1.default();
162
162
  // Update the control Id with the appropriate value based on the rule id.
163
163
  switch (useRuleId) {
164
- case 'group':
164
+ case 'group': {
165
165
  control.id = rule.group['@_id'].toString();
166
166
  break;
167
- case 'rule':
168
- if (rule['@_id'][0].toLowerCase().startsWith('sv')) {
169
- control.id = rule['@_id'][0].split('r')[0];
170
- }
171
- else {
172
- control.id = rule['@_id'][0];
173
- }
167
+ }
168
+ case 'rule': {
169
+ control.id = rule['@_id'][0].toLowerCase().startsWith('sv') ? rule['@_id'][0].split('r')[0] : rule['@_id'][0];
174
170
  break;
175
- case 'version':
176
- if (rule.version !== undefined) {
177
- control.id = (lodash_1.default.isArray(rule.version)) ? rule.version[0] : rule.version;
171
+ }
172
+ case 'version': {
173
+ if (rule.version === undefined) {
174
+ throw new Error('The rule type "version" did not provide an identification (Id) value');
178
175
  }
179
176
  else {
180
- throw new Error('The rule type "version" did not provide an identification (Id) value');
177
+ control.id = (lodash_1.default.isArray(rule.version)) ? rule.version[0] : rule.version;
181
178
  }
182
179
  break;
180
+ }
183
181
  case 'cis': {
184
182
  // Regex explained
185
183
  // \d:
@@ -203,8 +201,9 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
203
201
  }
204
202
  break;
205
203
  }
206
- default:
204
+ default: {
207
205
  throw new Error('useRuleId must be one of "group", "rule", "version" for STIG benchmarks, or "cis" for CIS benchmarks');
206
+ }
208
207
  }
209
208
  if (!(lodash_1.default.isArray(rule.title) && rule.title.length === 1)) {
210
209
  throw new Error('Rule title is not an array of length 1. Investigate if the file is in the proper format.');
@@ -217,7 +216,7 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
217
216
  : `[[[MISSING SEVERITY or WEIGHT FROM BENCHMARK]]] ${ensureDecodedXMLStringValue(rule.title[0], 'undefined title')}`);
218
217
  // Update the control description (desc) with the extracted description content
219
218
  if (typeof extractedDescription === 'object' && !Array.isArray(extractedDescription)) {
220
- control.desc = ((_a = extractedDescription.VulnDiscussion) === null || _a === void 0 ? void 0 : _a.split('Satisfies: ')[0]) || '';
219
+ control.desc = extractedDescription.VulnDiscussion?.split('Satisfies: ')[0] || '';
221
220
  }
222
221
  else if (typeof extractedDescription === 'object') {
223
222
  control.desc = JSON.stringify(extractedDescription);
@@ -236,11 +235,11 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
236
235
  }
237
236
  // Update the control descriptions (descs) check with the check text from the rule,
238
237
  if (rule.check) {
239
- if (rule.check.some((ruleValue) => 'check-content' in ruleValue)) {
238
+ if (rule.check.some(ruleValue => 'check-content' in ruleValue)) {
240
239
  control.descs.check = (0, xccdf_1.removeXMLSpecialCharacters)(rule.check ? rule.check[0]['check-content'][0] : 'Missing description');
241
240
  control.tags.check_id = rule.check[0]['@_system'];
242
241
  }
243
- else if (rule.check.some((ruleValue) => 'check-content-ref' in ruleValue) && ovalDefinitions) {
242
+ else if (rule.check.some(ruleValue => 'check-content-ref' in ruleValue) && ovalDefinitions) {
244
243
  let referenceID = null;
245
244
  for (const checkContent of rule.check) {
246
245
  if ('check-content-ref' in checkContent && checkContent['@_system'].includes('oval')) {
@@ -261,30 +260,28 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
261
260
  }
262
261
  }
263
262
  }
264
- // Very CIS specific
265
- else if (rule['complex-check']) {
263
+ else if (rule['complex-check']) { // Very CIS specific
266
264
  const checkTexts = [];
267
265
  for (const complexChecks of rule['complex-check']) {
268
266
  const allComplexChecks = extractAllComplexChecks(complexChecks);
269
267
  if (control.id === '1.1.1.5') {
270
268
  logger.info(allComplexChecks);
271
269
  }
272
- allComplexChecks.forEach((complexCheck) => {
270
+ for (const complexCheck of allComplexChecks) {
273
271
  if (complexCheck.check) {
274
- complexCheck.check.forEach((check) => {
275
- var _a;
276
- if ((_a = check['@_system']) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase().includes('oval')) {
272
+ for (const check of complexCheck.check) {
273
+ if (check['@_system']?.toString().toLowerCase().includes('oval')) {
277
274
  const ovalReference = check['check-content-ref'][0]['@_name'];
278
275
  if (!ovalDefinitions) {
279
276
  logger.warn(`Missing OVAL definitions! Unable to process OVAL reference: ${ovalReference}`);
280
277
  }
281
278
  else if (ovalReference && ovalReference in ovalDefinitions) {
282
- ovalDefinitions[ovalReference].resolvedValues.forEach((resolvedValue) => {
279
+ for (const resolvedValue of ovalDefinitions[ovalReference].resolvedValues) {
283
280
  const comment = resolvedValue['@_comment'];
284
281
  if (comment) {
285
282
  checkTexts.push(comment + '\n');
286
283
  }
287
- resolvedValue.resolvedObjects.forEach((resolvedObject) => {
284
+ for (const resolvedObject of resolvedValue.resolvedObjects) {
288
285
  // Try to find the associated state for a resolved object
289
286
  const resolvedId = resolvedObject['@_id'].split(':')[resolvedValue['@_id'].split(':').length - 1];
290
287
  if (resolvedId) {
@@ -294,18 +291,18 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
294
291
  }
295
292
  }
296
293
  checkTexts.push(JSON.stringify(lodash_1.default.pickBy(resolvedObject, (value, key) => !key.startsWith('@_')), null, 2));
297
- });
298
- });
294
+ }
295
+ }
299
296
  }
300
297
  }
301
298
  else {
302
299
  logger.warn(`Found external reference to unknown system: ${check['@_system']}, only OVAL is supported`);
303
300
  }
304
- });
301
+ }
305
302
  }
306
- });
303
+ }
307
304
  }
308
- if (checkTexts.length >= 1) {
305
+ if (checkTexts.length > 0) {
309
306
  control.descs.check = checkTexts.join('\n');
310
307
  }
311
308
  }
@@ -314,7 +311,7 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
314
311
  if (lodash_1.default.get(rule.fixtext, '[0]["#text"]')) {
315
312
  control.descs.fix = (0, xccdf_1.removeXMLSpecialCharacters)(rule.fixtext[0]['#text']);
316
313
  }
317
- else if (typeof rule.fixtext === 'undefined') {
314
+ else if (rule.fixtext === undefined) {
318
315
  if (rule.fix && rule.fix[0]) {
319
316
  control.descs.fix = (0, xccdf_1.removeHtmlTags)(rule.fix[0]['#text'] || 'Missing fix text');
320
317
  }
@@ -323,19 +320,11 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
323
320
  control.descs.fix = (0, xccdf_1.removeHtmlTags)(rule.fixtext[0]);
324
321
  }
325
322
  else if (typeof rule.fixtext[0] === 'object') {
326
- if (Array.isArray(rule.fixtext[0])) {
327
- control.descs.fix = (0, xccdf_1.removeHtmlTags)((0, pretty_1.default)((0, xccdf_1.convertJsonIntoXML)(rule.fixtext[0].map((fixtext) => {
328
- if (fixtext.div) {
329
- return fixtext.div;
330
- }
331
- else {
332
- return fixtext;
333
- }
334
- }))));
335
- }
336
- else {
337
- control.descs.fix = (0, xccdf_1.removeHtmlTags)((0, xccdf_1.removeXMLSpecialCharacters)((0, pretty_1.default)((0, xccdf_1.convertJsonIntoXML)(rule.fixtext)))).replace('\n', ' ').trim();
338
- }
323
+ control.descs.fix = Array.isArray(rule.fixtext[0])
324
+ ? (0, xccdf_1.removeHtmlTags)((0, htmlfy_1.prettify)((0, xccdf_1.convertJsonIntoXML)(rule.fixtext[0].map((fixtext) => {
325
+ return fixtext.div || fixtext;
326
+ }))))
327
+ : (0, xccdf_1.removeHtmlTags)((0, xccdf_1.removeXMLSpecialCharacters)((0, htmlfy_1.prettify)((0, xccdf_1.convertJsonIntoXML)(rule.fixtext)))).replace('\n', ' ').trim();
339
328
  }
340
329
  else {
341
330
  control.descs.fix = 'Missing fix text';
@@ -365,8 +354,8 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
365
354
  // "SeverityOverrideGuidance", "PotentialImpacts", "ThirdPartyTools",
366
355
  // "MitigationControl", "Responsibility", "IAControls"
367
356
  if (typeof extractedDescription === 'object') {
368
- control.tags.satisfies =
369
- ((_b = extractedDescription.VulnDiscussion) === null || _b === void 0 ? void 0 : _b.includes('Satisfies: ')) && extractedDescription.VulnDiscussion.split('Satisfies: ').length >= 1
357
+ control.tags.satisfies
358
+ = extractedDescription.VulnDiscussion?.includes('Satisfies: ') && extractedDescription.VulnDiscussion.split('Satisfies: ').length > 0
370
359
  ? extractedDescription.VulnDiscussion.split('Satisfies: ')[1].split(',').map(satisfaction => satisfaction.trim())
371
360
  : undefined;
372
361
  control.tags.false_negatives = extractedDescription.FalseNegatives || undefined;
@@ -384,7 +373,7 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
384
373
  control.tags.ia_controls = extractedDescription.IAControls || undefined;
385
374
  }
386
375
  // Ensure that tags inside the tags array are not an array
387
- control.tags = lodash_1.default.mapValues(lodash_1.default.omitBy(control.tags, (value) => value === undefined), (value) => {
376
+ control.tags = lodash_1.default.mapValues(lodash_1.default.omitBy(control.tags, value => value === undefined), (value) => {
388
377
  if (value && Array.isArray(value)) {
389
378
  if (Array.isArray(value[0])) {
390
379
  return (0, xccdf_1.removeXMLSpecialCharacters)(value[0][0]);
@@ -405,110 +394,106 @@ function processXCCDF(xml, removeNewlines, useRuleId, ovalDefinitions) {
405
394
  });
406
395
  // Get all identifiers from the rule; cci, nist, and legacy
407
396
  if (rule.ident) {
408
- rule.ident.forEach((identifier) => {
409
- var _a, _b, _c;
397
+ for (const identifier of rule.ident) {
410
398
  // Get CCIs
411
399
  if (identifier['@_system'][0].toLowerCase().includes('cci')) {
412
400
  if (!('cci' in control.tags)) {
413
401
  control.tags.cci = [];
414
402
  }
415
- (_a = control.tags.cci) === null || _a === void 0 ? void 0 : _a.push(identifier['#text']);
403
+ control.tags.cci?.push(identifier['#text']);
416
404
  }
417
- // Get legacy identifiers
418
- else if (identifier['@_system'][0].toLowerCase().includes('legacy')) {
405
+ else if (identifier['@_system'][0].toLowerCase().includes('legacy')) { // Get legacy identifiers
419
406
  if (!('legacy' in control.tags)) {
420
407
  control.tags.legacy = [];
421
408
  }
422
- (_b = control.tags.legacy) === null || _b === void 0 ? void 0 : _b.push(identifier['#text']);
409
+ control.tags.legacy?.push(identifier['#text']);
423
410
  }
424
- // Get NIST identifiers
425
- else if (identifier['@_system'].toString().toLowerCase().includes('nist')) {
411
+ else if (identifier['@_system'].toString().toLowerCase().includes('nist')) { // Get NIST identifiers
426
412
  if (!('nist' in control.tags)) {
427
413
  control.tags.nist = [];
428
414
  }
429
- (_c = control.tags.nist) === null || _c === void 0 ? void 0 : _c.push(identifier['#text']);
415
+ control.tags.nist?.push(identifier['#text']);
430
416
  }
431
- });
417
+ }
432
418
  }
433
419
  // Update control references with content from the benchmark rule object
434
- (_c = rule.reference) === null || _c === void 0 ? void 0 : _c.forEach((reference) => {
435
- var _a, _b, _c, _d, _e;
436
- if (lodash_1.default.get(reference, '@_href') === '') {
437
- (_a = control.refs) === null || _a === void 0 ? void 0 : _a.push(lodash_1.default.get(reference, '#text', 'undefined href'));
438
- }
439
- else {
440
- try {
441
- const referenceText = lodash_1.default.get(reference, '#text') || '';
442
- const referenceURL = lodash_1.default.get(reference, '@_href') || '';
443
- if (referenceURL) {
444
- const parsedURL = new URL(lodash_1.default.get(reference, '@_href', 'undefined href'));
445
- if (parsedURL.protocol.toLowerCase().includes('http') || parsedURL.protocol.toLowerCase().includes('https')) {
446
- (_b = control.refs) === null || _b === void 0 ? void 0 : _b.push({
447
- ref: referenceText,
448
- url: referenceURL
449
- });
450
- }
451
- else {
452
- (_c = control.refs) === null || _c === void 0 ? void 0 : _c.push({
453
- ref: referenceText,
454
- uri: referenceURL
455
- });
456
- }
457
- }
458
- else {
459
- if ('title' in reference) {
460
- const title = lodash_1.default.get(reference, 'title');
461
- if (Array.isArray(title)) {
462
- (_d = control.refs) === null || _d === void 0 ? void 0 : _d.push(title[0]);
420
+ if (rule.reference)
421
+ for (const reference of rule.reference) {
422
+ if (lodash_1.default.get(reference, '@_href') === '') {
423
+ control.refs?.push(lodash_1.default.get(reference, '#text', 'undefined href'));
424
+ }
425
+ else {
426
+ try {
427
+ const referenceText = lodash_1.default.get(reference, '#text') || '';
428
+ const referenceURL = lodash_1.default.get(reference, '@_href') || '';
429
+ if (referenceURL) {
430
+ const parsedURL = new URL(lodash_1.default.get(reference, '@_href', 'undefined href'));
431
+ if (parsedURL.protocol.toLowerCase().includes('http') || parsedURL.protocol.toLowerCase().includes('https')) {
432
+ control.refs?.push({
433
+ ref: referenceText,
434
+ url: referenceURL,
435
+ });
463
436
  }
464
437
  else {
465
- (_e = control.refs) === null || _e === void 0 ? void 0 : _e.push(lodash_1.default.get(reference, 'title'));
438
+ control.refs?.push({
439
+ ref: referenceText,
440
+ uri: referenceURL,
441
+ });
466
442
  }
467
443
  }
468
- }
469
- // Add the reference to the control tags when separated by §
470
- if (typeof referenceText === 'string' && referenceText.indexOf('§') !== -1) {
471
- const referenceParts = referenceText.split('§');
472
- if (referenceParts.length == 2) {
473
- // eslint-disable-next-line prefer-const
474
- let [identifierType, identifier] = referenceText.split('§');
475
- identifierType = identifierType.toLowerCase();
476
- if (!(identifierType in control.tags)) {
477
- control.tags[identifierType] = [identifier];
444
+ else {
445
+ if ('title' in reference) {
446
+ const title = lodash_1.default.get(reference, 'title');
447
+ if (Array.isArray(title)) {
448
+ control.refs?.push(title[0]);
449
+ }
450
+ else {
451
+ control.refs?.push(lodash_1.default.get(reference, 'title'));
452
+ }
478
453
  }
479
- else if (Array.isArray(control.tags[identifierType])) {
480
- control.tags[identifierType] = lodash_1.default.union(control.tags[identifierType], [identifier]);
454
+ }
455
+ // Add the reference to the control tags when separated by §
456
+ if (typeof referenceText === 'string' && referenceText.includes('§')) {
457
+ const referenceParts = referenceText.split('§');
458
+ if (referenceParts.length == 2) {
459
+ // eslint-disable-next-line prefer-const
460
+ let [identifierType, identifier] = referenceText.split('§');
461
+ identifierType = identifierType.toLowerCase();
462
+ if (!(identifierType in control.tags)) {
463
+ control.tags[identifierType] = [identifier];
464
+ }
465
+ else if (Array.isArray(control.tags[identifierType])) {
466
+ control.tags[identifierType] = lodash_1.default.union(control.tags[identifierType], [identifier]);
467
+ }
468
+ else {
469
+ logger.warn(`Attempted to push identifier to control tags when identifier already exists: ${identifierType}: ${identifier}`);
470
+ }
481
471
  }
482
472
  else {
483
- logger.warn(`Attempted to push identifier to control tags when identifier already exists: ${identifierType}: ${identifier}`);
473
+ logger.warn('Reference parts of invalid length: ', referenceParts);
484
474
  }
485
475
  }
486
- else {
487
- logger.warn('Reference parts of invalid length: ', referenceParts);
488
- }
489
476
  }
490
- }
491
- catch (e) {
492
- logger.warn(`Error parsing ref for control ${control.id}: `);
493
- logger.warn(JSON.stringify(reference, null, 2));
494
- logger.warn(e);
477
+ catch (error) {
478
+ logger.warn(`Error parsing ref for control ${control.id}: `);
479
+ logger.warn(JSON.stringify(reference, null, 2));
480
+ logger.warn(error);
481
+ }
495
482
  }
496
483
  }
497
- });
498
484
  // Associate any CCIs with NIST tags
499
485
  if (control.tags.cci) {
500
- control.tags.cci.forEach((cci) => {
501
- var _a;
486
+ for (const cci of control.tags.cci) {
502
487
  if (!('nist' in control.tags)) {
503
488
  control.tags.nist = [];
504
489
  }
505
- if (cci in CciNistMappingData_1.data) {
506
- (_a = control.tags.nist) === null || _a === void 0 ? void 0 : _a.push(lodash_1.default.get(CciNistMappingData_1.data, cci));
490
+ if (cci in cci_nist_mapping_data_1.data) {
491
+ control.tags.nist?.push(lodash_1.default.get(cci_nist_mapping_data_1.data, cci));
507
492
  }
508
- });
493
+ }
509
494
  }
510
495
  profile.controls.push(control);
511
- });
496
+ }
512
497
  profile.controls = lodash_1.default.sortBy(profile.controls, 'id');
513
498
  return profile.toUnformattedObject();
514
499
  }