Socket
Socket
Sign inDemoInstall

dd-trace

Package Overview
Dependencies
Maintainers
1
Versions
574
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dd-trace - npm Package Compare versions

Comparing version 6.0.0-pre-09455e6 to 6.0.0-pre-0f36e48

packages/datadog-instrumentations/src/helpers/fetch.js

9

package.json
{
"name": "dd-trace",
"version": "6.0.0-pre-09455e6",
"version": "6.0.0-pre-0f36e48",
"description": "Datadog APM tracing client for JavaScript",

@@ -39,2 +39,3 @@ "main": "index.js",

"test:integration:playwright": "mocha --colors --timeout 30000 \"integration-tests/playwright/*.spec.js\"",
"test:integration:selenium": "mocha --colors --timeout 30000 \"integration-tests/selenium/*.spec.js\"",
"test:integration:profiler": "mocha --colors --timeout 90000 \"integration-tests/profiler/*.spec.js\"",

@@ -73,7 +74,7 @@ "test:integration:serverless": "mocha --colors --timeout 30000 \"integration-tests/serverless/*.spec.js\"",

"dependencies": {
"@datadog/native-appsec": "7.1.0",
"@datadog/native-appsec": "7.1.1",
"@datadog/native-iast-rewriter": "2.3.0",
"@datadog/native-iast-taint-tracking": "1.7.0",
"@datadog/native-metrics": "^2.0.0",
"@datadog/pprof": "5.1.0",
"@datadog/pprof": "5.2.0",
"@datadog/sketches-js": "^2.1.0",

@@ -100,3 +101,3 @@ "@opentelemetry/api": "^1.0.0",

"path-to-regexp": "^0.1.2",
"pprof-format": "^2.0.7",
"pprof-format": "^2.1.0",
"protobufjs": "^7.2.5",

@@ -103,0 +104,0 @@ "retry": "^0.13.1",

'use strict'
const shimmer = require('../../datadog-shimmer')
const { channel } = require('./helpers/instrument')
const { tracingChannel } = require('dc-polyfill')
const { createWrapFetch } = require('./helpers/fetch')
const startChannel = channel('apm:fetch:request:start')
const finishChannel = channel('apm:fetch:request:finish')
const errorChannel = channel('apm:fetch:request:error')
if (globalThis.fetch) {
const ch = tracingChannel('apm:fetch:request')
const wrapFetch = createWrapFetch(globalThis.Request, ch)
function wrapFetch (fetch, Request) {
if (typeof fetch !== 'function') return fetch
return function (input, init) {
if (!startChannel.hasSubscribers) return fetch.apply(this, arguments)
const req = new Request(input, init)
const headers = req.headers
const message = { req, headers }
return startChannel.runStores(message, () => {
// Request object is read-only so we need new objects to change headers.
arguments[0] = message.req
arguments[1] = { headers: message.headers }
return fetch.apply(this, arguments)
.then(
res => {
message.res = res
finishChannel.publish(message)
return res
},
err => {
if (err.name !== 'AbortError') {
message.error = err
errorChannel.publish(message)
}
finishChannel.publish(message)
throw err
}
)
})
}
globalThis.fetch = shimmer.wrap(fetch, wrapFetch(fetch))
}
if (globalThis.fetch) {
globalThis.fetch = shimmer.wrap(fetch, wrapFetch(fetch, globalThis.Request))
}

@@ -61,2 +61,3 @@ 'use strict'

'jest-jasmine2': () => require('../jest'),
'jest-runtime': () => require('../jest'),
'jest-worker': () => require('../jest'),

@@ -107,4 +108,5 @@ knex: () => require('../knex'),

router: () => require('../router'),
'selenium-webdriver': () => require('../selenium'),
sequelize: () => require('../sequelize'),
sharedb: () => require('../sharedb'),
sequelize: () => require('../sequelize'),
tedious: () => require('../tedious'),

@@ -111,0 +113,0 @@ when: () => require('../when'),

@@ -14,3 +14,4 @@ 'use strict'

addEfdStringToTestName,
removeEfdStringFromTestName
removeEfdStringFromTestName,
getIsFaultyEarlyFlakeDetection
} = require('../../dd-trace/src/plugins/util/test')

@@ -48,2 +49,5 @@ const {

// Message sent by jest's main process to workers to run a test suite (=test file)
// https://github.com/jestjs/jest/blob/1d682f21c7a35da4d3ab3a1436a357b980ebd0fa/packages/jest-worker/src/types.ts#L37
const CHILD_MESSAGE_CALL = 1
// Maximum time we'll wait for the tracer to flush

@@ -53,3 +57,3 @@ const FLUSH_TIMEOUT = 10000

let skippableSuites = []
let knownTests = []
let knownTests = {}
let isCodeCoverageEnabled = false

@@ -64,2 +68,4 @@ let isSuitesSkippingEnabled = false

let earlyFlakeDetectionNumRetries = 0
let earlyFlakeDetectionFaultyThreshold = 30
let isEarlyFlakeDetectionFaulty = false
let hasFilteredSkippableSuites = false

@@ -80,2 +86,3 @@

const retriedTestsToNumAttempts = new Map()
const newTestsTestStatuses = new Map()

@@ -109,2 +116,9 @@ // based on https://github.com/facebook/jest/blob/main/packages/jest-circus/src/formatNodeAssertErrors.ts#L41

function getEfdStats (testStatuses) {
return testStatuses.reduce((acc, testStatus) => {
acc[testStatus]++
return acc
}, { pass: 0, fail: 0 })
}
function getWrappedEnvironment (BaseEnvironment, jestVersion) {

@@ -119,2 +133,3 @@ return class DatadogEnvironment extends BaseEnvironment {

this.global._ddtrace = global._ddtrace
this.hasSnapshotTests = undefined

@@ -133,5 +148,8 @@ this.displayName = config.projectConfig?.displayName?.name

if (this.isEarlyFlakeDetectionEnabled) {
const hasKnownTests = !!knownTests.jest
earlyFlakeDetectionNumRetries = this.testEnvironmentOptions._ddEarlyFlakeDetectionNumRetries
try {
this.knownTestsForThisSuite = this.getKnownTestsForSuite(this.testEnvironmentOptions._ddKnownTests)
this.knownTestsForThisSuite = hasKnownTests
? (knownTests.jest[this.testSuite] || [])
: this.getKnownTestsForSuite(this.testEnvironmentOptions._ddKnownTests)
} catch (e) {

@@ -144,2 +162,17 @@ // If there has been an error parsing the tests, we'll disable Early Flake Deteciton

getHasSnapshotTests () {
if (this.hasSnapshotTests !== undefined) {
return this.hasSnapshotTests
}
let hasSnapshotTests = true
try {
const { _snapshotData } = this.context.expect.getState().snapshotState
hasSnapshotTests = Object.keys(_snapshotData).length > 0
} catch (e) {
// if we can't be sure, we'll err on the side of caution and assume it has snapshots
}
this.hasSnapshotTests = hasSnapshotTests
return hasSnapshotTests
}
// Function that receives a list of known tests for a test service and

@@ -157,3 +190,3 @@ // returns the ones that belong to the current suite

}
return knownTestsForSuite.jest?.[this.testSuite] || []
return knownTestsForSuite
}

@@ -230,2 +263,9 @@

retriedTestsToNumAttempts.set(testName, 0)
// Retrying snapshots has proven to be problematic, so we'll skip them for now
// We'll still detect new tests, but we won't retry them.
// TODO: do not bail out of EFD with the whole test suite
if (this.getHasSnapshotTests()) {
log.warn('Early flake detection is disabled for suites with snapshots')
return
}
for (let retryIndex = 0; retryIndex < earlyFlakeDetectionNumRetries; retryIndex++) {

@@ -256,2 +296,15 @@ if (this.global.test) {

event.test.fn = originalTestFns.get(event.test)
// We'll store the test statuses of the retries
if (this.isEarlyFlakeDetectionEnabled) {
const testName = getJestTestName(event.test)
const originalTestName = removeEfdStringFromTestName(testName)
const isNewTest = retriedTestsToNumAttempts.has(originalTestName)
if (isNewTest) {
if (newTestsTestStatuses.has(originalTestName)) {
newTestsTestStatuses.get(originalTestName).push(status)
} else {
newTestsTestStatuses.set(originalTestName, [status])
}
}
}
})

@@ -300,3 +353,3 @@ }

itrSkippedSuitesCh.publish({ skippedSuites: jestSuitesToRun.skippedSuites, frameworkVersion })
skippableSuites = []
return jestSuitesToRun.suitesToRun

@@ -399,2 +452,3 @@ }

earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold
}

@@ -514,2 +568,3 @@ } catch (err) {

isEarlyFlakeDetectionEnabled,
isEarlyFlakeDetectionFaulty,
onDone

@@ -526,2 +581,24 @@ })

/**
* If Early Flake Detection (EFD) is enabled the logic is as follows:
* - If all attempts for a test are failing, the test has failed and we will let the test process fail.
* - If just a single attempt passes, we will prevent the test process from failing.
* The rationale behind is the following: you may still be able to block your CI pipeline by gating
* on flakiness (the test will be considered flaky), but you may choose to unblock the pipeline too.
*/
if (isEarlyFlakeDetectionEnabled) {
let numFailedTestsToIgnore = 0
for (const testStatuses of newTestsTestStatuses.values()) {
const { pass, fail } = getEfdStats(testStatuses)
if (pass > 0) { // as long as one passes, we'll consider the test passed
numFailedTestsToIgnore += fail
}
}
// If every test that failed was an EFD retry, we'll consider the suite passed
if (numFailedTestsToIgnore !== 0 && result.results.numFailedTests === numFailedTestsToIgnore) {
result.results.success = true
}
}
return result

@@ -638,3 +715,2 @@ })

config.testEnvironmentOptions._ddTestCodeCoverageEnabled = isCodeCoverageEnabled
config.testEnvironmentOptions._ddKnownTests = knownTests
})

@@ -732,9 +808,22 @@

