Skip to content

Commit cd42868

Browse files
authored
test(appsec): avoid shell execution in taint tracking tests (#9657)
The taint propagation matrix armed a one-second trace deadline before each synchronous shell command. One Windows invocation blocked the event loop for 3.293 seconds, so the web span could not flush before the expectation expired.
1 parent 1de6f49 commit cd42868

3 files changed

Lines changed: 22 additions & 20 deletions

File tree

packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-impl.spec.js

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const { storage } = require('../../../../../datadog-core')
88
const iastContextFunctions = require('../../../../src/appsec/iast/iast-context')
99
const { newTaintedString, isTainted, getRanges } = require('../../../../src/appsec/iast/taint-tracking/operations')
1010
const { clearCache } = require('../../../../src/appsec/iast/vulnerability-reporter')
11-
const { prepareTestServerForIast, copyFileToTmp } = require('../utils')
11+
const { prepareTestServerForIast, copyFileToTmp, invokeCommandInjectionSink } = require('../utils')
1212
const propagationFns = [
1313
'appendStr',
1414
'arrayInVariableJoin',
@@ -78,12 +78,7 @@ describe('TaintTracking', () => {
7878
const commandResultOrig = propFnOriginal(commandTainted)
7979
assert.strictEqual(commandResult, commandResultOrig)
8080

81-
try {
82-
const childProcess = require('child_process')
83-
childProcess.execSync(commandResult, { stdio: 'ignore' })
84-
} catch {
85-
// do nothing
86-
}
81+
invokeCommandInjectionSink(commandResult)
8782
}, 'COMMAND_INJECTION')
8883
})
8984
})
@@ -117,12 +112,7 @@ describe('TaintTracking', () => {
117112
const resultOrig = propFnOriginal(jsonTainted)
118113
assert.deepStrictEqual(result, resultOrig)
119114

120-
try {
121-
const childProcess = require('child_process')
122-
childProcess.execSync(result.command, { stdio: 'ignore' })
123-
} catch {
124-
// do nothing
125-
}
115+
invokeCommandInjectionSink(result.command)
126116
}, 'COMMAND_INJECTION')
127117
})
128118
})

packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking.lodash.plugin.spec.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const { storage } = require('../../../../../datadog-core')
1010
const iastContextFunctions = require('../../../../src/appsec/iast/iast-context')
1111
const { newTaintedString, isTainted } = require('../../../../src/appsec/iast/taint-tracking/operations')
1212
const { clearCache } = require('../../../../src/appsec/iast/vulnerability-reporter')
13-
const { prepareTestServerForIast, copyFileToTmp } = require('../utils')
13+
const { prepareTestServerForIast, copyFileToTmp, invokeCommandInjectionSink } = require('../utils')
1414
const commands = [
1515
' ls -la ',
1616
' ls -la',
@@ -68,12 +68,7 @@ describe('TaintTracking lodash', () => {
6868
const commandResultOrig = propFnOriginal(_, commandTainted)
6969
assert.strictEqual(commandResult, commandResultOrig)
7070

71-
try {
72-
const childProcess = require('child_process')
73-
childProcess.execSync(commandResult, { stdio: 'ignore' })
74-
} catch {
75-
// do nothing
76-
}
71+
invokeCommandInjectionSink(commandResult)
7772
}, 'COMMAND_INJECTION')
7873
})
7974
})

packages/dd-trace/test/appsec/iast/utils.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,22 @@ function copyFileToTmp (src) {
120120
return dest
121121
}
122122

123+
/**
124+
* @param {string} command
125+
*/
126+
function invokeCommandInjectionSink (command) {
127+
const childProcess = require('node:child_process')
128+
129+
// The tracing start hook runs before Node rejects cwd, avoiding a child process.
130+
assert.throws(
131+
() => childProcess.execSync(command, { cwd: '\0' }),
132+
{
133+
code: 'ERR_INVALID_ARG_VALUE',
134+
message: /without null bytes/,
135+
}
136+
)
137+
}
138+
123139
function beforeEachIastTest (iastConfig) {
124140
iastConfig = iastConfig || {
125141
enabled: true,
@@ -530,6 +546,7 @@ module.exports = {
530546
testOutsideRequestHasVulnerability,
531547
testInRequest,
532548
copyFileToTmp,
549+
invokeCommandInjectionSink,
533550
prepareTestServerForIast,
534551
prepareTestServerForIastInExpress,
535552
prepareTestServerForIastInFastify,

0 commit comments

Comments
 (0)