@mitre/inspec-objects 0.0.1 → 0.0.2

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.
@@ -0,0 +1,38 @@
1
+ name: Run TS-InSpec-Objects E2E Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-20.04
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+
16
+ - name: Cache node modules
17
+ uses: actions/cache@v2
18
+ env:
19
+ cache-name: cache-node-modules
20
+ with:
21
+ # npm cache files are stored in `~/.npm` on Linux/macOS
22
+ path: ~/.npm
23
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }}
24
+ restore-keys: |
25
+ ${{ runner.os }}-build-${{ env.cache-name }}-
26
+ ${{ runner.os }}-build-
27
+ ${{ runner.os }}-
28
+
29
+ - name: Setup Node.js
30
+ uses: actions/setup-node@v1
31
+ with:
32
+ node-version: '16.x'
33
+
34
+ - name: Install dependencies
35
+ run: npm install
36
+
37
+ - name: Run e2e tests
38
+ run: yarn test
package/error.log ADDED
@@ -0,0 +1,12 @@
1
+ yarn run v1.22.19
2
+ $ jest 2
3
+ No tests found, exiting with code 1
4
+ Run with `--passWithNoTests` to exit with code 0
5
+ In /home/c/Documents/SAF/ts-inspec-objects
6
+ 219 files checked.
7
+ testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 4 matches
8
+ testPathIgnorePatterns: /node_modules/ - 219 matches
9
+ testRegex: - 0 matches
10
+ Pattern: 2 - 0 matches
11
+ error Command failed with exit code 1.
12
+ info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
@@ -5,11 +5,15 @@ export default class Control {
5
5
  code?: string | null;
6
6
  desc?: string | null;
7
7
  descs?: ExecJSON.ControlDescription[] | {
8
- [key: string]: string;
8
+ [key: string]: string | undefined;
9
9
  } | null;
10
10
  impact?: number;
11
11
  ref?: string;
12
- refs?: string[];
12
+ refs?: (string | {
13
+ ref?: string;
14
+ url?: string;
15
+ uri?: string;
16
+ })[];
13
17
  tags: {
14
18
  check?: string;
15
19
  fix?: string;
@@ -19,7 +23,7 @@ export default class Control {
19
23
  satisfies?: string[];
20
24
  rid?: string;
21
25
  stig_id?: string;
22
- fix_id?: string;
26
+ fix_id?: string | null;
23
27
  cci?: string[];
24
28
  cis_controls?: Record<string, string[]>[];
25
29
  nist?: string[];
@@ -6,6 +6,8 @@ const flat_1 = require("flat");
6
6
  const global_1 = require("../utilities/global");
7
7
  class Control {
8
8
  constructor(data) {
9
+ this.tags = {};
10
+ this.refs = [];
9
11
  this.tags = {};
10
12
  if (data) {
11
13
  Object.entries(data).forEach(([key, value]) => {
@@ -55,7 +57,12 @@ class Control {
55
57
  }
56
58
  if (this.refs) {
57
59
  this.refs.forEach((ref) => {
58
- result += ` ref '${(0, global_1.escapeQuotes)(ref)}'\n`;
60
+ if (typeof ref === 'string') {
61
+ result += ` ref '${(0, global_1.escapeQuotes)(ref)}'\n`;
62
+ }
63
+ else {
64
+ result += ` ref '${(0, global_1.escapeQuotes)(ref.ref || '')}', url: '${(0, global_1.escapeQuotes)(ref.url || '')}'`;
65
+ }
59
66
  });
60
67
  }
61
68
  Object.entries(this.tags).forEach(([tag, value]) => {
@@ -0,0 +1,2 @@
1
+ import { OvalDefinitionValue } from '../types/oval';
2
+ export declare function processOVAL(oval: string): Record<string, OvalDefinitionValue>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processOVAL = void 0;
4
+ const xccdf_1 = require("../utilities/xccdf");
5
+ function processOVAL(oval) {
6
+ const parsed = (0, xccdf_1.convertEncodedXmlIntoJson)(oval);
7
+ const extractedDefinitions = {};
8
+ for (const ovalDefinitions of parsed.oval_definitions) {
9
+ for (const definitionList of ovalDefinitions.definitions) {
10
+ for (const definition of definitionList.definition) {
11
+ extractedDefinitions[definition["@_id"]] = definition;
12
+ }
13
+ }
14
+ }
15
+ return extractedDefinitions;
16
+ }
17
+ exports.processOVAL = processOVAL;
@@ -1,2 +1,8 @@
1
1
  import Profile from '../objects/profile';
2
- export declare function processXCCDF(xml: string): Profile;
2
+ import { BenchmarkGroup, BenchmarkRule } from '../types/xccdf';
3
+ import { OvalDefinitionValue } from '../types/oval';
4
+ export declare type GroupContextualizedRule = BenchmarkRule & {
5
+ group: Omit<BenchmarkGroup, 'Rule' | 'Group'>;
6
+ };
7
+ export declare function extractAllRules(groups: BenchmarkGroup[]): GroupContextualizedRule[];
8
+ export declare function processXCCDF(xml: string, ovalDefinitions?: Record<string, OvalDefinitionValue>): Profile;
@@ -1,67 +1,215 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.processXCCDF = void 0;
3
+ exports.processXCCDF = exports.extractAllRules = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const CciNistMappingData_1 = require("@mitre/hdf-converters/lib/src/mappings/CciNistMappingData");
6
5
  const profile_1 = tslib_1.__importDefault(require("../objects/profile"));
7
6
  const xccdf_1 = require("../utilities/xccdf");
8
7
  const control_1 = tslib_1.__importDefault(require("../objects/control"));
9
8
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
10
- function processXCCDF(xml) {
9
+ const hdf_converters_1 = require("@mitre/hdf-converters");
10
+ function extractAllRules(groups) {
11
+ const rules = [];
12
+ groups.forEach((group) => {
13
+ if (group.Rule) {
14
+ rules.push(...(group.Rule.map((rule) => {
15
+ return {
16
+ ...rule,
17
+ group: lodash_1.default.omit(group, ['Rule', 'Group'])
18
+ };
19
+ })));
20
+ }
21
+ if (group.Group) {
22
+ rules.push(...extractAllRules(group.Group));
23
+ }
24
+ });
25
+ return rules;
26
+ }
27
+ exports.extractAllRules = extractAllRules;
28
+ function processXCCDF(xml, ovalDefinitions) {
11
29
  const parsedXML = (0, xccdf_1.convertEncodedXmlIntoJson)(xml);
12
- const groups = parsedXML.Benchmark.Group;
30
+ const rules = extractAllRules(parsedXML.Benchmark[0].Group);
13
31
  const profile = new profile_1.default({
14
- name: parsedXML.Benchmark['@_id'],
15
- title: parsedXML.Benchmark.title,
16
- summary: parsedXML.Benchmark.description
32
+ name: parsedXML.Benchmark[0]['@_id'],
33
+ title: parsedXML.Benchmark[0].title[0]['#text'],
34
+ summary: parsedXML.Benchmark[0].description[0]['#text']
17
35
  });
18
- groups.forEach(group => {
36
+ rules.forEach(rule => {
19
37
  var _a, _b, _c;
20
- const extractedDescription = (0, xccdf_1.convertEncodedHTMLIntoJson)((_a = group.Rule) === null || _a === void 0 ? void 0 : _a.description);
21
- const control = new control_1.default({
22
- id: group['@_id'],
23
- title: group.Rule['@_severity'] ? group.Rule.title : `[[[MISSING SEVERITY FROM STIG]]] ${group.Rule.title}`,
24
- desc: (_b = extractedDescription.VulnDiscussion) === null || _b === void 0 ? void 0 : _b.split('Satisfies: ')[0],
25
- impact: (0, xccdf_1.severityStringToImpact)(group.Rule['@_severity'] || 'critical'),
26
- descs: {
27
- check: group.Rule.check['check-content'],
28
- fix: group.Rule.fixtext['#text']
29
- },
30
- tags: lodash_1.default.omitBy({
31
- severity: (0, xccdf_1.impactNumberToSeverityString)((0, xccdf_1.severityStringToImpact)(group.Rule['@_severity'] || 'critical')),
32
- gtitle: group.title,
33
- satisfies: ((_c = extractedDescription.VulnDiscussion) === null || _c === void 0 ? void 0 : _c.includes('Satisfies: ')) && extractedDescription.VulnDiscussion.split('Satisfies: ').length >= 1 ? extractedDescription.VulnDiscussion.split('Satisfies: ')[1].split(',').map(satisfaction => satisfaction.trim()) : undefined,
34
- gid: group['@_id'],
35
- rid: group.Rule['@_id'],
36
- stig_id: group.Rule.version,
37
- fix_id: group.Rule.fix['@_id'],
38
- false_negatives: extractedDescription.FalseNegatives,
39
- false_positives: extractedDescription.FalsePositives,
40
- documentable: extractedDescription.Documentable,
41
- mitigations: extractedDescription.Mitigations,
42
- severity_override_guidance: extractedDescription.SeverityOverrideGuidance,
43
- potential_impacts: extractedDescription.PotentialImpacts,
44
- third_party_tools: extractedDescription.ThirdPartyTools,
45
- mitigation_control: extractedDescription.MitigationControl,
46
- mitigation_controls: extractedDescription.MitigationControls,
47
- responsibility: extractedDescription.Responsibility,
48
- ia_controls: extractedDescription.IAControls
49
- }, i => !Boolean(i))
50
- });
51
- if ('ident' in group.Rule) {
52
- const identifiers = Array.isArray(group.Rule.ident) ? group.Rule.ident : [group.Rule.ident];
53
- // Grab CCI/NIST/Legacy identifiers
54
- identifiers.forEach(identifier => {
38
+ let extractedDescription;
39
+ if (Array.isArray(rule.description)) {
40
+ extractedDescription = rule.description[0]['#text'];
41
+ }
42
+ else {
43
+ extractedDescription = (0, xccdf_1.convertEncodedHTMLIntoJson)(rule.description);
44
+ }
45
+ const control = new control_1.default();
46
+ control.id = rule.group['@_id'];
47
+ control.title = rule['@_severity'] ? rule.title : `[[[MISSING SEVERITY FROM STIG]]] ${rule.title}`;
48
+ control.desc = typeof extractedDescription === 'string' ? extractedDescription : (_a = extractedDescription.VulnDiscussion) === null || _a === void 0 ? void 0 : _a.split('Satisfies: ')[0];
49
+ control.impact = (0, xccdf_1.severityStringToImpact)(rule['@_severity'] || 'critical', rule.group['@_id']);
50
+ if (!control.descs || Array.isArray(control.descs)) {
51
+ control.descs = {};
52
+ }
53
+ if (rule.check) {
54
+ if (rule.check.some((ruleValue) => 'check-content' in ruleValue)) {
55
+ control.descs.check = rule.check ? rule.check[0]['check-content'] : 'Missing description';
56
+ }
57
+ else if (rule.check.some((ruleValue) => 'check-content-ref' in ruleValue) && ovalDefinitions) {
58
+ let referenceID = null;
59
+ for (const checkContent of rule.check) {
60
+ if ('check-content-ref' in checkContent && checkContent['@_system'].includes('oval')) {
61
+ for (const checkContentRef of checkContent['check-content-ref']) {
62
+ if (checkContentRef['@_name']) {
63
+ referenceID = checkContentRef['@_name'];
64
+ }
65
+ }
66
+ }
67
+ }
68
+ if (referenceID && referenceID in ovalDefinitions) {
69
+ control.descs.check = ovalDefinitions[referenceID].metadata[0].title;
70
+ }
71
+ else if (referenceID) {
72
+ console.warn(`Could not find OVAL definition for ${referenceID}`);
73
+ }
74
+ }
75
+ }
76
+ control.descs.fix = rule.fixtext ? rule.fixtext[0]['#text'] : (rule.fix ? rule.fix[0]['#text'] || 'Missing fix text' : 'Missing fix text');
77
+ control.tags.severity = (0, xccdf_1.impactNumberToSeverityString)((0, xccdf_1.severityStringToImpact)(rule['@_severity'] || 'critical', control.id));
78
+ control.tags.gid = rule.group['@_id'],
79
+ control.tags.rid = rule['@_id'];
80
+ control.tags.stig_id = rule['version'];
81
+ if (typeof rule.group.title === "string") {
82
+ control.tags.gtitle = rule.group.title;
83
+ }
84
+ else {
85
+ control.tags.gtitle = lodash_1.default.get(rule.group, 'title[0].#text');
86
+ }
87
+ if (rule['fix'] && rule['fix'].length > 0) {
88
+ control.tags.fix_id = rule['fix'][0]['@_id'];
89
+ }
90
+ else {
91
+ control.tags.fix_id = null;
92
+ }
93
+ if (rule['rationale']) {
94
+ control.tags.rationale = rule['rationale'][0]['#text'];
95
+ }
96
+ else {
97
+ control.tags.rationale = null;
98
+ }
99
+ if (typeof extractedDescription === 'object') {
100
+ control.tags.satisfies = ((_b = extractedDescription.VulnDiscussion) === null || _b === void 0 ? void 0 : _b.includes('Satisfies: ')) && extractedDescription.VulnDiscussion.split('Satisfies: ').length >= 1 ? extractedDescription.VulnDiscussion.split('Satisfies: ')[1].split(',').map(satisfaction => satisfaction.trim()) : undefined;
101
+ control.tags.false_negatives = extractedDescription.FalseNegatives || undefined;
102
+ control.tags.false_positives = extractedDescription.FalsePositives || undefined;
103
+ control.tags.documentable = typeof extractedDescription.Documentable === 'boolean' ? extractedDescription.Documentable : undefined;
104
+ control.tags.mitigations = extractedDescription.Mitigations || undefined;
105
+ control.tags.severity_override_guidance = extractedDescription.SeverityOverrideGuidance || undefined;
106
+ control.tags.potential_impacts = extractedDescription.PotentialImpacts || undefined;
107
+ control.tags.third_party_tools = extractedDescription.ThirdPartyTools || undefined;
108
+ control.tags.mitigation_control = extractedDescription.MitigationControl || undefined;
109
+ control.tags.mitigation_controls = extractedDescription.MitigationControls || undefined;
110
+ control.tags.responsibility = extractedDescription.Responsibility || undefined;
111
+ control.tags.ia_controls = extractedDescription.IAControls || undefined;
112
+ }
113
+ control.tags = lodash_1.default.omitBy(control.tags, (value) => value === undefined);
114
+ // Get all identifiers from the rule
115
+ if (rule.ident) {
116
+ rule.ident.forEach((identifier) => {
55
117
  var _a, _b, _c;
56
- const identifierText = identifier['#text'];
57
- if (identifier['@_system'].toLowerCase().endsWith('cci')) {
58
- (_a = control.tags.cci) === null || _a === void 0 ? void 0 : _a.push(identifierText);
59
- if (identifierText in CciNistMappingData_1.data) {
60
- (_b = control.tags.nist) === null || _b === void 0 ? void 0 : _b.push(lodash_1.default.get(CciNistMappingData_1.data, identifierText));
118
+ // Get CCIs
119
+ if (identifier['@_system'].toLowerCase().includes('cci')) {
120
+ if (!('cci' in control.tags)) {
121
+ control.tags.cci = [];
122
+ }
123
+ (_a = control.tags.cci) === null || _a === void 0 ? void 0 : _a.push(identifier['#text']);
124
+ }
125
+ // Get legacy identifiers
126
+ else if (identifier['@_system'].toLowerCase().includes('legacy')) {
127
+ if (!('legacy' in control.tags)) {
128
+ control.tags.legacy = [];
61
129
  }
130
+ (_b = control.tags.legacy) === null || _b === void 0 ? void 0 : _b.push(identifier['#text']);
131
+ }
132
+ // Get NIST identifiers
133
+ else if (identifier['@_system'].toLowerCase().includes('nist')) {
134
+ if (!('nist' in control.tags)) {
135
+ control.tags.nist = [];
136
+ }
137
+ (_c = control.tags.nist) === null || _c === void 0 ? void 0 : _c.push(identifier['#text']);
138
+ }
139
+ else {
140
+ // console.log('Alert')
141
+ // console.log(identifier['@_system'])
142
+ // console.log(identifier['#text'])
143
+ }
144
+ });
145
+ }
146
+ (_c = rule.reference) === null || _c === void 0 ? void 0 : _c.forEach((reference) => {
147
+ var _a, _b, _c, _d;
148
+ if (lodash_1.default.get(reference, '@_href') === '') {
149
+ (_a = control.refs) === null || _a === void 0 ? void 0 : _a.push(lodash_1.default.get(reference, '#text'));
150
+ }
151
+ else {
152
+ try {
153
+ const referenceText = lodash_1.default.get(reference, '#text') || '';
154
+ const referenceURL = lodash_1.default.get(reference, '@_href') || '';
155
+ if (referenceURL) {
156
+ const parsedURL = new URL(lodash_1.default.get(reference, '@_href'));
157
+ if (parsedURL.protocol.toLowerCase().includes('http') || parsedURL.protocol.toLowerCase().includes('https')) {
158
+ (_b = control.refs) === null || _b === void 0 ? void 0 : _b.push({
159
+ ref: referenceText,
160
+ url: referenceURL
161
+ });
162
+ }
163
+ else {
164
+ (_c = control.refs) === null || _c === void 0 ? void 0 : _c.push({
165
+ ref: referenceText,
166
+ uri: referenceURL
167
+ });
168
+ }
169
+ }
170
+ else {
171
+ if ('title' in reference) {
172
+ (_d = control.refs) === null || _d === void 0 ? void 0 : _d.push(lodash_1.default.get(reference, 'title'));
173
+ }
174
+ }
175
+ // Add the reference to the control tags when seperated by §
176
+ if (typeof referenceText === 'string' && referenceText.indexOf('§') !== -1) {
177
+ const referenceParts = referenceText.split('§');
178
+ if (referenceParts.length == 2) {
179
+ let [identifierType, identifier] = referenceText.split('§');
180
+ identifierType = identifierType.toLowerCase();
181
+ if (!(identifierType in control.tags)) {
182
+ control.tags[identifierType] = [identifier];
183
+ }
184
+ else if (Array.isArray(control.tags[identifierType])) {
185
+ control.tags[identifierType] = lodash_1.default.union(control.tags[identifierType], [identifier]);
186
+ }
187
+ else {
188
+ console.warn(`Attempted to push identifier to control tags when identifier already exists: ${identifierType}: ${identifier}`);
189
+ }
190
+ }
191
+ else {
192
+ console.warn("Reference parts of invalid length:");
193
+ console.log(referenceParts);
194
+ }
195
+ }
196
+ }
197
+ catch (e) {
198
+ console.warn(`Error parsing ref for control ${control.id}: `);
199
+ console.warn(JSON.stringify(reference, null, 2));
200
+ console.warn(e);
201
+ }
202
+ }
203
+ });
204
+ // Associate any CCIs with NIST tags
205
+ if (control.tags.cci) {
206
+ control.tags.cci.forEach((cci) => {
207
+ var _a;
208
+ if (!('nist' in control.tags)) {
209
+ control.tags.nist = [];
62
210
  }
63
- if (identifier['@_system'].toLowerCase().endsWith('legacy')) {
64
- (_c = control.tags.legacy) === null || _c === void 0 ? void 0 : _c.push(identifierText);
211
+ if (cci in hdf_converters_1.CciNistMappingData.data) {
212
+ (_a = control.tags.nist) === null || _a === void 0 ? void 0 : _a.push(lodash_1.default.get(hdf_converters_1.CciNistMappingData.data, cci));
65
213
  }
66
214
  });
67
215
  }
@@ -1,3 +1,5 @@
1
1
  import Profile from '../objects/profile';
2
2
  import { ProfileDiff } from '../types/diff';
3
+ import Control from '../objects/control';
4
+ export declare function updateControl(originalControlString: string, originalControl: Control, updatedControl: Control): void;
3
5
  export declare function diffProfile(fromProfile: Profile, toProfile: Profile): ProfileDiff;
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.diffProfile = void 0;
3
+ exports.diffProfile = exports.updateControl = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const json_diff_1 = require("json-diff");
6
6
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
7
+ function updateControl(originalControlString, originalControl, updatedControl) {
8
+ console.log('Here is the original control:');
9
+ }
10
+ exports.updateControl = updateControl;
7
11
  function diffProfile(fromProfile, toProfile) {
8
12
  const profileDiff = {
9
13
  addedControlIDs: [],
@@ -14,7 +18,7 @@ function diffProfile(fromProfile, toProfile) {
14
18
  const toControlIDs = toProfile.controls.map((control) => control.id).sort();
15
19
  // Find new controls
16
20
  const controlIDDiff = (0, json_diff_1.diff)(fromControlIDs, toControlIDs);
17
- controlIDDiff.forEach((diffValue) => {
21
+ controlIDDiff === null || controlIDDiff === void 0 ? void 0 : controlIDDiff.forEach((diffValue) => {
18
22
  if (diffValue[0] === '-') {
19
23
  profileDiff.removedControlIDs.push(diffValue[1]);
20
24
  }
@@ -40,7 +44,7 @@ function diffProfile(fromProfile, toProfile) {
40
44
  lodash_1.default.set(profileDiff, 'changedControls.' + fromControl.id + '.' + key.replace('.', '\\.'), lodash_1.default.get(controlDiff, key + '.__new'));
41
45
  }
42
46
  else if (typeof value === 'object') {
43
- Object.entries(value).forEach(([subKey, subValue]) => {
47
+ Object.entries(value).forEach(([subKey]) => {
44
48
  lodash_1.default.set(profileDiff, 'changedControls.' + fromControl.id + '.' + key.replace('.', '\\.') + '.' + subKey.replace('.', '\\.'), lodash_1.default.get(controlDiff, key + '.' + subKey + '.__new'));
45
49
  });
46
50
  }
@@ -4,3 +4,5 @@ declare const escapeQuotes: (s: string) => string;
4
4
  declare const escapeDoubleQuotes: (s: string) => string;
5
5
  declare const wrapAndEscapeQuotes: (s: string, lineLength?: number) => string;
6
6
  export { escapeQuotes, escapeDoubleQuotes, wrapAndEscapeQuotes };
7
+ export declare function getFirstPath(object: Record<string, unknown>, paths: string[]): string;
8
+ export declare function hasPath(file: Record<string, unknown>, path: string | string[]): boolean;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.wrapAndEscapeQuotes = exports.escapeDoubleQuotes = exports.escapeQuotes = exports.unformatText = exports.wrap = void 0;
3
+ exports.hasPath = exports.getFirstPath = exports.wrapAndEscapeQuotes = exports.escapeDoubleQuotes = exports.escapeQuotes = exports.unformatText = exports.wrap = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
4
6
  // Breaks lines down to lineLength number of characters
5
7
  function wrap(s, lineLength = 80) {
6
8
  return s.replace(new RegExp(`(?![^\n]{1,${lineLength}}$)([^\n]{1,${lineLength}})`, "g"), "$1\n");
@@ -16,3 +18,24 @@ const escapeDoubleQuotes = (s) => s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
16
18
  exports.escapeDoubleQuotes = escapeDoubleQuotes;
17
19
  const wrapAndEscapeQuotes = (s, lineLength) => escapeDoubleQuotes(wrap(s, lineLength)); // Escape backslashes and quotes, and wrap long lines
18
20
  exports.wrapAndEscapeQuotes = wrapAndEscapeQuotes;
21
+ function getFirstPath(object, paths) {
22
+ const index = lodash_1.default.findIndex(paths, (p) => hasPath(object, p));
23
+ if (index === -1) {
24
+ throw new Error(`Attestation is missing one of these paths: ${paths.join(', ')}`);
25
+ }
26
+ else {
27
+ return lodash_1.default.get(object, paths[index]);
28
+ }
29
+ }
30
+ exports.getFirstPath = getFirstPath;
31
+ function hasPath(file, path) {
32
+ let pathArray;
33
+ if (typeof path === 'string') {
34
+ pathArray = [path];
35
+ }
36
+ else {
37
+ pathArray = path;
38
+ }
39
+ return lodash_1.default.some(pathArray, (p) => lodash_1.default.has(file, p));
40
+ }
41
+ exports.hasPath = hasPath;
@@ -1,5 +1,5 @@
1
1
  import { DecodedDescription } from '../types/xccdf';
2
2
  export declare function convertEncodedXmlIntoJson(encodedXml: string): any;
3
- export declare function severityStringToImpact(string: string): number;
3
+ export declare function severityStringToImpact(string: string, id: string): number;
4
4
  export declare function impactNumberToSeverityString(impact: number): string;
5
5
  export declare function convertEncodedHTMLIntoJson(encodedHTML?: string): DecodedDescription;
@@ -8,11 +8,13 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
8
8
  function convertEncodedXmlIntoJson(encodedXml) {
9
9
  return fast_xml_parser_1.default.parse(encodedXml, {
10
10
  ignoreAttributes: false,
11
+ ignoreNameSpace: true,
11
12
  attributeNamePrefix: '@_',
13
+ arrayMode: true
12
14
  });
13
15
  }
14
16
  exports.convertEncodedXmlIntoJson = convertEncodedXmlIntoJson;
15
- function severityStringToImpact(string) {
17
+ function severityStringToImpact(string, id) {
16
18
  var _a, _b, _c, _d, _e;
17
19
  if ((_a = string.match(/none|na|n\/a|not[\s()*_|]?applicable/i)) === null || _a === void 0 ? void 0 : _a.length) {
18
20
  return 0.0;
@@ -29,7 +31,8 @@ function severityStringToImpact(string) {
29
31
  if ((_e = string.match(/crit(ical)?|severe/)) === null || _e === void 0 ? void 0 : _e.length) {
30
32
  return 1.0;
31
33
  }
32
- throw new Error(`${string}' is not a valid severity value. It should be one of the approved keywords`);
34
+ console.log(`${string} is not a valid severity value. It should be one of the approved keywords. ${id} will be treated as medium severity`);
35
+ return 0.5;
33
36
  }
34
37
  exports.severityStringToImpact = severityStringToImpact;
35
38
  function impactNumberToSeverityString(impact) {
Binary file