shimmer.wrap(SearchSource.prototype, 'getTestPaths', getTestPaths => async function () {
if (!isSuitesSkippingEnabled || !skippableSuites.length) {
return getTestPaths.apply(this, arguments)
const testPaths = await getTestPaths.apply(this, arguments)
const [{ rootDir, shard }] = arguments
if (isEarlyFlakeDetectionEnabled) {
const projectSuites = testPaths.tests.map(test => getTestSuitePath(test.path, test.context.config.rootDir))
const isFaulty =
getIsFaultyEarlyFlakeDetection(projectSuites, knownTests.jest || {}, earlyFlakeDetectionFaultyThreshold)
if (isFaulty) {
log.error('Early flake detection is disabled because the number of new suites is too high.')
isEarlyFlakeDetectionEnabled = false
const testEnvironmentOptions = testPaths.tests[0]?.context?.config?.testEnvironmentOptions
// Project config is shared among all tests, so we can modify it here
if (testEnvironmentOptions) {
testEnvironmentOptions._ddIsEarlyFlakeDetectionEnabled = false
}
isEarlyFlakeDetectionFaulty = true
}
}
const [{ rootDir, shard }] = arguments
if (shard?.shardCount > 1) {
if (shard?.shardCount > 1 || !isSuitesSkippingEnabled || !skippableSuites.length) {
// If the user is using jest sharding, we want to apply the filtering of tests in the shard process.

@@ -747,6 +836,4 @@ // The reason for this is the following:

// causing the shards to potentially run the same suite.
return getTestPaths.apply(this, arguments)
return testPaths
}
const testPaths = await getTestPaths.apply(this, arguments)
const { tests } = testPaths

@@ -811,3 +898,31 @@

const LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = [
'selenium-webdriver'
]
function shouldBypassJestRequireEngine (moduleName) {
return (
LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE.some(library => moduleName.includes(library))
)
}
addHook({
name: 'jest-runtime',
versions: ['>=24.8.0']
}, (runtimePackage) => {
const Runtime = runtimePackage.default ? runtimePackage.default : runtimePackage
shimmer.wrap(Runtime.prototype, 'requireModuleOrMock', requireModuleOrMock => function (from, moduleName) {
// TODO: do this for every library that we instrument
if (shouldBypassJestRequireEngine(moduleName)) {
// To bypass jest's own require engine
return this._requireCoreModule(moduleName)
}
return requireModuleOrMock.apply(this, arguments)
})
return runtimePackage
})
addHook({
name: 'jest-worker',

@@ -818,2 +933,34 @@ versions: ['>=24.9.0'],

const ChildProcessWorker = childProcessWorker.default
shimmer.wrap(ChildProcessWorker.prototype, 'send', send => function (request) {
if (!isEarlyFlakeDetectionEnabled) {
return send.apply(this, arguments)
}
const [type] = request
// eslint-disable-next-line
// https://github.com/jestjs/jest/blob/1d682f21c7a35da4d3ab3a1436a357b980ebd0fa/packages/jest-worker/src/workers/ChildProcessWorker.ts#L424
if (type === CHILD_MESSAGE_CALL) {
// This is the message that the main process sends to the worker to run a test suite (=test file).
// In here we modify the config.testEnvironmentOptions to include the known tests for the suite.
// This way the suite only knows about the tests that are part of it.
const args = request[request.length - 1]
if (args.length > 1) {
return send.apply(this, arguments)
}
if (!args[0]?.config) {
return send.apply(this, arguments)
}
const [{ globalConfig, config, path: testSuiteAbsolutePath }] = args
const testSuite = getTestSuitePath(testSuiteAbsolutePath, globalConfig.rootDir || process.cwd())
const suiteKnownTests = knownTests.jest?.[testSuite] || []
args[0].config = {
...config,
testEnvironmentOptions: {
...config.testEnvironmentOptions,
_ddKnownTests: suiteKnownTests
}
}
}
return send.apply(this, arguments)
})
shimmer.wrap(ChildProcessWorker.prototype, '_onMessage', _onMessage => function () {

@@ -820,0 +967,0 @@ const [code, data] = arguments[0]

@@ -71,3 +71,6 @@ 'use strict'

result.then(
innerAsyncResource.bind(() => producerFinishCh.publish(undefined)),
innerAsyncResource.bind(res => {
producerFinishCh.publish(undefined)
producerCommitCh.publish(res)
}),
innerAsyncResource.bind(err => {

@@ -81,8 +84,2 @@ if (err) {

result.then(res => {
if (producerCommitCh.hasSubscribers) {
producerCommitCh.publish(res)
}
})
return result

@@ -89,0 +86,0 @@ } catch (e) {

@@ -24,3 +24,4 @@ 'use strict'

}, mongoose => {
if (mongoose.Promise !== global.Promise) {
// As of Mongoose 7, custom promise libraries are no longer supported and mongoose.Promise may be undefined
if (mongoose.Promise && mongoose.Promise !== global.Promise) {
shimmer.wrap(mongoose.Promise.prototype, 'then', wrapThen)

@@ -27,0 +28,0 @@ }

@@ -13,2 +13,94 @@ 'use strict'

const V4_PACKAGE_SHIMS = [
{
file: 'resources/chat/completions.js',
targetClass: 'Completions',
baseResource: 'chat.completions',
methods: ['create']
},
{
file: 'resources/completions.js',
targetClass: 'Completions',
baseResource: 'completions',
methods: ['create']
},
{
file: 'resources/embeddings.js',
targetClass: 'Embeddings',
baseResource: 'embeddings',
methods: ['create']
},
{
file: 'resources/files.js',
targetClass: 'Files',
baseResource: 'files',
methods: ['create', 'del', 'list', 'retrieve']
},
{
file: 'resources/files.js',
targetClass: 'Files',
baseResource: 'files',
methods: ['retrieveContent'],
versions: ['>=4.0.0 <4.17.1']
},
{
file: 'resources/files.js',
targetClass: 'Files',
baseResource: 'files',
methods: ['content'], // replaced `retrieveContent` in v4.17.1
versions: ['>=4.17.1']
},
{
file: 'resources/images.js',
targetClass: 'Images',
baseResource: 'images',
methods: ['createVariation', 'edit', 'generate']
},
{
file: 'resources/fine-tuning/jobs/jobs.js',
targetClass: 'Jobs',
baseResource: 'fine_tuning.jobs',
methods: ['cancel', 'create', 'list', 'listEvents', 'retrieve'],
versions: ['>=4.34.0'] // file location changed in 4.34.0
},
{
file: 'resources/fine-tuning/jobs.js',
targetClass: 'Jobs',
baseResource: 'fine_tuning.jobs',
methods: ['cancel', 'create', 'list', 'listEvents', 'retrieve'],
versions: ['>=4.1.0 <4.34.0']
},
{
file: 'resources/fine-tunes.js', // deprecated after 4.1.0
targetClass: 'FineTunes',
baseResource: 'fine-tune',
methods: ['cancel', 'create', 'list', 'listEvents', 'retrieve'],
versions: ['>=4.0.0 <4.1.0']
},
{
file: 'resources/models.js',
targetClass: 'Models',
baseResource: 'models',
methods: ['del', 'list', 'retrieve']
},
{
file: 'resources/moderations.js',
targetClass: 'Moderations',
baseResource: 'moderations',
methods: ['create']
},
{
file: 'resources/audio/transcriptions.js',
targetClass: 'Transcriptions',
baseResource: 'audio.transcriptions',
methods: ['create']
},
{
file: 'resources/audio/translations.js',
targetClass: 'Translations',
baseResource: 'audio.translations',
methods: ['create']
}
]
addHook({ name: 'openai', file: 'dist/api.js', versions: ['>=3.0.0 <4'] }, exports => {

@@ -52,1 +144,58 @@ const methodNames = Object.getOwnPropertyNames(exports.OpenAIApi.prototype)

})
for (const shim of V4_PACKAGE_SHIMS) {
const { file, targetClass, baseResource, methods } = shim
addHook({ name: 'openai', file, versions: shim.versions || ['>=4'] }, exports => {
const targetPrototype = exports[targetClass].prototype
for (const methodName of methods) {
shimmer.wrap(targetPrototype, methodName, methodFn => function () {
if (!startCh.hasSubscribers) {
return methodFn.apply(this, arguments)
}
const client = this._client || this.client
startCh.publish({
methodName: `${baseResource}.${methodName}`,
args: arguments,
basePath: client.baseURL,
apiKey: client.apiKey
})
const apiProm = methodFn.apply(this, arguments)
// wrapping `parse` avoids problematic wrapping of `then` when trying to call
// `withResponse` in userland code after. This way, we can return the whole `APIPromise`
shimmer.wrap(apiProm, 'parse', origApiPromParse => function () {
return origApiPromParse.apply(this, arguments)
// the original response is wrapped in a promise, so we need to unwrap it
.then(body => Promise.all([this.responsePromise, body]))
.then(([{ response, options }, body]) => {
finishCh.publish({
headers: response.headers,
body,
path: response.url,
method: options.method
})
return body
})
.catch(err => {
errorCh.publish({ err })
throw err
})
.finally(() => {
// maybe we don't want to unwrap here in case the promise is re-used?
// other hand: we want to avoid resource leakage
shimmer.unwrap(apiProm, 'parse')
})
})
return apiProm
})
}
return exports
})
}

@@ -24,3 +24,3 @@ 'use strict'

addHook({ name: 'oracledb', versions: ['5'] }, oracledb => {
addHook({ name: 'oracledb', versions: ['>=5'] }, oracledb => {
shimmer.wrap(oracledb.Connection.prototype, 'execute', execute => {

@@ -27,0 +27,0 @@ return function wrappedExecute (dbQuery, ...args) {

@@ -7,3 +7,8 @@ 'use strict'

if (process.env.DD_TRACE_OTEL_ENABLED) {
const otelSdkEnabled = process.env.DD_TRACE_OTEL_ENABLED ||
process.env.OTEL_SDK_DISABLED
? !process.env.OTEL_SDK_DISABLED
: undefined
if (otelSdkEnabled) {
addHook({

@@ -10,0 +15,0 @@ name: '@opentelemetry/sdk-trace-node',

@@ -19,3 +19,3 @@ 'use strict'

TEST_SOURCE_FILE,
TEST_EARLY_FLAKE_IS_ENABLED,
TEST_EARLY_FLAKE_ENABLED,
TEST_IS_NEW,

@@ -72,3 +72,3 @@ TEST_IS_RETRY

if (isEarlyFlakeDetectionEnabled) {
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_IS_ENABLED, 'true')
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ENABLED, 'true')
}

@@ -75,0 +75,0 @@

@@ -31,3 +31,3 @@ const {

TEST_IS_RETRY,
TEST_EARLY_FLAKE_IS_ENABLED
TEST_EARLY_FLAKE_ENABLED
} = require('../../dd-trace/src/plugins/util/test')

@@ -368,3 +368,3 @@ const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')

if (this.isEarlyFlakeDetectionEnabled) {
testSessionSpanMetadata[TEST_EARLY_FLAKE_IS_ENABLED] = 'true'
testSessionSpanMetadata[TEST_EARLY_FLAKE_ENABLED] = 'true'
}

@@ -371,0 +371,0 @@

@@ -7,2 +7,12 @@ /* eslint-disable */

// If the test is using multi domain with cy.origin, trying to access
// window properties will result in a cross origin error.
function safeGetRum (window) {
try {
return window.DD_RUM
} catch (e) {
return null
}
}
function isNewTest (test) {

@@ -66,3 +76,3 @@ return !knownTestsForSuite.includes(test.fullTitle())

cy.window().then(win => {
if (win.DD_RUM) {
if (safeGetRum(win)) {
win.dispatchEvent(new Event('beforeunload'))

@@ -89,7 +99,13 @@ }

if (win.DD_RUM) {
if (safeGetRum(win)) {
testInfo.isRUMActive = true
}
cy.task('dd:afterEach', { test: testInfo, coverage: win.__coverage__ })
let coverage
try {
coverage = win.__coverage__
} catch (e) {
// ignore error and continue
}
cy.task('dd:afterEach', { test: testInfo, coverage })
})
})

@@ -7,10 +7,6 @@ 'use strict'

static get id () { return 'fetch' }
static get prefix () { return 'apm:fetch:request' }
static get prefix () { return 'tracing:apm:fetch:request' }
addTraceSub (eventName, handler) {
this.addSub(`apm:${this.constructor.id}:${this.operation}:${eventName}`, handler)
}
bindStart (message) {
const req = message.req
bindStart (ctx) {
const req = ctx.req
const options = new URL(req.url)

@@ -21,13 +17,26 @@ const headers = options.headers = Object.fromEntries(req.headers.entries())

message.args = { options }
ctx.args = { options }
const store = super.bindStart(message)
const store = super.bindStart(ctx)
message.headers = headers
message.req = new globalThis.Request(req, { headers })
for (const name in headers) {
if (!req.headers.has(name)) {
req.headers.set(name, headers[name])
}
}
return store
}
error (ctx) {
if (ctx.error.name === 'AbortError') return
return super.error(ctx)
}
asyncEnd (ctx) {
ctx.res = ctx.result
return this.finish(ctx)
}
}
module.exports = FetchPlugin

@@ -21,3 +21,4 @@ const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')

TEST_IS_RETRY,
TEST_EARLY_FLAKE_IS_ENABLED,
TEST_EARLY_FLAKE_ENABLED,
TEST_EARLY_FLAKE_ABORT_REASON,
JEST_DISPLAY_NAME

@@ -93,2 +94,3 @@ } = require('../../dd-trace/src/plugins/util/test')

isEarlyFlakeDetectionEnabled,
isEarlyFlakeDetectionFaulty,
onDone

@@ -120,4 +122,7 @@ }) => {

if (isEarlyFlakeDetectionEnabled) {
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_IS_ENABLED, 'true')
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ENABLED, 'true')
}
if (isEarlyFlakeDetectionFaulty) {
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ABORT_REASON, 'faulty')
}

@@ -124,0 +129,0 @@ this.testModuleSpan.finish()

@@ -23,3 +23,3 @@ 'use strict'

TEST_IS_RETRY,
TEST_EARLY_FLAKE_IS_ENABLED
TEST_EARLY_FLAKE_ENABLED
} = require('../../dd-trace/src/plugins/util/test')

@@ -148,6 +148,5 @@ const { COMPONENT } = require('../../dd-trace/src/constants')

const store = storage.getStore()
const span = store?.span
if (store && store.span) {
const span = store.span
if (span) {
span.setTag(TEST_STATUS, status)

@@ -228,3 +227,3 @@

if (isEarlyFlakeDetectionEnabled) {
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_IS_ENABLED, 'true')
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ENABLED, 'true')
}

@@ -231,0 +230,0 @@

@@ -87,3 +87,3 @@ 'use strict'

// createChatCompletion, createCompletion, createImage, createImageEdit, createTranscription, createTranslation
if ('prompt' in payload) {
if (payload.prompt) {
const prompt = payload.prompt

@@ -103,3 +103,3 @@ store.prompt = prompt

// createEdit, createEmbedding, createModeration
if ('input' in payload) {
if (payload.input) {
const normalized = normalizeStringOrTokenArray(payload.input, false)

@@ -119,2 +119,4 @@ tags['openai.request.input'] = truncateText(normalized)

case 'createFineTune':
case 'fine_tuning.jobs.create':
case 'fine-tune.create':
createFineTuneRequestExtraction(tags, payload)

@@ -124,4 +126,7 @@ break

case 'createImage':
case 'images.generate':
case 'createImageEdit':
case 'images.edit':
case 'createImageVariation':
case 'images.createVariation':
commonCreateImageRequestExtraction(tags, payload, store)

@@ -131,2 +136,3 @@ break

case 'createChatCompletion':
case 'chat.completions.create':
createChatCompletionRequestExtraction(tags, payload, store)

@@ -136,3 +142,5 @@ break

case 'createFile':
case 'files.create':
case 'retrieveFile':
case 'files.retrieve':
commonFileRequestExtraction(tags, payload)

@@ -142,3 +150,5 @@ break

case 'createTranscription':
case 'audio.transcriptions.create':
case 'createTranslation':
case 'audio.translations.create':
commonCreateAudioRequestExtraction(tags, payload, store)

@@ -148,2 +158,3 @@ break

case 'retrieveModel':
case 'models.retrieve':
retrieveModelRequestExtraction(tags, payload)

@@ -153,5 +164,12 @@ break

case 'listFineTuneEvents':
case 'fine_tuning.jobs.listEvents':
case 'fine-tune.listEvents':
case 'retrieveFineTune':
case 'fine_tuning.jobs.retrieve':
case 'fine-tune.retrieve':
case 'deleteModel':
case 'models.del':
case 'cancelFineTune':
case 'fine_tuning.jobs.cancel':
case 'fine-tune.cancel':
commonLookupFineTuneRequestExtraction(tags, payload)

@@ -161,2 +179,3 @@ break

case 'createEdit':
case 'edits.create':
createEditRequestExtraction(tags, payload, store)

@@ -170,2 +189,6 @@ break

finish ({ headers, body, method, path }) {
if (headers.constructor.name === 'Headers') {
headers = Object.fromEntries(headers)
}
const span = this.activeSpan

@@ -179,2 +202,7 @@ const methodName = span._spanContext._tags['resource.name']

if (path.startsWith('https://') || path.startsWith('http://')) {
// basic checking for if the path was set as a full URL
// not using a full regex as it will likely be "https://api.openai.com/..."
path = new URL(path).pathname
}
const endpoint = lookupOperationEndpoint(methodName, path)

@@ -184,3 +212,3 @@

'openai.request.endpoint': endpoint,
'openai.request.method': method,
'openai.request.method': method.toUpperCase(),

@@ -236,3 +264,3 @@ 'openai.organization.id': body.organization_id, // only available in fine-tunes endpoints

if (body && ('usage' in body)) {
if (body && body.usage) {
const promptTokens = body.usage.prompt_tokens

@@ -245,15 +273,15 @@ const completionTokens = body.usage.completion_tokens

if ('x-ratelimit-limit-requests' in headers) {
if (headers['x-ratelimit-limit-requests']) {
this.metrics.gauge('openai.ratelimit.requests', Number(headers['x-ratelimit-limit-requests']), tags)
}
if ('x-ratelimit-remaining-requests' in headers) {
if (headers['x-ratelimit-remaining-requests']) {
this.metrics.gauge('openai.ratelimit.remaining.requests', Number(headers['x-ratelimit-remaining-requests']), tags)
}
if ('x-ratelimit-limit-tokens' in headers) {
if (headers['x-ratelimit-limit-tokens']) {
this.metrics.gauge('openai.ratelimit.tokens', Number(headers['x-ratelimit-limit-tokens']), tags)
}
if ('x-ratelimit-remaining-tokens' in headers) {
if (headers['x-ratelimit-remaining-tokens']) {
this.metrics.gauge('openai.ratelimit.remaining.tokens', Number(headers['x-ratelimit-remaining-tokens']), tags)

@@ -293,6 +321,6 @@ }

const message = payload.messages[i]
tags[`openai.request.${i}.content`] = truncateText(message.content)
tags[`openai.request.${i}.role`] = message.role
tags[`openai.request.${i}.name`] = message.name
tags[`openai.request.${i}.finish_reason`] = message.finish_reason
tags[`openai.request.messages.${i}.content`] = truncateText(message.content)
tags[`openai.request.messages.${i}.role`] = message.role
tags[`openai.request.messages.${i}.name`] = message.name
tags[`openai.request.messages.${i}.finish_reason`] = message.finish_reason
}

@@ -303,4 +331,5 @@ }

// createImageEdit, createImageVariation
if (payload.file && typeof payload.file === 'object' && payload.file.path) {
const file = path.basename(payload.file.path)
const img = payload.file || payload.image
if (img && typeof img === 'object' && img.path) {
const file = path.basename(img.path)
tags['openai.request.image'] = file

@@ -325,2 +354,3 @@ store.file = file

case 'createModeration':
case 'moderations.create':
createModerationResponseExtraction(tags, body)

@@ -330,4 +360,7 @@ break

case 'createCompletion':
case 'completions.create':
case 'createChatCompletion':
case 'chat.completions.create':
case 'createEdit':
case 'edits.create':
commonCreateResponseExtraction(tags, body, store)

@@ -337,4 +370,9 @@ break

case 'listFiles':
case 'files.list':
case 'listFineTunes':
case 'fine_tuning.jobs.list':
case 'fine-tune.list':
case 'listFineTuneEvents':
case 'fine_tuning.jobs.listEvents':
case 'fine-tune.listEvents':
commonListCountResponseExtraction(tags, body)

@@ -344,2 +382,3 @@ break

case 'createEmbedding':
case 'embeddings.create':
createEmbeddingResponseExtraction(tags, body)

@@ -349,3 +388,5 @@ break

case 'createFile':
case 'files.create':
case 'retrieveFile':
case 'files.retrieve':
createRetrieveFileResponseExtraction(tags, body)

@@ -355,2 +396,3 @@ break

case 'deleteFile':
case 'files.del':
deleteFileResponseExtraction(tags, body)

@@ -360,2 +402,4 @@ break

case 'downloadFile':
case 'files.retrieveContent':
case 'files.content':
downloadFileResponseExtraction(tags, body)

@@ -365,4 +409,10 @@ break

case 'createFineTune':
case 'fine_tuning.jobs.create':
case 'fine-tune.create':
case 'retrieveFineTune':
case 'fine_tuning.jobs.retrieve':
case 'fine-tune.retrieve':
case 'cancelFineTune':
case 'fine_tuning.jobs.cancel':
case 'fine-tune.cancel':
commonFineTuneResponseExtraction(tags, body)

@@ -372,3 +422,5 @@ break

case 'createTranscription':
case 'audio.transcriptions.create':
case 'createTranslation':
case 'audio.translations.create':
createAudioResponseExtraction(tags, body)

@@ -378,4 +430,7 @@ break

case 'createImage':
case 'images.generate':
case 'createImageEdit':
case 'images.edit':
case 'createImageVariation':
case 'images.createVariation':
commonImageResponseExtraction(tags, body)

@@ -385,2 +440,3 @@ break

case 'listModels':
case 'models.list':
listModelsResponseExtraction(tags, body)

@@ -390,2 +446,3 @@ break

case 'retrieveModel':
case 'models.retrieve':
retrieveModelResponseExtraction(tags, body)

@@ -463,11 +520,15 @@ break

tags['openai.response.fine_tuned_model'] = body.fine_tuned_model
if (body.hyperparams) {
tags['openai.response.hyperparams.n_epochs'] = body.hyperparams.n_epochs
tags['openai.response.hyperparams.batch_size'] = body.hyperparams.batch_size
tags['openai.response.hyperparams.prompt_loss_weight'] = body.hyperparams.prompt_loss_weight
tags['openai.response.hyperparams.learning_rate_multiplier'] = body.hyperparams.learning_rate_multiplier
const hyperparams = body.hyperparams || body.hyperparameters
const hyperparamsKey = body.hyperparams ? 'hyperparams' : 'hyperparameters'
if (hyperparams) {
tags[`openai.response.${hyperparamsKey}.n_epochs`] = hyperparams.n_epochs
tags[`openai.response.${hyperparamsKey}.batch_size`] = hyperparams.batch_size
tags[`openai.response.${hyperparamsKey}.prompt_loss_weight`] = hyperparams.prompt_loss_weight
tags[`openai.response.${hyperparamsKey}.learning_rate_multiplier`] = hyperparams.learning_rate_multiplier
}
tags['openai.response.training_files_count'] = defensiveArrayLength(body.training_files)
tags['openai.response.training_files_count'] = defensiveArrayLength(body.training_files || body.training_file)
tags['openai.response.result_files_count'] = defensiveArrayLength(body.result_files)
tags['openai.response.validation_files_count'] = defensiveArrayLength(body.validation_files)
tags['openai.response.validation_files_count'] = defensiveArrayLength(body.validation_files || body.validation_file)
tags['openai.response.updated_at'] = body.updated_at

@@ -561,14 +622,27 @@ tags['openai.response.status'] = body.status

for (let i = 0; i < body.choices.length; i++) {
const choice = body.choices[i]
tags[`openai.response.choices.${i}.finish_reason`] = choice.finish_reason
tags[`openai.response.choices.${i}.logprobs`] = ('logprobs' in choice) ? 'returned' : undefined
tags[`openai.response.choices.${i}.text`] = truncateText(choice.text)
for (let choiceIdx = 0; choiceIdx < body.choices.length; choiceIdx++) {
const choice = body.choices[choiceIdx]
// logprobs can be nullm and we still want to tag it as 'returned' even when set to 'null'
const specifiesLogProb = Object.keys(choice).indexOf('logprobs') !== -1
tags[`openai.response.choices.${choiceIdx}.finish_reason`] = choice.finish_reason
tags[`openai.response.choices.${choiceIdx}.logprobs`] = specifiesLogProb ? 'returned' : undefined
tags[`openai.response.choices.${choiceIdx}.text`] = truncateText(choice.text)
// createChatCompletion only
if ('message' in choice) {
if (choice.message) {
const message = choice.message
tags[`openai.response.choices.${i}.message.role`] = message.role
tags[`openai.response.choices.${i}.message.content`] = truncateText(message.content)
tags[`openai.response.choices.${i}.message.name`] = truncateText(message.name)
tags[`openai.response.choices.${choiceIdx}.message.role`] = message.role
tags[`openai.response.choices.${choiceIdx}.message.content`] = truncateText(message.content)
tags[`openai.response.choices.${choiceIdx}.message.name`] = truncateText(message.name)
if (message.tool_calls) {
const toolCalls = message.tool_calls
for (let toolIdx = 0; toolIdx < toolCalls.length; toolIdx++) {
tags[`openai.response.choices.${choiceIdx}.message.tool_calls.${toolIdx}.name`] =
toolCalls[toolIdx].function.name
tags[`openai.response.choices.${choiceIdx}.message.tool_calls.${toolIdx}.arguments`] =
toolCalls[toolIdx].function.arguments
}
}
}

@@ -611,6 +685,19 @@ }

case 'downloadFile':
case 'files.retrieveContent':
case 'files.content':
return { file: body }
}
return typeof body === 'object' ? body : {}
const type = typeof body
if (type === 'string') {
try {
return JSON.parse(body)
} catch {
return body
}
} else if (type === 'object') {
return body
} else {
return {}
}
}

@@ -622,20 +709,35 @@

case 'deleteModel':
case 'models.del':
case 'retrieveModel':
case 'models.retrieve':
return '/v1/models/*'
case 'deleteFile':
case 'files.del':
case 'retrieveFile':
case 'files.retrieve':
return '/v1/files/*'
case 'downloadFile':
case 'files.retrieveContent':
case 'files.content':
return '/v1/files/*/content'
case 'retrieveFineTune':
case 'fine-tune.retrieve':
return '/v1/fine-tunes/*'
case 'fine_tuning.jobs.retrieve':
return '/v1/fine_tuning/jobs/*'
case 'listFineTuneEvents':
case 'fine-tune.listEvents':
return '/v1/fine-tunes/*/events'
case 'fine_tuning.jobs.listEvents':
return '/v1/fine_tuning/jobs/*/events'
case 'cancelFineTune':
case 'fine-tune.cancel':
return '/v1/fine-tunes/*/cancel'
case 'fine_tuning.jobs.cancel':
return '/v1/fine_tuning/jobs/*/cancel'
}

@@ -654,4 +756,8 @@

case 'listModels':
case 'models.list':
case 'listFiles':
case 'files.list':
case 'listFineTunes':
case 'fine_tuning.jobs.list':
case 'fine-tune.list':
// no argument

@@ -661,2 +767,3 @@ return {}

case 'retrieveModel':
case 'models.retrieve':
return { id: args[0] }

@@ -671,7 +778,13 @@

case 'deleteFile':
case 'files.del':
case 'retrieveFile':
case 'files.retrieve':
case 'downloadFile':
case 'files.retrieveContent':
case 'files.content':
return { file_id: args[0] }
case 'listFineTuneEvents':
case 'fine_tuning.jobs.listEvents':
case 'fine-tune.listEvents':
return {

@@ -683,4 +796,9 @@ fine_tune_id: args[0],

case 'retrieveFineTune':
case 'fine_tuning.jobs.retrieve':
case 'fine-tune.retrieve':
case 'deleteModel':
case 'models.del':
case 'cancelFineTune':
case 'fine_tuning.jobs.cancel':
case 'fine-tune.cancel':
return { fine_tune_id: args[0] }

@@ -742,5 +860,14 @@

function defensiveArrayLength (maybeArray) {
return Array.isArray(maybeArray) ? maybeArray.length : undefined
if (maybeArray) {
if (Array.isArray(maybeArray)) {
return maybeArray.length
} else {
// case of a singular item (ie body.training_file vs body.training_files)
return 1
}
}
return undefined
}
module.exports = OpenApiPlugin
'use strict'
const { DogStatsDClient, NoopDogStatsDClient } = require('../../dd-trace/src/dogstatsd')
const { DogStatsDClient } = require('../../dd-trace/src/dogstatsd')
const NoopDogStatsDClient = require('../../dd-trace/src/noop/dogstatsd')
const { ExternalLogger, NoopExternalLogger } = require('../../dd-trace/src/external-logger/src')

@@ -5,0 +6,0 @@

@@ -17,3 +17,3 @@ 'use strict'

TEST_IS_RETRY,
TEST_EARLY_FLAKE_IS_ENABLED
TEST_EARLY_FLAKE_ENABLED
} = require('../../dd-trace/src/plugins/util/test')

@@ -45,3 +45,3 @@ const { RESOURCE_NAME } = require('../../../ext/tags')

if (isEarlyFlakeDetectionEnabled) {
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_IS_ENABLED, 'true')
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ENABLED, 'true')
}

@@ -48,0 +48,0 @@

@@ -5,2 +5,3 @@ 'use strict'

COMMAND_INJECTION_ANALYZER: require('./command-injection-analyzer'),
HARCODED_PASSWORD_ANALYZER: require('./hardcoded-password-analyzer'),
HARCODED_SECRET_ANALYZER: require('./hardcoded-secret-analyzer'),

@@ -7,0 +8,0 @@ HEADER_INJECTION_ANALYZER: require('./header-injection-analyzer'),

'use strict'
const Analyzer = require('./vulnerability-analyzer')
const { HARDCODED_SECRET } = require('../vulnerabilities')
const { getRelativePath } = require('../path-line')
const HardcodedBaseAnalyzer = require('./hardcoded-base-analyzer')
const { ValueOnly } = require('./hardcoded-rule-type')
const secretRules = require('./hardcoded-secrets-rules')
const allRules = require('./hardcoded-secret-rules')
class HardcodedSecretAnalyzer extends Analyzer {
class HardcodedSecretAnalyzer extends HardcodedBaseAnalyzer {
constructor () {
super(HARDCODED_SECRET)
super(HARDCODED_SECRET, allRules, allRules.filter(rule => rule.type === ValueOnly))
}
onConfigure () {
this.addSub('datadog:secrets:result', (secrets) => { this.analyze(secrets) })
}
analyze (secrets) {
if (!secrets?.file || !secrets.literals) return
const matches = secrets.literals
.filter(literal => literal.value && literal.locations?.length)
.map(literal => {
const match = secretRules.find(rule => literal.value.match(rule.regex))
return match ? { locations: literal.locations, ruleId: match.id } : undefined
})
.filter(match => !!match)
if (matches.length) {
const file = getRelativePath(secrets.file)
matches.forEach(match => {
match.locations
.filter(location => location.line)
.forEach(location => this._report({
file,
line: location.line,
column: location.column,
data: match.ruleId
}))
})
}
}
_getEvidence (value) {
return { value: `${value.data}` }
}
_getLocation (value) {
return {
path: value.file,
line: value.line,
column: value.column,
isInternal: false
}
}
}
module.exports = new HardcodedSecretAnalyzer()
/* eslint-disable max-len */
'use strict'
const { ValueOnly, NameAndValue } = require('./hardcoded-rule-type')
module.exports = [
{
id: 'adafruit-api-key',
regex: /(?:adafruit)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9_-]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'adobe-client-id',
regex: /(?:adobe)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'adobe-client-secret',
regex: /\b((p8e-)[a-z0-9]{32})(?:['"\s\x60;]|$)/i
regex: /\b((p8e-)[a-z0-9]{32})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'age-secret-key',
regex: /AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}/
regex: /AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}/,
type: ValueOnly
},
{
id: 'airtable-api-key',
regex: /(?:airtable)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{17})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'algolia-api-key',
regex: /(?:algolia)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'alibaba-access-key-id',
regex: /\b((LTAI)[a-z0-9]{20})(?:['"\s\x60;]|$)/i
regex: /\b((LTAI)[a-z0-9]{20})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'asana-client-id',
regex: /(?:asana)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9]{16})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'asana-client-secret',
regex: /(?:asana)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'atlassian-api-token',
regex: /(?:atlassian|confluence|jira)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{24})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'authress-service-client-access-key',
regex: /\b((?:sc|ext|scauth|authress)_[a-z0-9]{5,30}\.[a-z0-9]{4,6}\.acc[_-][a-z0-9-]{10,32}\.[a-z0-9+/_=-]{30,120})(?:['"\s\x60;]|$)/i
regex: /\b((?:sc|ext|scauth|authress)_[a-z0-9]{5,30}\.[a-z0-9]{4,6}\.acc[_-][a-z0-9-]{10,32}\.[a-z0-9+/_=-]{30,120})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'aws-access-token',
regex: /\b((A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16})(?:['"\s\x60;]|$)/
regex: /\b((A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16})(?:['"\s\x60;]|$)/,
type: ValueOnly
},
{
id: 'beamer-api-token',
regex: /(?:beamer)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(b_[a-z0-9=_-]{44})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'bitbucket-client-id',
regex: /(?:bitbucket)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'bitbucket-client-secret',
regex: /(?:bitbucket)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{64})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'bittrex-access-key',
regex: /(?:bittrex)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'clojars-api-token',
regex: /(CLOJARS_)[a-z0-9]{60}/i
regex: /(CLOJARS_)[a-z0-9]{60}/i,
type: ValueOnly
},
{
id: 'codecov-access-token',
regex: /(?:codecov)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'coinbase-access-token',
regex: /(?:coinbase)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9_-]{64})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'confluent-access-token',
regex: /(?:confluent)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{16})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'confluent-secret-key',
regex: /(?:confluent)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{64})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'contentful-delivery-api-token',
regex: /(?:contentful)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{43})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'databricks-api-token',
regex: /\b(dapi[a-h0-9]{32})(?:['"\s\x60;]|$)/i
regex: /\b(dapi[a-h0-9]{32})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'datadog-access-token',
regex: /(?:datadog)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{40})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'defined-networking-api-token',
regex: /(?:dnkey)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(dnkey-[a-z0-9=_-]{26}-[a-z0-9=_-]{52})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'digitalocean-access-token',
regex: /\b(doo_v1_[a-f0-9]{64})(?:['"\s\x60;]|$)/i
regex: /\b(doo_v1_[a-f0-9]{64})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'digitalocean-pat',
regex: /\b(dop_v1_[a-f0-9]{64})(?:['"\s\x60;]|$)/i
regex: /\b(dop_v1_[a-f0-9]{64})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'digitalocean-refresh-token',
regex: /\b(dor_v1_[a-f0-9]{64})(?:['"\s\x60;]|$)/i
regex: /\b(dor_v1_[a-f0-9]{64})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'discord-api-token',
regex: /(?:discord)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{64})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'discord-client-id',
regex: /(?:discord)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9]{18})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'discord-client-secret',
regex: /(?:discord)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'doppler-api-token',
regex: /(dp\.pt\.)[a-z0-9]{43}/i
regex: /(dp\.pt\.)[a-z0-9]{43}/i,
type: ValueOnly
},
{
id: 'droneci-access-token',
regex: /(?:droneci)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'dropbox-api-token',
regex: /(?:dropbox)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{15})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'dropbox-long-lived-api-token',
regex: /(?:dropbox)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'dropbox-short-lived-api-token',
regex: /(?:dropbox)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(sl\.[a-z0-9\-=_]{135})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'duffel-api-token',
regex: /duffel_(test|live)_[a-z0-9_\-=]{43}/i
regex: /duffel_(test|live)_[a-z0-9_\-=]{43}/i,
type: ValueOnly
},
{
id: 'dynatrace-api-token',
regex: /dt0c01\.[a-z0-9]{24}\.[a-z0-9]{64}/i
regex: /dt0c01\.[a-z0-9]{24}\.[a-z0-9]{64}/i,
type: ValueOnly
},
{
id: 'easypost-api-token',
regex: /\bEZAK[a-z0-9]{54}/i
regex: /\bEZAK[a-z0-9]{54}/i,
type: ValueOnly
},
{
id: 'etsy-access-token',
regex: /(?:etsy)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{24})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'facebook',
regex: /(?:facebook)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'fastly-api-token',
regex: /(?:fastly)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'finicity-api-token',
regex: /(?:finicity)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'finicity-client-secret',
regex: /(?:finicity)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{20})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'finnhub-access-token',
regex: /(?:finnhub)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{20})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'flickr-access-token',
regex: /(?:flickr)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'flutterwave-public-key',
regex: /FLWPUBK_TEST-[a-h0-9]{32}-X/i
regex: /FLWPUBK_TEST-[a-h0-9]{32}-X/i,
type: ValueOnly
},
{
id: 'frameio-api-token',
regex: /fio-u-[a-z0-9\-_=]{64}/i
regex: /fio-u-[a-z0-9\-_=]{64}/i,
type: ValueOnly
},
{
id: 'freshbooks-access-token',
regex: /(?:freshbooks)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{64})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'gcp-api-key',
regex: /\b(AIza[0-9a-z\-_]{35})(?:['"\s\x60;]|$)/i
regex: /\b(AIza[0-9a-z\-_]{35})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'github-app-token',
regex: /(ghu|ghs)_[0-9a-zA-Z]{36}/
regex: /(ghu|ghs)_[0-9a-zA-Z]{36}/,
type: ValueOnly
},
{
id: 'github-fine-grained-pat',
regex: /github_pat_[0-9a-zA-Z_]{82}/
regex: /github_pat_[0-9a-zA-Z_]{82}/,
type: ValueOnly
},
{
id: 'github-oauth',
regex: /gho_[0-9a-zA-Z]{36}/
regex: /gho_[0-9a-zA-Z]{36}/,
type: ValueOnly
},
{
id: 'github-pat',
regex: /ghp_[0-9a-zA-Z]{36}/
regex: /ghp_[0-9a-zA-Z]{36}/,
type: ValueOnly
},
{
id: 'gitlab-pat',
regex: /glpat-[0-9a-zA-Z\-_]{20}/
regex: /glpat-[0-9a-zA-Z\-_]{20}/,
type: ValueOnly
},
{
id: 'gitlab-ptt',
regex: /glptt-[0-9a-f]{40}/
regex: /glptt-[0-9a-f]{40}/,
type: ValueOnly
},
{
id: 'gitlab-rrt',
regex: /GR1348941[0-9a-zA-Z\-_]{20}/
regex: /GR1348941[0-9a-zA-Z\-_]{20}/,
type: ValueOnly
},
{
id: 'gitter-access-token',
regex: /(?:gitter)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9_-]{40})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'gocardless-api-token',
regex: /(?:gocardless)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(live_[a-z0-9\-_=]{40})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'grafana-api-key',
regex: /\b(eyJrIjoi[a-z0-9]{70,400}={0,2})(?:['"\s\x60;]|$)/i
regex: /\b(eyJrIjoi[a-z0-9]{70,400}={0,2})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'grafana-cloud-api-token',
regex: /\b(glc_[a-z0-9+/]{32,400}={0,2})(?:['"\s\x60;]|$)/i
regex: /\b(glc_[a-z0-9+/]{32,400}={0,2})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'grafana-service-account-token',
regex: /\b(glsa_[a-z0-9]{32}_[a-f0-9]{8})(?:['"\s\x60;]|$)/i
regex: /\b(glsa_[a-z0-9]{32}_[a-f0-9]{8})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'hashicorp-tf-api-token',
regex: /[a-z0-9]{14}\.atlasv1\.[a-z0-9\-_=]{60,70}/i
regex: /[a-z0-9]{14}\.atlasv1\.[a-z0-9\-_=]{60,70}/i,
type: ValueOnly
},
{
id: 'heroku-api-key',
regex: /(?:heroku)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'hubspot-api-key',
regex: /(?:hubspot)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'intercom-api-key',
regex: /(?:intercom)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{60})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'jfrog-api-key',
regex: /(?:jfrog|artifactory|bintray|xray)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{73})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'jwt',
regex: /\b(ey[a-zA-Z0-9]{17,}\.ey[a-zA-Z0-9/_-]{17,}\.(?:[a-zA-Z0-9/_-]{10,}={0,2})?)(?:['"\s\x60;]|$)/
regex: /\b(ey[a-zA-Z0-9]{17,}\.ey[a-zA-Z0-9/_-]{17,}\.(?:[a-zA-Z0-9/_-]{10,}={0,2})?)(?:['"\s\x60;]|$)/,
type: ValueOnly
},
{
id: 'kraken-access-token',
regex: /(?:kraken)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9/=_+-]{80,90})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'kucoin-access-token',
regex: /(?:kucoin)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{24})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'launchdarkly-access-token',
regex: /(?:launchdarkly)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{40})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'linear-api-key',
regex: /lin_api_[a-z0-9]{40}/i
regex: /lin_api_[a-z0-9]{40}/i,
type: ValueOnly
},
{
id: 'linkedin-client-secret',
regex: /(?:linkedin|linked-in)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{16})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'lob-pub-api-key',
regex: /(?:lob)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}((test|live)_pub_[a-f0-9]{31})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'mailchimp-api-key',
regex: /(?:mailchimp)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{32}-us20)(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'mailgun-private-api-token',
regex: /(?:mailgun)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(key-[a-f0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'mailgun-pub-key',
regex: /(?:mailgun)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(pubkey-[a-f0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'mailgun-signing-key',
regex: /(?:mailgun)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'mapbox-api-token',
regex: /(?:mapbox)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(pk\.[a-z0-9]{60}\.[a-z0-9]{22})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'mattermost-access-token',
regex: /(?:mattermost)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{26})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'messagebird-api-token',
regex: /(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{25})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'netlify-access-token',
regex: /(?:netlify)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{40,46})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'new-relic-browser-api-token',
regex: /(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(NRJS-[a-f0-9]{19})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'new-relic-user-api-id',
regex: /(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{64})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'new-relic-user-api-key',
regex: /(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(NRAK-[a-z0-9]{27})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'npm-access-token',
regex: /\b(npm_[a-z0-9]{36})(?:['"\s\x60;]|$)/i
regex: /\b(npm_[a-z0-9]{36})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'nytimes-access-token',
regex: /(?:nytimes|new-york-times,|newyorktimes)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'okta-access-token',
regex: /(?:okta)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9=_-]{42})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'openai-api-key',
regex: /\b(sk-[a-z0-9]{20}T3BlbkFJ[a-z0-9]{20})(?:['"\s\x60;]|$)/i
regex: /\b(sk-[a-z0-9]{20}T3BlbkFJ[a-z0-9]{20})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'plaid-api-token',
regex: /(?:plaid)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(access-(?:sandbox|development|production)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'plaid-client-id',
regex: /(?:plaid)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{24})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'plaid-secret-key',
regex: /(?:plaid)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{30})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'planetscale-api-token',
regex: /\b(pscale_tkn_[a-z0-9=\-_.]{32,64})(?:['"\s\x60;]|$)/i
regex: /\b(pscale_tkn_[a-z0-9=\-_.]{32,64})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'planetscale-oauth-token',
regex: /\b(pscale_oauth_[a-z0-9=\-_.]{32,64})(?:['"\s\x60;]|$)/i
regex: /\b(pscale_oauth_[a-z0-9=\-_.]{32,64})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'planetscale-password',
regex: /\b(pscale_pw_[a-z0-9=\-_.]{32,64})(?:['"\s\x60;]|$)/i
regex: /\b(pscale_pw_[a-z0-9=\-_.]{32,64})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'postman-api-token',
regex: /\b(PMAK-[a-f0-9]{24}-[a-f0-9]{34})(?:['"\s\x60;]|$)/i
regex: /\b(PMAK-[a-f0-9]{24}-[a-f0-9]{34})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'prefect-api-token',
regex: /\b(pnu_[a-z0-9]{36})(?:['"\s\x60;]|$)/i
regex: /\b(pnu_[a-z0-9]{36})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'private-key',
regex: /-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY( BLOCK)?-----[\s\S]*KEY( BLOCK)?----/i
regex: /-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY( BLOCK)?-----[\s\S]*KEY( BLOCK)?----/i,
type: ValueOnly
},
{
id: 'pulumi-api-token',
regex: /\b(pul-[a-f0-9]{40})(?:['"\s\x60;]|$)/i
regex: /\b(pul-[a-f0-9]{40})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'pypi-upload-token',
regex: /pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000}/
regex: /pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000}/,
type: ValueOnly
},
{
id: 'rapidapi-access-token',
regex: /(?:rapidapi)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9_-]{50})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'readme-api-token',
regex: /\b(rdme_[a-z0-9]{70})(?:['"\s\x60;]|$)/i
regex: /\b(rdme_[a-z0-9]{70})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'rubygems-api-token',
regex: /\b(rubygems_[a-f0-9]{48})(?:['"\s\x60;]|$)/i
regex: /\b(rubygems_[a-f0-9]{48})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'scalingo-api-token',
regex: /tk-us-[a-zA-Z0-9-_]{48}/
regex: /tk-us-[a-zA-Z0-9-_]{48}/,
type: ValueOnly
},
{
id: 'sendbird-access-id',
regex: /(?:sendbird)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'sendbird-access-token',
regex: /(?:sendbird)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{40})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'sendgrid-api-token',
regex: /\b(SG\.[a-z0-9=_\-.]{66})(?:['"\s\x60;]|$)/i
regex: /\b(SG\.[a-z0-9=_\-.]{66})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'sendinblue-api-token',
regex: /\b(xkeysib-[a-f0-9]{64}-[a-z0-9]{16})(?:['"\s\x60;]|$)/i
regex: /\b(xkeysib-[a-f0-9]{64}-[a-z0-9]{16})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'sentry-access-token',
regex: /(?:sentry)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{64})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'shippo-api-token',
regex: /\b(shippo_(live|test)_[a-f0-9]{40})(?:['"\s\x60;]|$)/i
regex: /\b(shippo_(live|test)_[a-f0-9]{40})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'shopify-access-token',
regex: /shpat_[a-fA-F0-9]{32}/
regex: /shpat_[a-fA-F0-9]{32}/,
type: ValueOnly
},
{
id: 'shopify-custom-access-token',
regex: /shpca_[a-fA-F0-9]{32}/
regex: /shpca_[a-fA-F0-9]{32}/,
type: ValueOnly
},
{
id: 'shopify-private-app-access-token',
regex: /shppa_[a-fA-F0-9]{32}/
regex: /shppa_[a-fA-F0-9]{32}/,
type: ValueOnly
},
{
id: 'shopify-shared-secret',
regex: /shpss_[a-fA-F0-9]{32}/
regex: /shpss_[a-fA-F0-9]{32}/,
type: ValueOnly
},
{
id: 'sidekiq-secret',
regex: /(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'slack-app-token',
regex: /(xapp-\d-[A-Z0-9]+-\d+-[a-z0-9]+)/i
regex: /(xapp-\d-[A-Z0-9]+-\d+-[a-z0-9]+)/i,
type: ValueOnly
},
{
id: 'slack-bot-token',
regex: /(xoxb-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*)/
regex: /(xoxb-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*)/,
type: ValueOnly
},
{
id: 'slack-config-access-token',
regex: /(xoxe.xox[bp]-\d-[A-Z0-9]{163,166})/i
regex: /(xoxe.xox[bp]-\d-[A-Z0-9]{163,166})/i,
type: ValueOnly
},
{
id: 'slack-config-refresh-token',
regex: /(xoxe-\d-[A-Z0-9]{146})/i
regex: /(xoxe-\d-[A-Z0-9]{146})/i,
type: ValueOnly
},
{
id: 'slack-legacy-bot-token',
regex: /(xoxb-[0-9]{8,14}-[a-zA-Z0-9]{18,26})/
regex: /(xoxb-[0-9]{8,14}-[a-zA-Z0-9]{18,26})/,
type: ValueOnly
},
{
id: 'slack-legacy-token',
regex: /(xox[os]-\d+-\d+-\d+-[a-fA-F\d]+)/
regex: /(xox[os]-\d+-\d+-\d+-[a-fA-F\d]+)/,
type: ValueOnly
},
{
id: 'slack-legacy-workspace-token',
regex: /(xox[ar]-(?:\d-)?[0-9a-zA-Z]{8,48})/
regex: /(xox[ar]-(?:\d-)?[0-9a-zA-Z]{8,48})/,
type: ValueOnly
},
{
id: 'slack-user-token',
regex: /(xox[pe](?:-[0-9]{10,13}){3}-[a-zA-Z0-9-]{28,34})/
regex: /(xox[pe](?:-[0-9]{10,13}){3}-[a-zA-Z0-9-]{28,34})/,
type: ValueOnly
},
{
id: 'slack-webhook-url',
regex: /(https?:\/\/)?hooks.slack.com\/(services|workflows)\/[A-Za-z0-9+/]{43,46}/
regex: /(https?:\/\/)?hooks.slack.com\/(services|workflows)\/[A-Za-z0-9+/]{43,46}/,
type: ValueOnly
},
{
id: 'snyk-api-token',
regex: /(?:snyk)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'square-access-token',
regex: /\b(sq0atp-[0-9a-z\-_]{22})(?:['"\s\x60;]|$)/i
regex: /\b(sq0atp-[0-9a-z\-_]{22})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'square-secret',
regex: /\b(sq0csp-[0-9a-z\-_]{43})(?:['"\s\x60;]|$)/i
regex: /\b(sq0csp-[0-9a-z\-_]{43})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'squarespace-access-token',
regex: /(?:squarespace)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'stripe-access-token',
regex: /(sk|pk)_(test|live)_[0-9a-z]{10,32}/i
regex: /(sk|pk)_(test|live)_[0-9a-z]{10,32}/i,
type: ValueOnly
},
{
id: 'sumologic-access-token',
regex: /(?:sumo)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{64})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'telegram-bot-api-token',
regex: /(?:^|[^0-9])([0-9]{5,16}:A[a-z0-9_-]{34})(?:$|[^a-z0-9_-])/i
regex: /(?:^|[^0-9])([0-9]{5,16}:A[a-z0-9_-]{34})(?:$|[^a-z0-9_-])/i,
type: ValueOnly
},
{
id: 'travisci-access-token',
regex: /(?:travis)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{22})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'trello-access-token',
regex: /(?:trello)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z-0-9]{32})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'twilio-api-key',
regex: /SK[0-9a-fA-F]{32}/
regex: /SK[0-9a-fA-F]{32}/,
type: ValueOnly
},
{
id: 'twitch-api-token',
regex: /(?:twitch)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{30})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'twitter-access-secret',
regex: /(?:twitter)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{45})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'twitter-access-token',
regex: /(?:twitter)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9]{15,25}-[a-z0-9]{20,40})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'twitter-api-key',
regex: /(?:twitter)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{25})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'twitter-api-secret',
regex: /(?:twitter)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{50})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'twitter-bearer-token',
regex: /(?:twitter)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(A{22}[a-z0-9%]{80,100})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'typeform-api-token',
regex: /(?:typeform)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(tfp_[a-z0-9\-_.=]{59})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'vault-batch-token',
regex: /\b(hvb\.[a-z0-9_-]{138,212})(?:['"\s\x60;]|$)/i
regex: /\b(hvb\.[a-z0-9_-]{138,212})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'vault-service-token',
regex: /\b(hvs\.[a-z0-9_-]{90,100})(?:['"\s\x60;]|$)/i
regex: /\b(hvs\.[a-z0-9_-]{90,100})(?:['"\s\x60;]|$)/i,
type: ValueOnly
},
{
id: 'yandex-access-token',
regex: /(?:yandex)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(t1\.[A-Z0-9a-z_-]+[=]{0,2}\.[A-Z0-9a-z_-]{86}[=]{0,2})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'yandex-api-key',
regex: /(?:yandex)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(AQVN[a-z0-9_-]{35,38})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'yandex-aws-access-token',
regex: /(?:yandex)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}(YC[a-z0-9_-]{38})(?:['"\s\x60;]|$)/i,
type: NameAndValue
},
{
id: 'zendesk-secret-key',
regex: /(?:zendesk)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([a-z0-9]{40})(?:['"\s\x60;]|$)/i,
type: NameAndValue
}
]

@@ -23,7 +23,11 @@ 'use strict'

'sqreen/lib/package-reader/index.js',
'ws/lib/websocket-server.js'
'ws/lib/websocket-server.js',
'google-gax/build/src/grpc.js',
'cookie-signature/index.js'
)
const EXCLUDED_PATHS_FROM_STACK = [
path.join('node_modules', 'object-hash', path.sep)
path.join('node_modules', 'object-hash', path.sep),
path.join('node_modules', 'aws-sdk', 'lib', 'util.js'),
path.join('node_modules', 'keygrip', path.sep)
]

@@ -30,0 +34,0 @@ class WeakHashAnalyzer extends Analyzer {

@@ -7,3 +7,3 @@ 'use strict'

function taintObject (iastContext, object, type, keyTainting, keyType) {
function taintObject (iastContext, object, type) {
let result = object

@@ -26,5 +26,2 @@ const transactionId = iastContext?.[IAST_TRANSACTION_ID]

result = tainted
} else if (keyTainting && key) {
const taintedProperty = TaintedUtils.newTaintedString(transactionId, key, property, keyType)
parent[taintedProperty] = tainted
} else {

@@ -39,7 +36,2 @@ parent[key] = tainted

}
if (parent && keyTainting && key) {
const taintedProperty = TaintedUtils.newTaintedString(transactionId, key, property, keyType)
parent[taintedProperty] = value
}
}

@@ -46,0 +38,0 @@ } catch (e) {

@@ -98,8 +98,10 @@ 'use strict'

const iastContext = getIastContext(storage.getStore())
taintObject(iastContext, target, HTTP_REQUEST_COOKIE_VALUE, true, HTTP_REQUEST_COOKIE_NAME)
// Prevent tainting cookie names since it leads to taint literal string with same value.
taintObject(iastContext, target, HTTP_REQUEST_COOKIE_VALUE)
}
taintHeaders (headers, iastContext) {
// Prevent tainting header names since it leads to taint literal string with same value.
this.execSource({
handler: () => taintObject(iastContext, headers, HTTP_REQUEST_HEADER_VALUE, true, HTTP_REQUEST_HEADER_NAME),
handler: () => taintObject(iastContext, headers, HTTP_REQUEST_HEADER_VALUE),
tags: REQ_HEADER_TAGS,

@@ -106,0 +108,0 @@ iastContext

module.exports = {
COMMAND_INJECTION: 'COMMAND_INJECTION',
HARDCODED_PASSWORD: 'HARDCODED_PASSWORD',
HARDCODED_SECRET: 'HARDCODED_SECRET',

@@ -4,0 +5,0 @@ HEADER_INJECTION: 'HEADER_INJECTION',

@@ -11,3 +11,3 @@ 'use strict'

function enable (config) {
function enable (config, appsec) {
rc = new RemoteConfigManager(config)

@@ -35,3 +35,3 @@ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_CUSTOM_TAGS, true)

if (activation === Activation.ONECLICK) {
enableOrDisableAppsec(action, rcConfig, config)
enableOrDisableAppsec(action, rcConfig, config, appsec)
}

@@ -46,3 +46,3 @@

function enableOrDisableAppsec (action, rcConfig, config) {
function enableOrDisableAppsec (action, rcConfig, config, appsec) {
if (typeof rcConfig.asm?.enabled === 'boolean') {

@@ -58,5 +58,5 @@ let shouldEnable

if (shouldEnable) {
require('..').enable(config)
appsec.enable(config)
} else {
require('..').disable()
appsec.disable()
}

@@ -63,0 +63,0 @@ }

@@ -11,3 +11,4 @@ 'use strict'

incrementWafUpdatesMetric,
incrementWafRequestsMetric
incrementWafRequestsMetric,
getRequestMetrics
} = require('./telemetry')

@@ -96,3 +97,2 @@ const zlib = require('zlib')

function reportMetrics (metrics) {
// TODO: metrics should be incremental, there already is an RFC to report metrics
const store = storage.getStore()

@@ -102,10 +102,2 @@ const rootSpan = store?.req && web.root(store.req)

if (metrics.duration) {
rootSpan.setTag('_dd.appsec.waf.duration', metrics.duration)
}
if (metrics.durationExt) {
rootSpan.setTag('_dd.appsec.waf.duration_ext', metrics.durationExt)
}
if (metrics.rulesVersion) {

@@ -185,2 +177,11 @@ rootSpan.setTag('_dd.appsec.event_rules.version', metrics.rulesVersion)

const metrics = getRequestMetrics(req)
if (metrics?.duration) {
rootSpan.setTag('_dd.appsec.waf.duration', metrics.duration)
}
if (metrics?.durationExt) {
rootSpan.setTag('_dd.appsec.waf.duration_ext', metrics.durationExt)
}
incrementWafRequestsMetric(req)

@@ -187,0 +188,0 @@

@@ -8,2 +8,3 @@ 'use strict'

const DD_TELEMETRY_WAF_RESULT_TAGS = Symbol('_dd.appsec.telemetry.waf.result.tags')
const DD_TELEMETRY_REQUEST_METRICS = Symbol('_dd.appsec.telemetry.request.metrics')

@@ -30,6 +31,15 @@ const tags = {

function newStore () {
return {
[DD_TELEMETRY_REQUEST_METRICS]: {
duration: 0,
durationExt: 0
}
}
}
function getStore (req) {
let store = metricsStoreMap.get(req)
if (!store) {
store = {}
store = newStore()
metricsStoreMap.set(req, store)

@@ -56,5 +66,3 @@ }

function getOrCreateMetricTags (req, versionsTags) {
const store = getStore(req)
function getOrCreateMetricTags (store, versionsTags) {
let metricTags = store[DD_TELEMETRY_WAF_RESULT_TAGS]

@@ -75,4 +83,11 @@ if (!metricTags) {

function updateWafRequestsMetricTags (metrics, req) {
if (!req || !enabled) return
if (!req) return
const store = getStore(req)
// it does not depend on whether telemetry is enabled or not
addRequestMetrics(store, metrics)
if (!enabled) return
const versionsTags = getVersionsTags(metrics.wafVersion, metrics.rulesVersion)

@@ -82,3 +97,3 @@

const metricTags = getOrCreateMetricTags(req, versionsTags)
const metricTags = getOrCreateMetricTags(store, versionsTags)

@@ -129,2 +144,14 @@ const { blockTriggered, ruleTriggered, wafTimeout } = metrics

function addRequestMetrics (store, { duration, durationExt }) {
store[DD_TELEMETRY_REQUEST_METRICS].duration += duration || 0
store[DD_TELEMETRY_REQUEST_METRICS].durationExt += durationExt || 0
}
function getRequestMetrics (req) {
if (req) {
const store = getStore(req)
return store?.[DD_TELEMETRY_REQUEST_METRICS]
}
}
module.exports = {

@@ -137,3 +164,5 @@ enable,

incrementWafUpdatesMetric,
incrementWafRequestsMetric
incrementWafRequestsMetric,
getRequestMetrics
}

@@ -192,3 +192,4 @@ 'use strict'

isEarlyFlakeDetectionEnabled,
earlyFlakeDetectionNumRetries
earlyFlakeDetectionNumRetries,
earlyFlakeDetectionFaultyThreshold
} = remoteConfiguration

@@ -201,3 +202,4 @@ return {

isEarlyFlakeDetectionEnabled: isEarlyFlakeDetectionEnabled && this._config.isEarlyFlakeDetectionEnabled,
earlyFlakeDetectionNumRetries
earlyFlakeDetectionNumRetries,
earlyFlakeDetectionFaultyThreshold
}

@@ -204,0 +206,0 @@ }

@@ -117,2 +117,6 @@ const fs = require('fs')

if (commitsToUpload === null) {
return callback(new Error('git rev-list failed'))
}
callback(null, commitsToUpload)

@@ -256,5 +260,4 @@ })

const latestCommits = getLatestCommits()
let latestCommits = getLatestCommits()
log.debug(`There were ${latestCommits.length} commits since last month.`)
const [headCommit] = latestCommits

@@ -273,2 +276,3 @@ const getOnFinishGetCommitsToUpload = (hasCheckedShallow) => (err, commitsToUpload) => {

if (hasCheckedShallow || !isShallowRepository()) {
const [headCommit] = latestCommits
return generateAndUploadPackFiles({

@@ -286,2 +290,5 @@ url,

unshallowRepository()
// The latest commits change after unshallowing
latestCommits = getLatestCommits()
getCommitsToUpload({

@@ -288,0 +295,0 @@ url,

@@ -15,2 +15,3 @@ const request = require('../../exporters/common/request')

const DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES = 2
const DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD = 30

@@ -108,3 +109,5 @@ function getLibraryConfiguration ({

earlyFlakeDetectionNumRetries:
earlyFlakeDetectionConfig?.slow_test_retries?.['5s'] || DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES
earlyFlakeDetectionConfig?.slow_test_retries?.['5s'] || DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES,
earlyFlakeDetectionFaultyThreshold:
earlyFlakeDetectionConfig?.faulty_session_threshold ?? DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD
}

@@ -111,0 +114,0 @@

@@ -18,5 +18,61 @@ 'use strict'

const { updateConfig } = require('./telemetry')
const telemetryMetrics = require('./telemetry/metrics')
const { getIsGCPFunction, getIsAzureFunctionConsumptionPlan } = require('./serverless')
const { ORIGIN_KEY } = require('./constants')
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
const telemetryCounters = {
'otel.env.hiding': {},
'otel.env.invalid': {}
}
function getCounter (event, ddVar, otelVar, otelTracesSamplerArg) {
const counters = telemetryCounters[event]
const tags = []
if (ddVar) tags.push(ddVar)
if (otelVar) tags.push(otelVar)
if (otelTracesSamplerArg) tags.push(otelTracesSamplerArg)
if (!(ddVar in counters)) counters[ddVar] = {}
const counter = tracerMetrics.count(event, tags)
counters[ddVar][otelVar] = counter
return counter
}
const otelDdEnvMapping = {
DD_TRACE_LOG_LEVEL: 'OTEL_LOG_LEVEL',
DD_TRACE_PROPAGATION_STYLE: 'OTEL_PROPAGATORS',
DD_SERVICE: 'OTEL_SERVICE_NAME',
DD_TRACE_SAMPLE_RATE: 'OTEL_TRACES_SAMPLER',
DD_TRACE_ENABLED: 'OTEL_TRACES_EXPORTER',
DD_RUNTIME_METRICS_ENABLED: 'OTEL_METRICS_EXPORTER',
DD_TAGS: 'OTEL_RESOURCE_ATTRIBUTES',
DD_TRACE_OTEL_ENABLED: 'OTEL_SDK_DISABLED'
}
const otelInvalidEnv = ['OTEL_LOGS_EXPORTER']
function checkIfBothOtelAndDdEnvVarSet () {
for (const [ddVar, otelVar] of Object.entries(otelDdEnvMapping)) {
if (process.env[ddVar] && process.env[otelVar]) {
log.warn(`both ${ddVar} and ${otelVar} environment variables are set`)
getCounter('otel.env.hiding', ddVar, otelVar,
otelVar === 'OTEL_TRACES_SAMPLER' &&
process.env.OTEL_TRACES_SAMPLER_ARG
? 'OTEL_TRACES_SAMPLER_ARG'
: undefined).inc()
}
}
for (const otelVar of otelInvalidEnv) {
if (process.env[otelVar]) {
log.warn(`${otelVar} is not supported by the Datadog SDK`)
getCounter('otel.env.invalid', otelVar).inc()
}
}
}
const fromEntries = Object.fromEntries || (entries =>

@@ -31,2 +87,3 @@ entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))

const defaultWafObfuscatorValueRegex = '(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:\\s*=[^;]|"\\s*:\\s*"[^"]+")|bearer\\s+[a-z0-9\\._\\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\\w=-]+\\.ey[I-L][\\w=-]+(?:\\.[\\w.+\\/=-]+)?|[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}'
const runtimeId = uuid()

@@ -93,3 +150,4 @@ function maybeFile (filepath) {

const envKey = `DD_TRACE_PROPAGATION_STYLE_${key.toUpperCase()}`
const envVar = coalesce(process.env[envKey], process.env.DD_TRACE_PROPAGATION_STYLE)
const envVar = coalesce(process.env[envKey], process.env.DD_TRACE_PROPAGATION_STYLE, process.env.OTEL_PROPAGATORS)
if (typeof envVar !== 'undefined') {

@@ -113,2 +171,4 @@ return envVar.split(',')

checkIfBothOtelAndDdEnvVarSet()
// Configure the logger first so it can be used to warn about other configs

@@ -120,5 +180,7 @@ this.debug = isTrue(coalesce(

this.logger = options.logger
this.logLevel = coalesce(
options.logLevel,
process.env.DD_TRACE_LOG_LEVEL,
process.env.OTEL_LOG_LEVEL,
'debug'

@@ -170,3 +232,3 @@ )

}
const DD_TRACE_PROPAGATION_STYLE_INJECT = propagationStyle(
const PROPAGATION_STYLE_INJECT = propagationStyle(
'inject',

@@ -176,3 +238,3 @@ options.tracePropagationStyle,

)
const DD_TRACE_PROPAGATION_STYLE_EXTRACT = propagationStyle(
const PROPAGATION_STYLE_EXTRACT = propagationStyle(
'extract',

@@ -262,4 +324,9 @@ options.tracePropagationStyle,

this.tracePropagationStyle = {
inject: DD_TRACE_PROPAGATION_STYLE_INJECT,
extract: DD_TRACE_PROPAGATION_STYLE_EXTRACT
inject: PROPAGATION_STYLE_INJECT,
extract: PROPAGATION_STYLE_EXTRACT,
otelPropagators: process.env.DD_TRACE_PROPAGATION_STYLE ||
process.env.DD_TRACE_PROPAGATION_STYLE_INJECT ||
process.env.DD_TRACE_PROPAGATION_STYLE_EXTRACT
? false
: !!process.env.OTEL_PROPAGATORS
}

@@ -302,3 +369,3 @@ this.tracePropagationExtractFirst = isTrue(DD_TRACE_PROPAGATION_EXTRACT_FIRST)

version: this.version,
'runtime-id': uuid()
'runtime-id': runtimeId
})

@@ -537,3 +604,8 @@

DD_TRACING_ENABLED,
DD_VERSION
DD_VERSION,
OTEL_SERVICE_NAME,
OTEL_RESOURCE_ATTRIBUTES,
OTEL_TRACES_SAMPLER,
OTEL_TRACES_SAMPLER_ARG,
OTEL_METRICS_EXPORTER
} = process.env

@@ -544,2 +616,3 @@

tagger.add(tags, OTEL_RESOURCE_ATTRIBUTES, true)
tagger.add(tags, DD_TAGS)

@@ -605,7 +678,20 @@ tagger.add(tags, DD_TRACE_TAGS)

this._setBoolean(env, 'reportHostname', DD_TRACE_REPORT_HOSTNAME)
this._setBoolean(env, 'runtimeMetrics', DD_RUNTIME_METRICS_ENABLED)
this._setUnit(env, 'sampleRate', DD_TRACE_SAMPLE_RATE)
// only used to explicitly set runtimeMetrics to false
const otelSetRuntimeMetrics = String(OTEL_METRICS_EXPORTER).toLowerCase() === 'none'
? false
: undefined
this._setBoolean(env, 'runtimeMetrics', DD_RUNTIME_METRICS_ENABLED ||
otelSetRuntimeMetrics)
const OTEL_TRACES_SAMPLER_MAPPING = {
always_on: '1.0',
always_off: '0.0',
traceidratio: OTEL_TRACES_SAMPLER_ARG,
parentbased_always_on: '1.0',
parentbased_always_off: '0.0',
parentbased_traceidratio: OTEL_TRACES_SAMPLER_ARG
}
this._setUnit(env, 'sampleRate', DD_TRACE_SAMPLE_RATE || OTEL_TRACES_SAMPLER_MAPPING[OTEL_TRACES_SAMPLER])
this._setValue(env, 'sampler.rateLimit', DD_TRACE_RATE_LIMIT)
this._setString(env, 'scope', DD_TRACE_SCOPE)
this._setString(env, 'service', DD_SERVICE || DD_SERVICE_NAME || tags.service)
this._setString(env, 'service', DD_SERVICE || DD_SERVICE_NAME || tags.service || OTEL_SERVICE_NAME)
this._setString(env, 'site', DD_SITE)

@@ -838,2 +924,3 @@ if (DD_TRACE_SPAN_ATTRIBUTE_SCHEMA) {

tagger.add(tags, options.tracing_tags)
if (Object.keys(tags).length) tags['runtime-id'] = runtimeId

@@ -840,0 +927,0 @@ this._setUnit(opts, 'sampleRate', options.tracing_sampling_rate)

@@ -15,2 +15,3 @@ 'use strict'

const TYPE_DISTRIBUTION = 'd'
const TYPE_HISTOGRAM = 'h'

@@ -50,2 +51,6 @@ class DogStatsDClient {

histogram (stat, value, tags) {
this._add(stat, value, TYPE_HISTOGRAM, tags)
}
flush () {

@@ -185,12 +190,2 @@ const queue = this._enqueue()

class NoopDogStatsDClient {
gauge () { }
increment () { }
distribution () { }
flush () { }
}
// This is a simplified user-facing proxy to the underlying DogStatsDClient instance

@@ -235,2 +230,10 @@ class CustomMetrics {

histogram (stat, value, tags) {
return this.dogstatsd.histogram(
stat,
value,
CustomMetrics.tagTranslator(tags)
)
}
flush () {

@@ -259,4 +262,3 @@ return this.dogstatsd.flush()

DogStatsDClient,
NoopDogStatsDClient,
CustomMetrics
}

@@ -8,4 +8,8 @@ 'use strict'

module.exports = isFalse(process.env.DD_TRACE_ENABLED) || inJestWorker
const ddTraceDisabled = process.env.DD_TRACE_ENABLED
? isFalse(process.env.DD_TRACE_ENABLED)
: String(process.env.OTEL_TRACES_EXPORTER).toLowerCase() === 'none'
module.exports = ddTraceDisabled || inJestWorker
? require('./noop/proxy')
: require('./proxy')

@@ -5,5 +5,7 @@ 'use strict'

const NoopAppsecSdk = require('../appsec/sdk/noop')
const NoopDogStatsDClient = require('./dogstatsd')
const noop = new NoopTracer()
const noopAppsec = new NoopAppsecSdk()
const noopDogStatsDClient = new NoopDogStatsDClient()

@@ -14,2 +16,3 @@ class Tracer {

this.appsec = noopAppsec
this.dogstatsd = noopDogStatsDClient
}

@@ -16,0 +19,0 @@

@@ -227,9 +227,15 @@ 'use strict'

break
case 'b3': // TODO: should match "b3 single header" in next major
case 'b3' && this
._config
.tracePropagationStyle
.otelPropagators: // TODO: should match "b3 single header" in next major
case 'b3 single header': // TODO: delete in major after singular "b3"
spanContext = this._extractB3SingleContext(carrier)
break
case 'b3':
case 'b3multi':
spanContext = this._extractB3MultiContext(carrier)
break
case 'b3 single header': // TODO: delete in major after singular "b3"
spanContext = this._extractB3SingleContext(carrier)
break
default:
log.warn(`Unknown propagation style: ${extractor}`)
}

@@ -236,0 +242,0 @@

@@ -36,2 +36,3 @@ 'use strict'

const startCh = channel('dd-trace:span:start')
const finishCh = channel('dd-trace:span:finish')

@@ -100,2 +101,3 @@

spanleak.addSpan(this, operationName)
startCh.publish(this)
}

@@ -102,0 +104,0 @@

@@ -48,2 +48,3 @@ 'use strict'

get 'jest-jasmine2' () { return require('../../../datadog-plugin-jest/src') },
get 'jest-runtime' () { return require('../../../datadog-plugin-jest/src') },
get 'jest-worker' () { return require('../../../datadog-plugin-jest/src') },

@@ -81,2 +82,3 @@ get koa () { return require('../../../datadog-plugin-koa/src') },

get router () { return require('../../../datadog-plugin-router/src') },
get 'selenium-webdriver' () { return require('../../../datadog-plugin-selenium/src') },
get sharedb () { return require('../../../datadog-plugin-sharedb/src') },

@@ -83,0 +85,0 @@ get tedious () { return require('../../../datadog-plugin-tedious/src') },

@@ -31,3 +31,3 @@ const cp = require('child_process')

const GIT_REV_LIST_MAX_BUFFER = 8 * 1024 * 1024 // 8MB
const GIT_REV_LIST_MAX_BUFFER = 12 * 1024 * 1024 // 12MB

@@ -57,7 +57,11 @@ function sanitizedExec (

return result
} catch (e) {
} catch (err) {
if (errorMetric) {
incrementCountMetric(errorMetric.name, { ...errorMetric.tags, exitCode: e.status })
incrementCountMetric(errorMetric.name, {
...errorMetric.tags,
errorType: err.code,
exitCode: err.status || err.errno
})
}
log.error(e)
log.error(err)
return ''

@@ -134,3 +138,6 @@ } finally {

log.error(err)
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'unshallow', exitCode: err.status })
incrementCountMetric(
TELEMETRY_GIT_COMMAND_ERRORS,
{ command: 'unshallow', errorType: err.code, exitCode: err.status || err.errno }
)
const upstreamRemote = sanitizedExec('git', ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'])

@@ -145,3 +152,6 @@ try {

log.error(err)
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'unshallow', exitCode: err.status })
incrementCountMetric(
TELEMETRY_GIT_COMMAND_ERRORS,
{ command: 'unshallow', errorType: err.code, exitCode: err.status || err.errno }
)
// We use sanitizedExec here because if this last option fails, we'll give up.

@@ -182,3 +192,6 @@ sanitizedExec(

log.error(`Get latest commits failed: ${err.message}`)
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'get_local_commits', errorType: err.status })
incrementCountMetric(
TELEMETRY_GIT_COMMAND_ERRORS,
{ command: 'get_local_commits', errorType: err.status }
)
return []

@@ -189,3 +202,3 @@ }

function getCommitsRevList (commitsToExclude, commitsToInclude) {
let result = []
let result = null

@@ -214,3 +227,6 @@ const commitsToExcludeString = commitsToExclude.map(commit => `^${commit}`)

log.error(`Get commits to upload failed: ${err.message}`)
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'get_objects', errorType: err.status })
incrementCountMetric(
TELEMETRY_GIT_COMMAND_ERRORS,
{ command: 'get_objects', errorType: err.code, exitCode: err.status || err.errno } // err.status might be null
)
}

@@ -255,3 +271,6 @@ distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'get_objects' }, Date.now() - startTime)

log.error(err)
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'pack_objects', errorType: err.status })
incrementCountMetric(
TELEMETRY_GIT_COMMAND_ERRORS,
{ command: 'pack_objects', exitCode: err.status || err.errno, errorType: err.code }
)
/**

@@ -273,3 +292,6 @@ * The generation of pack files in the temporary folder (from `os.tmpdir()`)

log.error(err)
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'pack_objects', errorType: err.status })
incrementCountMetric(
TELEMETRY_GIT_COMMAND_ERRORS,
{ command: 'pack_objects', exitCode: err.status || err.errno, errorType: err.code }
)
}

@@ -276,0 +298,0 @@ }

@@ -56,3 +56,4 @@ const path = require('path')

const TEST_IS_RETRY = 'test.is_retry'
const TEST_EARLY_FLAKE_IS_ENABLED = 'test.early_flake.is_enabled'
const TEST_EARLY_FLAKE_ENABLED = 'test.early_flake.enabled'
const TEST_EARLY_FLAKE_ABORT_REASON = 'test.early_flake.abort_reason'

@@ -75,2 +76,8 @@ const CI_APP_ORIGIN = 'ciapp-test'

// selenium tags
const TEST_BROWSER_DRIVER = 'test.browser.driver'
const TEST_BROWSER_DRIVER_VERSION = 'test.browser.driver_version'
const TEST_BROWSER_NAME = 'test.browser.name'
const TEST_BROWSER_VERSION = 'test.browser.version'
// jest worker variables

@@ -107,3 +114,4 @@ const JEST_WORKER_TRACE_PAYLOAD_CODE = 60

TEST_IS_RETRY,
TEST_EARLY_FLAKE_IS_ENABLED,
TEST_EARLY_FLAKE_ENABLED,
TEST_EARLY_FLAKE_ABORT_REASON,
getTestEnvironmentMetadata,

@@ -147,3 +155,8 @@ getTestParametersString,

removeEfdStringFromTestName,
addEfdStringToTestName
addEfdStringToTestName,
getIsFaultyEarlyFlakeDetection,
TEST_BROWSER_DRIVER,
TEST_BROWSER_DRIVER_VERSION,
TEST_BROWSER_NAME,
TEST_BROWSER_VERSION
}

@@ -578,1 +591,19 @@

}
function getIsFaultyEarlyFlakeDetection (projectSuites, testsBySuiteName, faultyThresholdPercentage) {
let newSuites = 0
for (const suite of projectSuites) {
if (!testsBySuiteName[suite]) {
newSuites++
}
}
const newSuitesPercentage = (newSuites / projectSuites.length) * 100
// The faulty threshold represents a percentage, but we also want to consider
// smaller projects, where big variations in the % are more likely.
// This is why we also check the absolute number of new suites.
return (
newSuites > faultyThresholdPercentage &&
newSuitesPercentage > faultyThresholdPercentage
)
}

@@ -24,2 +24,3 @@ 'use strict'

DD_PROFILING_CODEHOTSPOTS_ENABLED,
DD_PROFILING_CPU_ENABLED,
DD_PROFILING_DEBUG_SOURCE_MAPS,

@@ -169,3 +170,3 @@ DD_PROFILING_ENABLED,

DD_PROFILING_TIMELINE_ENABLED,
DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED, false))
DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED, samplingContextsAvailable))
logExperimentalVarDeprecation('TIMELINE_ENABLED')

@@ -181,3 +182,5 @@ checkOptionWithSamplingContextAllowed(this.timelineEnabled, 'Timeline view')

this.cpuProfilingEnabled = isTrue(coalesce(options.cpuProfilingEnabled,
DD_PROFILING_EXPERIMENTAL_CPU_ENABLED, false))
DD_PROFILING_CPU_ENABLED,
DD_PROFILING_EXPERIMENTAL_CPU_ENABLED, samplingContextsAvailable))
logExperimentalVarDeprecation('CPU_ENABLED')
checkOptionWithSamplingContextAllowed(this.cpuProfilingEnabled, 'CPU profiling')

@@ -294,4 +297,5 @@

// Events profiler is a profiler for timeline events
if (options.timelineEnabled) {
// Events profiler is a profiler that produces timeline events. It is only
// added if timeline is enabled and there's a wall profiler.
if (options.timelineEnabled && profilers.some(p => p instanceof WallProfiler)) {
profilers.push(new EventsProfiler(options))

@@ -298,0 +302,0 @@ }

@@ -13,2 +13,3 @@ 'use strict'

const os = require('os')
const { urlToHttpOptions } = require('url')
const perf = require('perf_hooks').performance

@@ -181,5 +182,6 @@

} else {
options.protocol = this._url.protocol
options.hostname = this._url.hostname
options.port = this._url.port
const httpOptions = urlToHttpOptions(this._url)
options.protocol = httpOptions.protocol
options.hostname = httpOptions.hostname
options.port = httpOptions.port
}

@@ -186,0 +188,0 @@

@@ -7,3 +7,6 @@ 'use strict'

const { threadNamePrefix } = require('./profilers/shared')
const dc = require('dc-polyfill')
const profileSubmittedChannel = dc.channel('datadog:profiling:profile-submitted')
function maybeSourceMap (sourceMap, SourceMapper, debug) {

@@ -165,2 +168,3 @@ if (!sourceMap) return

await this._submit(encodedProfiles, startDate, endDate, snapshotKind)
profileSubmittedChannel.publish()
this._logger.debug('Submitted profiles')

@@ -167,0 +171,0 @@ } catch (err) {

@@ -14,4 +14,21 @@ 'use strict'

const dogstatsd = require('./dogstatsd')
const NoopDogStatsDClient = require('./noop/dogstatsd')
const spanleak = require('./spanleak')
const { SSITelemetry } = require('./profiling/ssi-telemetry')
class LazyModule {
constructor (provider) {
this.provider = provider
}
enable (...args) {
this.module = this.provider()
this.module.enable(...args)
}
disable () {
this.module?.disable()
}
}
class Tracer extends NoopProxy {

@@ -24,4 +41,10 @@ constructor () {

this._pluginManager = new PluginManager(this)
this.dogstatsd = new dogstatsd.NoopDogStatsDClient()
this.dogstatsd = new NoopDogStatsDClient()
this._tracingInitialized = false
// these requires must work with esm bundler
this._modules = {
appsec: new LazyModule(() => require('./appsec')),
iast: new LazyModule(() => require('./appsec/iast'))
}
}

@@ -61,3 +84,3 @@

if (config.remoteConfig.enabled && !config.isCiVisibility) {
const rc = remoteConfig.enable(config)
const rc = remoteConfig.enable(config, this._modules.appsec)

@@ -78,2 +101,4 @@ rc.on('APM_TRACING', (action, conf) => {

const ssiTelemetry = new SSITelemetry()
ssiTelemetry.start()
if (config.profiling.enabled) {

@@ -87,2 +112,4 @@ // do not stop tracer initialization if the profiler fails to be imported

}
} else if (ssiTelemetry.enabled()) {
require('./profiling/ssi-telemetry-mock-profiler').start(config)
}

@@ -115,5 +142,4 @@ if (!this._profilerStarted) {

if (config.tracing !== false) {
// dirty require for now so zero appsec code is executed unless explicitly enabled
if (config.appsec.enabled) {
require('./appsec').enable(config)
this._modules.appsec.enable(config)
}

@@ -126,7 +152,7 @@ if (!this._tracingInitialized) {

if (config.iast.enabled) {
require('./appsec/iast').enable(config, this._tracer)
this._modules.iast.enable(config, this._tracer)
}
} else if (this._tracingInitialized) {
require('./appsec').disable()
require('./appsec/iast').disable()
this._modules.appsec.disable()
this._modules.iast.disable()
}

@@ -133,0 +159,0 @@

@@ -5,3 +5,9 @@ 'use strict'

function add (carrier, keyValuePairs) {
const otelTagMap = {
'deployment.environment': 'env',
'service.name': 'service',
'service.version': 'version'
}
function add (carrier, keyValuePairs, parseOtelTags = false) {
if (!carrier || !keyValuePairs) return

@@ -17,8 +23,12 @@

for (const segment of segments) {
const separatorIndex = segment.indexOf(':')
const separatorIndex = parseOtelTags ? segment.indexOf('=') : segment.indexOf(':')
if (separatorIndex === -1) continue
const key = segment.slice(0, separatorIndex)
let key = segment.slice(0, separatorIndex)
const value = segment.slice(separatorIndex + 1)
if (parseOtelTags && key in otelTagMap) {
key = otelTagMap[key]
}
carrier[key.trim()] = value.trim()

@@ -25,0 +35,0 @@ }

@@ -13,2 +13,3 @@ 'use strict'

const telemetryStopChannel = dc.channel('datadog:telemetry:stop')
const telemetryAppClosingChannel = dc.channel('datadog:telemetry:app-closing')

@@ -133,8 +134,8 @@ let config

}
// Give chance to listeners to update metrics before shutting down.
telemetryAppClosingChannel.publish()
const { reqType, payload } = createPayload('app-closing')
sendData(config, application, host, reqType, payload)
// we flush before shutting down. Only in CI Visibility
if (config.isCiVisibility) {
metricsManager.send(config, application, host)
}
// We flush before shutting down.
metricsManager.send(config, application, host)
}

@@ -141,0 +142,0 @@

@@ -78,4 +78,4 @@ 'use strict'

dec (value = -1) {
return this.track(value)
dec (value = 1) {
return this.track(-value)
}

@@ -82,0 +82,0 @@

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc