@hclsoftware/secagent
Version:
IAST agent
144 lines (118 loc) • 4.38 kB
JavaScript
//IASTIGNORE
/*
* ****************************************************
* Licensed Materials - Property of HCL.
* (c) Copyright HCL Technologies Ltd. 2017, 2025.
* Note to U.S. Government Users *Restricted Rights.
* ****************************************************
*/
'use strict'
const Entity = require('./Entity')
const TaskType = require('./Tasks/TaskType')
const Utils = require('./Utils/Utils')
const {keys} = require("./AdditionalInfo");
const lodash = require("lodash");
class TaintedObjectDataFlow {
constructor(requestInfo, entityName, entityValue, entityType) {
this.requestInfo = requestInfo
this.sanitized = []
this.entity = new Entity.Entity(entityName, entityValue, entityType)
this.stackInfoList = []
this.taskList = []
this.hasSanitationTask = false
this.hasValidationTask = false
this.reported = new Set()
this.hashValue = null
this.stackArray = null
this.stackString = null
this.sinkStackString = null
this.additionalInfo = {}
this.storedDataForTelemetryIssue = null
}
isTaintedForVulnerability(vulnerability) {
return this.isTainted() && !this.sanitized.origArrayIncludes(vulnerability)
}
getCopy() {
const copy = new TaintedObjectDataFlow(this.requestInfo, this.entity.name,
this.entity.value, this.entity.type)
copy.sanitized = [...this.sanitized]
copy.stackInfoList = [...this.stackInfoList]
copy.taskList = [...this.taskList]
copy.hasSanitationTask = this.hasSanitationTask
copy.hasValidationTask = this.hasValidationTask
copy.additionalInfo = lodash.cloneDeep(this.additionalInfo);
copy.storedDataForTelemetryIssue = this.storedDataForTelemetryIssue === null ? null : Object.assign({}, this.storedDataForTelemetryIssue);
return copy
}
addToTaskList(task) {
if (task.type === TaskType.VALIDATION) {
this.hasValidationTask = true
} else if (task.type === TaskType.SANITIZATION) {
this.hasSanitationTask = true
}
this.taskList.push(task)
}
addToStackInfoList(stackInfo) {
this.stackInfoList.push(stackInfo)
}
sanitize(vulnerability) {
this.sanitized.push(vulnerability)
}
isReported(vulnerability) { return this.reported.has(vulnerability) }
addToReported(vulnerability) { this.reported.add(vulnerability) }
getHashValue() { return this.hashValue }
getStackArray() { return this.stackArray }
getStackString() {
if (this.stackString == null) {
this.stackString = JSON.origStringify(this.stackArray)
}
return this.stackString
}
updateEntity(entityName, entityValue, entityType) {
this.entity = new Entity.Entity(entityName, entityValue, entityType)
}
updateStackAndHashForReporting(vulnerability) {
let hash = Utils.createHashObject()
const jsonOutput = []
if (this.requestInfo.routePath !== undefined)
hash.update(this.requestInfo.routePath)
else if (this.requestInfo.uri !== undefined)
hash.update(this.requestInfo.uri)
if (this.requestInfo.method !== undefined) { hash.update(this.requestInfo.method) }
if (vulnerability != null) { hash.update(vulnerability) }
if (this.entity.type !== undefined) { hash.update(this.entity.type) }
if (this.entity.name !== undefined) { hash.update(this.entity.name) }
for (const item of this.stackInfoList) {
// must update stack before its hash:
item.updateStack()
jsonOutput.push(item)
hash.update(item.updateHash(vulnerability))
}
// update values in flow
this.stackArray = jsonOutput
this.hashValue = hash.produce() // The Hash object can not be used again after hash.digest() method has been called. Multiple calls will cause an error to be thrown
}
getSinkStackString() {
return this.sinkStackString
}
setSinkStackString(sinkStackString) {
this.sinkStackString = sinkStackString
}
addAdditionalInfo(info) {
Object.assign(this.additionalInfo, info)
}
addAdditionalInfoElementToArray(info) {
for (const property in info) {
if (!this.additionalInfo.hasOwnProperty(property)) {
this.additionalInfo[property] = [info[property]]
}
else {
this.additionalInfo[property].push(info[property])
}
}
}
isTainted() {
return this.additionalInfo[keys.SANITIZED] === undefined
}
}
module.exports = TaintedObjectDataFlow