Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 4 additions & 4 deletions integration-tests/aiguard/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
const assert = require('node:assert/strict')
const path = require('path')

const { expect } = require('chai')
const { after, afterEach, before, beforeEach, describe, it } = require('mocha')

const { sandboxCwd, useSandbox, FakeAgent, spawnProc } = require('../helpers')
const startApiMock = require('./api-mock')
const { executeRequest } = require('./util')
const { assertObjectContains } = require('../helpers')

describe('AIGuard SDK integration tests', () => {
let cwd, appFile, agent, proc, api, url
Expand Down Expand Up @@ -63,11 +63,11 @@ describe('AIGuard SDK integration tests', () => {
const response = await executeRequest(`${url}${endpoint}`, 'GET', headers)
if (blocking && action !== 'ALLOW') {
assert.strictEqual(response.status, 403)
expect(response.body).to.contain(reason)
assertObjectContains(response.body, reason)
} else {
assert.strictEqual(response.status, 200)
expect(response.body).to.have.nested.property('action', action)
expect(response.body).to.have.nested.property('reason', reason)
assert.strictEqual(response.body?.action, action)
assert.strictEqual(response.body?.reason, reason)
}
await agent.assertMessageReceived(({ headers, payload }) => {
const span = payload[0].find(span => span.name === 'ai_guard')
Expand Down
6 changes: 3 additions & 3 deletions integration-tests/appsec/data-collection.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const { assert } = require('chai')
const assert = require('node:assert/strict')
const path = require('path')
const Axios = require('axios')

Expand Down Expand Up @@ -55,7 +55,7 @@ describe('ASM Data collection', () => {
requestHeaders.length
)
requestHeaders.forEach((headerName) => {
assert.property(payload[0][0].meta, `http.request.headers.${headerName}`)
assert.ok(Object.hasOwn(payload[0][0].meta, `http.request.headers.${headerName}`))
})

// Response headers
Expand All @@ -64,7 +64,7 @@ describe('ASM Data collection', () => {
responseHeaders.length
)
responseHeaders.forEach((headerName) => {
assert.property(payload[0][0].meta, `http.response.headers.${headerName}`)
assert.ok(Object.hasOwn(payload[0][0].meta, `http.response.headers.${headerName}`))
})
})
}
Expand Down
30 changes: 15 additions & 15 deletions integration-tests/appsec/graphql.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const { assert } = require('chai')
const assert = require('node:assert/strict')
const path = require('path')
const axios = require('axios')

Expand Down Expand Up @@ -38,15 +38,15 @@ describe('graphql', () => {

it('should not report any attack', async () => {
const agentPromise = agent.assertMessageReceived(({ headers, payload }) => {
assert.propertyVal(headers, 'host', `127.0.0.1:${agent.port}`)
assert.isArray(payload)
assert.strictEqual(headers.host, `127.0.0.1:${agent.port}`)
assert.ok(Array.isArray(payload))
assert.strictEqual(payload.length, 2)
// Apollo server 5 is using Node.js http server instead of express
assert.propertyVal(payload[1][0], 'name', 'web.request')
assert.propertyVal(payload[1][0].metrics, '_dd.appsec.enabled', 1)
assert.property(payload[1][0].metrics, '_dd.appsec.waf.duration')
assert.notProperty(payload[1][0].meta, '_dd.appsec.event')
assert.notProperty(payload[1][0].meta, '_dd.appsec.json')
assert.strictEqual(payload[1][0].name, 'web.request')
assert.strictEqual(payload[1][0].metrics['_dd.appsec.enabled'], 1)
assert.ok(Object.hasOwn(payload[1][0].metrics, '_dd.appsec.waf.duration'))
assert.ok(!('_dd.appsec.event' in payload[1][0].meta))
assert.ok(!('_dd.appsec.json' in payload[1][0].meta))
})

await axios({
Expand Down Expand Up @@ -100,15 +100,15 @@ describe('graphql', () => {
}

const agentPromise = agent.assertMessageReceived(({ headers, payload }) => {
assert.propertyVal(headers, 'host', `127.0.0.1:${agent.port}`)
assert.isArray(payload)
assert.strictEqual(headers.host, `127.0.0.1:${agent.port}`)
assert.ok(Array.isArray(payload))
assert.strictEqual(payload.length, 2)
// Apollo server 5 is using Node.js http server instead of express
assert.propertyVal(payload[1][0], 'name', 'web.request')
assert.propertyVal(payload[1][0].metrics, '_dd.appsec.enabled', 1)
assert.property(payload[1][0].metrics, '_dd.appsec.waf.duration')
assert.propertyVal(payload[1][0].meta, 'appsec.event', 'true')
assert.property(payload[1][0].meta, '_dd.appsec.json')
assert.strictEqual(payload[1][0].name, 'web.request')
assert.strictEqual(payload[1][0].metrics['_dd.appsec.enabled'], 1)
assert.ok(Object.hasOwn(payload[1][0].metrics, '_dd.appsec.waf.duration'))
assert.strictEqual(payload[1][0].meta['appsec.event'], 'true')
assert.ok(Object.hasOwn(payload[1][0].meta, '_dd.appsec.json'))
assert.deepStrictEqual(JSON.parse(payload[1][0].meta['_dd.appsec.json']), result)
})

Expand Down
11 changes: 6 additions & 5 deletions integration-tests/appsec/iast-esbuild.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict'

const assert = require('node:assert/strict')

const Axios = require('axios')
const { assert } = require('chai')
const childProcess = require('child_process')
const fs = require('fs')
const path = require('path')
Expand Down Expand Up @@ -34,7 +35,7 @@ describe('esbuild support for IAST', () => {
return 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.ok(Object.hasOwn(span.meta, '_dd.iast.json'))
const spanIastData = JSON.parse(span.meta['_dd.iast.json'])
assert.strictEqual(spanIastData.vulnerabilities[0].type, 'COMMAND_INJECTION')
assert.strictEqual(spanIastData.vulnerabilities[0].location.path, expectedPath)
Expand All @@ -43,8 +44,8 @@ describe('esbuild support for IAST', () => {
}

const ddStack = msgpack.decode(span.meta_struct['_dd.stack'])
assert.property(ddStack.vulnerability[0], 'frames')
assert.isNotEmpty(ddStack.vulnerability[0].frames)
assert.ok(Object.hasOwn(ddStack.vulnerability[0], 'frames'))
assert.ok(ddStack.vulnerability[0].frames.length > 0)
})
}, null, 1, true)
}
Expand All @@ -53,7 +54,7 @@ describe('esbuild support for IAST', () => {
return 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.ok(!('_dd.iast.json' in span.meta))
})
}, null, 1, true)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict'

const assert = require('node:assert/strict')

const { sandboxCwd, useSandbox, spawnProc, FakeAgent } = require('../helpers')
const childProcess = require('child_process')
const path = require('path')
const Axios = require('axios')
const { assert } = require('chai')

describe('IAST stack traces and vulnerabilities with sourcemaps', () => {
let axios, cwd, appDir, appFile, agent, proc

Expand Down Expand Up @@ -49,13 +49,13 @@ describe('IAST stack traces and vulnerabilities with sourcemaps', () => {
it('should detect correct stack trace in unnamed function', async () => {
const response = await axios.get('/rewritten/stack-trace-from-unnamed-function')

assert.include(response.data, '/rewritten-routes.ts:7:13')
assert.match(response.data, /\/rewritten-routes\.ts:7:13/)
})

it('should detect correct stack trace in named function', async () => {
const response = await axios.get('/rewritten/stack-trace-from-named-function')

assert.include(response.data, '/rewritten-routes.ts:11:13')
assert.match(response.data, /\/rewritten-routes\.ts:11:13/)
})

it('should detect vulnerability in the correct location', async () => {
Expand All @@ -64,14 +64,14 @@ describe('IAST stack traces and vulnerabilities with sourcemaps', () => {
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.ok(Object.hasOwn(span.meta, '_dd.iast.json'))
const iastJsonObject = JSON.parse(span.meta['_dd.iast.json'])

assert.isTrue(iastJsonObject.vulnerabilities.some(vulnerability => {
assert.strictEqual(iastJsonObject.vulnerabilities.some(vulnerability => {
return vulnerability.type === 'WEAK_HASH' &&
vulnerability.location.path === 'appsec/iast-stack-traces-ts-with-sourcemaps/rewritten-routes.ts' &&
vulnerability.location.line === 15
}))
}), true)
})
}, null, 1, true)
})
Expand All @@ -81,13 +81,13 @@ describe('IAST stack traces and vulnerabilities with sourcemaps', () => {
it('should detect correct stack trace in unnamed function', async () => {
const response = await axios.get('/not-rewritten/stack-trace-from-unnamed-function')

assert.include(response.data, '/not-rewritten-routes.ts:7:13')
assert.match(response.data, /\/not-rewritten-routes\.ts:7:13/)
})

it('should detect correct stack trace in named function', async () => {
const response = await axios.get('/not-rewritten/stack-trace-from-named-function')

assert.include(response.data, '/not-rewritten-routes.ts:11:13')
assert.match(response.data, /\/not-rewritten-routes\.ts:11:13/)
})

it('should detect vulnerability in the correct location', async () => {
Expand All @@ -96,14 +96,14 @@ describe('IAST stack traces and vulnerabilities with sourcemaps', () => {
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.ok(Object.hasOwn(span.meta, '_dd.iast.json'))
const iastJsonObject = JSON.parse(span.meta['_dd.iast.json'])

assert.isTrue(iastJsonObject.vulnerabilities.some(vulnerability => {
assert.strictEqual(iastJsonObject.vulnerabilities.some(vulnerability => {
return vulnerability.type === 'WEAK_HASH' &&
vulnerability.location.path === 'appsec/iast-stack-traces-ts-with-sourcemaps/not-rewritten-routes.ts' &&
vulnerability.location.line === 15
}))
}), true)
})
}, null, 1, true)
})
Expand Down
28 changes: 14 additions & 14 deletions integration-tests/appsec/iast.esm-security-controls.spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use strict'

const assert = require('node:assert/strict')

const { sandboxCwd, useSandbox, spawnProc, FakeAgent } = require('../helpers')
const path = require('path')
const Axios = require('axios')
const { assert } = require('chai')

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

Expand Down Expand Up @@ -51,8 +51,8 @@ describe('ESM Security controls', () => {
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"')
assert.ok(Object.hasOwn(span.meta, '_dd.iast.json'))
assert.match(span.meta['_dd.iast.json'], /"COMMAND_INJECTION"/)
})
}, null, 1, true)
})
Expand All @@ -63,8 +63,8 @@ describe('ESM Security controls', () => {
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')
assert.ok(!('_dd.iast.json' in span.meta))
assert.ok(Object.hasOwn(span.metrics, '_dd.iast.telemetry.suppressed.vulnerabilities.command_injection'))
})
}, null, 1, true)
})
Expand All @@ -75,8 +75,8 @@ describe('ESM Security controls', () => {
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')
assert.ok(!('_dd.iast.json' in span.meta))
assert.ok(Object.hasOwn(span.metrics, '_dd.iast.telemetry.suppressed.vulnerabilities.command_injection'))
})
}, null, 1, true)
})
Expand All @@ -87,8 +87,8 @@ describe('ESM Security controls', () => {
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"')
assert.ok(Object.hasOwn(span.meta, '_dd.iast.json'))
assert.match(span.meta['_dd.iast.json'], /"COMMAND_INJECTION"/)
})
}, null, 1, true)
})
Expand All @@ -99,8 +99,8 @@ describe('ESM Security controls', () => {
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')
assert.ok(!('_dd.iast.json' in span.meta))
assert.ok(Object.hasOwn(span.metrics, '_dd.iast.telemetry.suppressed.vulnerabilities.command_injection'))
})
}, null, 1, true)
})
Expand All @@ -111,8 +111,8 @@ describe('ESM Security controls', () => {
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')
assert.ok(!('_dd.iast.json' in span.meta))
assert.ok(Object.hasOwn(span.metrics, '_dd.iast.telemetry.suppressed.vulnerabilities.command_injection'))
})
}, null, 1, true)
})
Expand Down
12 changes: 6 additions & 6 deletions integration-tests/appsec/iast.esm.spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use strict'

