UNPKG

dd-trace

Version:

Datadog APM tracing client for JavaScript

129 lines (105 loc) 3.14 kB
'use strict' const log = require('../../../log') const { getMarkFromVulnerabilityType, CUSTOM_SECURE_MARK } = require('../taint-tracking/secure-marks') const SECURITY_CONTROL_DELIMITER = ';' const SECURITY_CONTROL_FIELD_DELIMITER = ':' const SECURITY_CONTROL_ELEMENT_DELIMITER = ',' const INPUT_VALIDATOR_TYPE = 'INPUT_VALIDATOR' const SANITIZER_TYPE = 'SANITIZER' const validTypes = new Set([INPUT_VALIDATOR_TYPE, SANITIZER_TYPE]) /** * @param {string} securityControlsConfiguration * @returns {Map<string, Array<{ * type: string, * secureMarks: number, * file: string, * method: string, * parameters: number[] | undefined * }>>} */ function parse (securityControlsConfiguration) { const controls = new Map() const potentialControls = securityControlsConfiguration .replaceAll(/[\r\n\t\v\f]*/g, '') .split(SECURITY_CONTROL_DELIMITER) for (const potentialControl of potentialControls) { const control = parseControl(potentialControl) if (control) { const fileControls = controls.get(control.file) if (fileControls) { fileControls.push(control) } else { controls.set(control.file, [control]) } } } return controls } /** * @param {string} control * @returns {{ * type: string, * secureMarks: number, * file: string, * method: string, * parameters: number[] | undefined * } | undefined} */ function parseControl (control) { if (!control) return const fields = control.split(SECURITY_CONTROL_FIELD_DELIMITER) if (fields.length < 3 || fields.length > 5) { log.warn('[ASM] Security control configuration is invalid: %s', control) return } let [type, marks, file, method, parameters] = fields type = type.trim().toUpperCase() if (!validTypes.has(type)) { log.warn('[ASM] Invalid security control type: %s', type) return } let secureMarks = CUSTOM_SECURE_MARK for (const mark of getSecureMarks(marks)) { secureMarks |= mark } if (secureMarks === CUSTOM_SECURE_MARK) { log.warn('[ASM] Invalid security control mark: %s', marks) return } file = file.trim() method = method?.trim() try { const parsedParameters = getParameters(parameters) return { type, secureMarks, file, method, parameters: parsedParameters } } catch { log.warn('[ASM] Invalid non-numeric security control parameter %s', parameters) } } /** * @param {string} marks * @returns {number[]} */ function getSecureMarks (marks) { return marks.split(SECURITY_CONTROL_ELEMENT_DELIMITER) .map(getMarkFromVulnerabilityType) .filter(Boolean) } /** * @param {string | undefined} parameters */ function getParameters (parameters) { return parameters?.split(SECURITY_CONTROL_ELEMENT_DELIMITER) .map(param => { const parsedParam = Number.parseInt(param, 10) // discard the securityControl if there is an incorrect parameter if (Number.isNaN(parsedParam)) { throw new TypeError('Invalid non-numeric security control parameter') } return parsedParam }) } module.exports = { parse, INPUT_VALIDATOR_TYPE, SANITIZER_TYPE, }