Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v5.37.0 proposal #5281

Merged
merged 29 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7eee97e
Fix mongoose plugin tests (#5217)
iunanua Feb 10, 2025
80388bd
chore(graphql): only stringify graphql error extension attributes in …
wconti27 Feb 10, 2025
b80e636
[DSM] Add a wait for active stream to the putTestRecords function whi…
ericfirth Feb 10, 2025
11c7d52
dd-trace-api: don't proxy objects returned from callbacks (#5240)
bengl Feb 10, 2025
ead9421
datadog-plugin-mongoose test remove forgotten skip condition for vers…
iunanua Feb 11, 2025
71505fc
Extended iast location fields (#5171)
IlyasShabi Feb 11, 2025
598240d
Add troubleshooting link to profiler start error message (#5242)
szegedi Feb 11, 2025
c7db6f4
Upgrade ESLint from v8 to v9 (#5215)
watson Feb 11, 2025
fb71f8d
change RASP addresses from persistent to ephemeral (#5235)
simon-id Feb 11, 2025
1c62331
Temporarily limit koa upstream tests to test against 2.15.3
watson Feb 12, 2025
5f694bc
Revert "Temporarily limit koa upstream tests to test against 2.15.3"
watson Feb 12, 2025
849ca50
remove semver and replace with simpler semifies (#5251)
rochdev Feb 12, 2025
a9a019f
[asm] IAST security controls (#5117)
iunanua Feb 12, 2025
8da5f7a
fix(config): keep the lookup value as passed (#5244)
tlhunter Feb 12, 2025
2f009db
prevent usage of semver in code (#5252)
rochdev Feb 12, 2025
b014bb9
[MLOB-2096] feat(llmobs): metadata and metrics annotations update ins…
sabrenner Feb 12, 2025
d7d1c55
dd-trace-api: remove runtime tests that should be test time (#5246)
bengl Feb 12, 2025
3f6c148
ESLint: Disallow warnings in CI (#5261)
watson Feb 13, 2025
15a8545
change telemetry name for dd-trace-api (#5264)
bengl Feb 13, 2025
785f1d0
fix(openai): update openai instrumentation for newest release (#5271)
sabrenner Feb 13, 2025
4f4b2e8
remove span kind from inferred proxy spans (#5265)
wconti27 Feb 14, 2025
569456f
Inject trace info as comment to MongoDB operation when dbm propagatio…
lu-zhengda Feb 14, 2025
791934c
Delete unused packages/memwatch/* directory (#5275)
watson Feb 14, 2025
2480ed2
fix(openai): apply span char limit truncation to chat completion inpu…
sabrenner Feb 14, 2025
26b3585
[DI] Add source map support (#5205)
watson Feb 17, 2025
09764cb
[test optimization] Fix session fingerprint in playwright (#5273)
juan-fernandez Feb 17, 2025
2615565
[test optimization] [SDTEST-1529] Add quarantined tests logic (#5236)
juan-fernandez Feb 17, 2025
7e04808
[DI] Use column number from source maps (#5279)
watson Feb 17, 2025
e3f43a4
v5.37.0
watson Feb 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ require,protobufjs,BSD-3-Clause,Copyright 2016 Daniel Wirtz
require,tlhunter-sorted-set,MIT,Copyright (c) 2023 Datadog Inc.
require,retry,MIT,Copyright 2011 Tim Koschützki Felix Geisendörfer
require,rfdc,MIT,Copyright 2019 David Mark Clements
require,semver,ISC,Copyright Isaac Z. Schlueter and Contributors
require,semifies,Apache license 2.0,Copyright Authors
require,shell-quote,mit,Copyright (c) 2013 James Halliday
require,source-map,BSD-3-Clause,Copyright (c) 2009-2011, Mozilla Foundation and contributors
require,ttl-set,MIT,Copyright (c) 2024 Thomas Watson
Expand Down Expand Up @@ -68,6 +68,7 @@ dev,nock,MIT,Copyright 2017 Pedro Teixeira and other contributors
dev,nyc,ISC,Copyright 2015 Contributors
dev,proxyquire,MIT,Copyright 2013 Thorsten Lorenz
dev,rimraf,ISC,Copyright Isaac Z. Schlueter and Contributors
dev,semver,ISC,Copyright Isaac Z. Schlueter and Contributors
dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
dev,tap,ISC,Copyright 2011-2022 Isaac Z. Schlueter and Contributors
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ services:
ports:
- "127.0.0.1:6379:6379"
mongo:
image: circleci/mongo:3.6
image: circleci/mongo:4.4
platform: linux/amd64
ports:
- "127.0.0.1:27017:27017"
Expand Down
28 changes: 28 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const compat = new FlatCompat({ baseDirectory: __dirname })

const SRC_FILES = [
'*.js',
'*.mjs',
'ext/**/*.js',
'ext/**/*.mjs',
'packages/*/src/**/*.js',
'packages/*/src/**/*.mjs'
]

const TEST_FILES = [
'packages/*/test/**/*.js',
'packages/*/test/**/*.mjs',
Expand All @@ -22,6 +31,7 @@ const TEST_FILES = [

export default [
{
name: 'dd-trace/global-ignore',
ignores: [
'**/coverage', // Just coverage reports.
'**/dist', // Generated
Expand All @@ -31,6 +41,8 @@ export default [
'**/versions', // This is effectively a node_modules tree.
'**/acmeair-nodejs', // We don't own this.
'**/vendor', // Generally, we didn't author this code.
'integration-tests/debugger/target-app/source-map-support/minify.min.js', // Generated
'integration-tests/debugger/target-app/source-map-support/typescript.js', // Generated
'integration-tests/esbuild/out.js', // Generated
'integration-tests/esbuild/aws-sdk-out.js', // Generated
'packages/dd-trace/src/appsec/blocked_templates.js', // TODO Why is this ignored?
Expand Down Expand Up @@ -82,6 +94,22 @@ export default [
...mocha.configs.flat.recommended,
files: TEST_FILES
},
{
name: 'dd-trace/src/all',
files: SRC_FILES,
rules: {
'n/no-restricted-require': ['error', [
{
name: 'diagnostics_channel',
message: 'Please use dc-polyfill instead.'
},
{
name: 'semver',
message: 'Please use semifies instead.'
}
]]
}
},
{
name: 'dd-trace/tests/all',
files: TEST_FILES,
Expand Down
5 changes: 5 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2226,6 +2226,11 @@ declare namespace tracer {
*/
redactionValuePattern?: string,

/**
* Allows to enable security controls.
*/
securityControlsConfiguration?: string,

/**
* Specifies the verbosity of the sent telemetry. Default 'INFORMATION'
*/
Expand Down
69 changes: 69 additions & 0 deletions integration-tests/appsec/esm-security-controls/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use strict'

import childProcess from 'node:child_process'
import express from 'express'
import { sanitize } from './sanitizer.mjs'
import sanitizeDefault from './sanitizer-default.mjs'
import { validate, validateNotConfigured } from './validator.mjs'

const app = express()
const port = process.env.APP_PORT || 3000

app.get('/cmdi-s-secure', (req, res) => {
const command = sanitize(req.query.command)
try {
childProcess.execSync(command)
} catch (e) {
// ignore
}

res.end()
})

app.get('/cmdi-s-secure-comparison', (req, res) => {
const command = sanitize(req.query.command)
try {
childProcess.execSync(command)
} catch (e) {
// ignore
}

try {
childProcess.execSync(req.query.command)
} catch (e) {
// ignore
}

res.end()
})

app.get('/cmdi-s-secure-default', (req, res) => {
const command = sanitizeDefault(req.query.command)
try {
childProcess.execSync(command)
} catch (e) {
// ignore
}

res.end()
})

app.get('/cmdi-iv-insecure', (req, res) => {
if (validateNotConfigured(req.query.command)) {
childProcess.execSync(req.query.command)
}

res.end()
})

app.get('/cmdi-iv-secure', (req, res) => {
if (validate(req.query.command)) {
childProcess.execSync(req.query.command)
}

res.end()
})

app.listen(port, () => {
process.send({ port })
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict'

function sanitizeDefault (input) {
return input
}

export default sanitizeDefault
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict'

export function sanitize (input) {
return input
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict'

export function validate (input) {
return true
}

export function validateNotConfigured (input) {
return true
}
126 changes: 126 additions & 0 deletions integration-tests/appsec/iast.esm-security-controls.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
'use strict'

const { createSandbox, spawnProc, FakeAgent } = require('../helpers')
const path = require('path')
const getPort = require('get-port')
const Axios = require('axios')
const { assert } = require('chai')

describe('ESM Security controls', () => {
let axios, sandbox, cwd, appPort, appFile, agent, proc

before(async function () {
this.timeout(process.platform === 'win32' ? 90000 : 30000)
sandbox = await createSandbox(['express'])
appPort = await getPort()
cwd = sandbox.folder
appFile = path.join(cwd, 'appsec', 'esm-security-controls', 'index.mjs')

axios = Axios.create({
baseURL: `http://localhost:${appPort}`
})
})

after(async function () {
await sandbox.remove()
})

const nodeOptions = '--import dd-trace/initialize.mjs'

beforeEach(async () => {
agent = await new FakeAgent().start()

proc = await spawnProc(appFile, {
cwd,
env: {
DD_TRACE_AGENT_PORT: agent.port,
APP_PORT: appPort,
DD_IAST_ENABLED: 'true',
DD_IAST_REQUEST_SAMPLING: '100',
// eslint-disable-next-line no-multi-str
DD_IAST_SECURITY_CONTROLS_CONFIGURATION: '\
SANITIZER:COMMAND_INJECTION:appsec/esm-security-controls/sanitizer.mjs:sanitize;\
SANITIZER:COMMAND_INJECTION:appsec/esm-security-controls/sanitizer-default.mjs;\
INPUT_VALIDATOR:*:appsec/esm-security-controls/validator.mjs:validate',
NODE_OPTIONS: nodeOptions
}
})
})

afterEach(async () => {
proc.kill()
await agent.stop()
})

it('test endpoint with iv not configured does have COMMAND_INJECTION vulnerability', async function () {
await axios.get('/cmdi-iv-insecure?command=ls -la')

await agent.assertMessageReceived(({ payload }) => {
const spans = payload.flatMap(p => p.filter(span => span.name === 'express.request'))
spans.forEach(span => {
assert.property(span.meta, '_dd.iast.json')
assert.include(span.meta['_dd.iast.json'], '"COMMAND_INJECTION"')
})
}, null, 1, true)
})

it('test endpoint sanitizer does not have COMMAND_INJECTION vulnerability', async () => {
await axios.get('/cmdi-s-secure?command=ls -la')

await agent.assertMessageReceived(({ payload }) => {
const spans = payload.flatMap(p => p.filter(span => span.name === 'express.request'))
spans.forEach(span => {
assert.notProperty(span.meta, '_dd.iast.json')
assert.property(span.metrics, '_dd.iast.telemetry.suppressed.vulnerabilities.command_injection')
})
}, null, 1, true)
})

it('test endpoint with default sanitizer does not have COMMAND_INJECTION vulnerability', async () => {
await axios.get('/cmdi-s-secure-default?command=ls -la')

await agent.assertMessageReceived(({ payload }) => {
const spans = payload.flatMap(p => p.filter(span => span.name === 'express.request'))
spans.forEach(span => {
assert.notProperty(span.meta, '_dd.iast.json')
assert.property(span.metrics, '_dd.iast.telemetry.suppressed.vulnerabilities.command_injection')
})
}, null, 1, true)
})

it('test endpoint with default sanitizer does have COMMAND_INJECTION with original tainted', async () => {
await axios.get('/cmdi-s-secure-comparison?command=ls -la')

await agent.assertMessageReceived(({ payload }) => {
const spans = payload.flatMap(p => p.filter(span => span.name === 'express.request'))
spans.forEach(span => {
assert.property(span.meta, '_dd.iast.json')
assert.include(span.meta['_dd.iast.json'], '"COMMAND_INJECTION"')
})
}, null, 1, true)
})

it('test endpoint with default sanitizer does have COMMAND_INJECTION vulnerability', async () => {
await axios.get('/cmdi-s-secure-default?command=ls -la')

await agent.assertMessageReceived(({ payload }) => {
const spans = payload.flatMap(p => p.filter(span => span.name === 'express.request'))
spans.forEach(span => {
assert.notProperty(span.meta, '_dd.iast.json')
assert.property(span.metrics, '_dd.iast.telemetry.suppressed.vulnerabilities.command_injection')
})
}, null, 1, true)
})

it('test endpoint with iv does not have COMMAND_INJECTION vulnerability', async () => {
await axios.get('/cmdi-iv-secure?command=ls -la')

await agent.assertMessageReceived(({ payload }) => {
const spans = payload.flatMap(p => p.filter(span => span.name === 'express.request'))
spans.forEach(span => {
assert.notProperty(span.meta, '_dd.iast.json')
assert.property(span.metrics, '_dd.iast.telemetry.suppressed.vulnerabilities.command_injection')
})
}, null, 1, true)
})
})
Loading
Loading