const assert = require('node:assert/strict')

const { sandboxCwd, useSandbox, spawnProc, FakeAgent } = require('../helpers')
const path = require('path')
const Axios = require('axios')
const { assert } = require('chai')

describe('ESM', () => {
let axios, cwd, appFile, agent, proc

Expand Down Expand Up @@ -64,8 +64,8 @@ describe('ESM', () => {

await agent.assertMessageReceived(({ payload }) => {
verifySpan(payload, span => {
assert.property(span.meta, '_dd.iast.json')
assert.include(span.meta['_dd.iast.json'], '"COMMAND_INJECTION"')
assert.ok(Object.hasOwn(span.meta, '_dd.iast.json'))
assert.match(span.meta['_dd.iast.json'], /"COMMAND_INJECTION"/)
})
}, null, 1, true)
})
Expand All @@ -75,8 +75,8 @@ describe('ESM', () => {

await agent.assertMessageReceived(({ payload }) => {
verifySpan(payload, span => {
assert.property(span.meta, '_dd.iast.json')
assert.include(span.meta['_dd.iast.json'], '"COMMAND_INJECTION"')
assert.ok(Object.hasOwn(span.meta, '_dd.iast.json'))
assert.match(span.meta['_dd.iast.json'], /"COMMAND_INJECTION"/)
})
}, null, 1, true)
})
Expand Down
17 changes: 9 additions & 8 deletions integration-tests/appsec/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use strict'

const assert = require('node:assert/strict')

const path = require('path')
const Axios = require('axios')
const { assert } = require('chai')
const msgpack = require('@msgpack/msgpack')
const { sandboxCwd, useSandbox, FakeAgent, spawnProc } = require('../helpers')

Expand Down Expand Up @@ -49,18 +50,18 @@ describe('RASP', () => {

async function assertExploitDetected () {
await agent.assertMessageReceived(({ headers, payload }) => {
assert.property(payload[0][0].meta, '_dd.appsec.json')
assert.include(payload[0][0].meta['_dd.appsec.json'], '"test-rule-id-2"')
assert.ok(Object.hasOwn(payload[0][0].meta, '_dd.appsec.json'))
assert.match(payload[0][0].meta['_dd.appsec.json'], /"test-rule-id-2"/)
})
}

async function assertBodyReported (expectedBody, truncated) {
await agent.assertMessageReceived(({ headers, payload }) => {
assert.property(payload[0][0].meta_struct, 'http.request.body')
assert.ok(Object.hasOwn(payload[0][0].meta_struct, 'http.request.body'))
assert.deepStrictEqual(msgpack.decode(payload[0][0].meta_struct['http.request.body']), expectedBody)

if (truncated) {
assert.property(payload[0][0].meta, '_dd.appsec.rasp.request_body_size.exceeded')
assert.ok(Object.hasOwn(payload[0][0].meta, '_dd.appsec.rasp.request_body_size.exceeded'))
}
})
}
Expand Down Expand Up @@ -338,8 +339,8 @@ describe('RASP', () => {
}

// not blocked
assert.notEqual(response.status, 418)
assert.notEqual(response.status, 403)
assert.notStrictEqual(response.status, 418)
assert.notStrictEqual(response.status, 403)
await assertExploitDetected()
})
})
Expand Down Expand Up @@ -399,7 +400,7 @@ describe('RASP', () => {
}

await agent.assertMessageReceived(({ headers, payload }) => {
assert.notProperty(payload[0][0].meta_struct, 'http.request.body')
assert.ok(!('http.request.body' in payload[0][0].meta_struct))
})
}
})
Expand Down
Loading
Loading