Skip to content

Commit

Permalink
Merge pull request #1073 from CVEProject/jd-1063
Browse files Browse the repository at this point in the history
Resolves #1061 and #1063 Added tests for creating/updating ADP containers and rejecting records w/ adp contain
  • Loading branch information
david-rocca authored Jun 2, 2023
2 parents d1ad208 + 64e31d8 commit f07301a
Show file tree
Hide file tree
Showing 7 changed files with 300 additions and 2 deletions.
3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"jsonschema": "^1.4.0",
"JSONStream": "^1.3.5",
"kleur": "^4.1.4",
"lodash": "^4.17.21",
"mongoose": "^5.13.15",
"mongoose-aggregate-paginate-v2": "1.0.6",
"morgan": "^1.9.1",
Expand Down Expand Up @@ -95,4 +96,4 @@
"test:coverage": "NODE_ENV=test nyc --reporter=text mocha --recursive --exit || true",
"test:scripts": "NODE_ENV=development node-dev src/scripts/templateScript.js"
}
}
}
50 changes: 50 additions & 0 deletions test/schemas/5.0/adpContainerExample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"adpContainer": {
"affected": [
{
"vendor": "n/a",
"product": "n/a",
"versions": [
{
"version": "n/a",
"status": "unknown"
}
]
}
],
"descriptions": [
{
"lang": "en",
"value": "Cross-site scripting (XSS) vulnerability in Revive Adserver before 4.0.1 allows remote authenticated users to inject arbitrary web script or HTML via the user's email address."
}
],
"problemTypes": [
{
"descriptions": [
{
"description": "n/a",
"lang": "eng",
"type": "text"
}
]
}
],
"references": [
{
"name": "[oss-security] 20170202 Re: CVE request: multiples vulnerabilities in Revive Adserver",
"refsource": "MLIST",
"url": "http://www.openwall.com/lists/oss-security/2017/02/02/3"
},
{
"name": "https://www.revive-adserver.com/security/revive-sa-2017-001/",
"refsource": "CONFIRM",
"url": "https://www.revive-adserver.com/security/revive-sa-2017-001/"
},
{
"name": "95875",
"refsource": "BID",
"url": "http://www.securityfocus.com/bid/95875"
}
]
}
}
20 changes: 20 additions & 0 deletions test/schemas/5.0/rejectCveExample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"cnaContainer": {
"rejectedReasons": [
{
"lang": "qe",
"value": "I professional site herself recently behavior. Situation institution meeting recognize successful.",
"supportingMedia": [
{
"type": "test/markdown",
"base64": false,
"value": "*this* _is_ supporting media in ~markdown~"
}
]
}
],
"replacedBy": [
"CVE-1999-0006"
]
}
}
186 changes: 186 additions & 0 deletions test/unit-tests/cve/insertAdpTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
const chai = require('chai')
const sinon = require('sinon')
const { faker } = require('@faker-js/faker')
const _ = require('lodash')
const expect = chai.expect
const cveIdPublished5 = 'CVE-2017-4024'
const cveRecordPublished = require('../../schemas/5.0/CVE-2017-4024_published.json')
const adpContainer = require('../../schemas/5.0/adpContainerExample.json').adpContainer
const { CVE_INSERT_ADP } = require('../../../src/controller/cve.controller/cve.controller.js')
const errors = require('../../../src/controller/cve.controller/error.js')
const error = new errors.CveControllerError()

const OrgRepository = require('../../../src/repositories/orgRepository.js')
const CveIdRepository = require('../../../src/repositories/cveIdRepository.js')
const CveRepository = require('../../../src/repositories/cveRepository.js')
const UserRepository = require('../../../src/repositories/userRepository.js')

const adpUUID = faker.datatype.uuid()

const stubAdpOrg = {
short_name: 'adpOrg',
name: 'test_adp',
UUID: adpUUID,
authority: {
active_roles: [
'ADP'
]
}
}

const stubAdpUser = {
username: 'testAdpUser',
org_UUID: adpUUID,
UUID: faker.datatype.uuid()
}

const stubCveId = {
requested_by: {
cna: 'mitre',
user: '[email protected]'
},
cve_id: 'CVE-2017-4024',
cve_year: '2017',
state: 'PUBLISHED',
owning_cna: 'mitre',
reserved: '2023-05-17T16:57:35.698Z'
}

describe('Testing insertAdp function', () => {
let status, json, res, next, getOrgRepository,
orgRepo, getCveRepository, cveRepo, getCveIdRepository,
cveIdRepo, getUserRepository, userRepo, adpContainerCopy,
cveCopy, req

// Stub out functions called in insertAdp and reset them for each test
beforeEach(() => {
status = sinon.stub()
json = sinon.spy()
res = { json, status }
next = sinon.spy()
status.returns(res)
orgRepo = new OrgRepository()
getOrgRepository = sinon.stub()
getOrgRepository.returns(orgRepo)

userRepo = new UserRepository()
getUserRepository = sinon.stub()
getUserRepository.returns(userRepo)

cveRepo = new CveRepository()
getCveRepository = sinon.stub()
getCveRepository.returns(cveRepo)

cveIdRepo = new CveIdRepository()
getCveIdRepository = sinon.stub()
getCveIdRepository.returns(cveIdRepo)

// Deep copy because adpContainer and cveRecordPublished are directly modified in inserAdp call
adpContainerCopy = _.cloneDeep(adpContainer)
cveCopy = _.cloneDeep(cveRecordPublished)

sinon.stub(cveIdRepo, 'findOneByCveId').returns(stubCveId)
sinon.stub(orgRepo, 'getOrgUUID').returns(stubAdpOrg.UUID)
sinon.stub(userRepo, 'getUserUUID').returns(stubAdpUser.UUID)
sinon.stub(cveRepo, 'findOneByCveId').returns({ cve: cveCopy })
sinon.stub(cveRepo, 'updateByCveId').returns(true)

req = {
ctx: {
org: stubAdpOrg.short_name,
uuid: stubAdpOrg.UUID,
params: {
id: cveIdPublished5
},
repositories: {
getOrgRepository,
getUserRepository,
getCveRepository,
getCveIdRepository
},
body: {
adpContainer
}
}
}
})
context('Negative Tests', () => {
it('Should return 400 when ADP json body is the wrong format', async () => {
req.ctx.body = {
adpContainerCopy // insertAdp requires the body to have adpContainer property
}

await CVE_INSERT_ADP(req, res, next)

expect(status.args[0][0]).to.equal(400)
expect(res.json.args[0][0].message).to.equal(error.badAdpFormat().message)
expect(res.json.args[0][0].error).to.equal(error.badAdpFormat().error)
})

it('Should return 400 when ADP fails to validate', async () => {
adpContainerCopy.affected = {} // affected must be an array per the schema
req.ctx.body = {
adpContainer: adpContainerCopy
}

await CVE_INSERT_ADP(req, res, next)

expect(status.args[0][0]).to.equal(400)
expect(res.json.args[0][0].message).to.equal(error.badAdpJson().message)
expect(res.json.args[0][0].error).to.equal(error.badAdpJson().error)
})
})

context('Positive Tests', () => {
it('Should add an ADP container to an existing CVE record', async () => {
const adpCount = cveCopy.containers.adp.length

const resMessage = cveIdPublished5 + ' record had new ADP container ' + (adpCount + 1) + ' successfully inserted'
await CVE_INSERT_ADP(req, res, next)

expect(status.args[0][0]).to.equal(200)
expect(res.json.args[0][0].message).to.include(resMessage)
expect(res.json.args[0][0].updated.containers.adp[adpCount].providerMetadata.orgId).to.equal(stubAdpOrg.UUID)
expect(res.json.args[0][0].updated.containers.adp[adpCount].providerMetadata.shortName).to.equal(stubAdpOrg.short_name)

// Set providerMetadata on copy, since that field is generated, then compare objects
adpContainerCopy.providerMetadata = res.json.args[0][0].updated.containers.adp[adpCount].providerMetadata
expect(res.json.args[0][0].updated.containers.adp[adpCount]).to.deep.equal(adpContainerCopy)
})

it('Should update an existing ADP container on an existing CVE record', async () => {
const adpCopy2 = _.cloneDeep(adpContainer)
adpCopy2.providerMetadata = {
orgId: stubAdpOrg.UUID,
shortName: stubAdpOrg.short_name,
dateUpdated: faker.date.past()
}

// Create adpContainer to modify and add it to record
cveCopy.containers.adp.push(adpCopy2)

adpContainerCopy.providerMetadata = {
orgId: stubAdpOrg.UUID,
shortName: stubAdpOrg.short_name,
dateUpdated: faker.date.past()
}

// Modify container to test for changes
adpContainerCopy.affected[0].vendor = 'test'
req.ctx.body = {
adpContainer: adpContainerCopy
}

const adpCount = cveCopy.containers.adp.length
const resMessage = cveIdPublished5 + ' record had replacement ADP container ' + adpCount + ' successfully inserted'
await CVE_INSERT_ADP(req, res, next)

expect(status.args[0][0]).to.equal(200)
expect(res.json.args[0][0].message).to.include(resMessage)
expect(res.json.args[0][0].updated.containers.adp[adpCount - 1].providerMetadata.orgId).to.equal(stubAdpOrg.UUID)
expect(res.json.args[0][0].updated.containers.adp[adpCount - 1].providerMetadata.shortName).to.equal(stubAdpOrg.short_name)
expect(res.json.args[0][0].updated.containers.adp[adpCount - 1].affected[0].vendor).to.equal('test')
expect(res.json.args[0][0].updated.containers.adp[adpCount - 1]).to.not.deep.equal(adpCopy2)
})
})
})
18 changes: 18 additions & 0 deletions test/unit-tests/cve/rejectCveAdpTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const chai = require('chai')
const expect = chai.expect
const _ = require('lodash')
const cveRecordPublished = require('../../schemas/5.0/CVE-2017-4024_published.json')
const cveRejectExample = require('../../schemas/5.0/rejectCveExample.json')

const Cve = require('../../../src/model/cve')
const cveCopy = _.cloneDeep(cveRecordPublished)

describe('Testing rejecting CVE record that has an ADP container', () => {
it('Should return rejected Cve record without ADP container', async () => {
const newRecord = await Cve.updateCveToRejected('', cveRecordPublished.containers.cna.providerMetadata, cveCopy, cveRejectExample)

expect(newRecord.containers).to.not.have.property('adp')
expect(cveRecordPublished.containers).to.have.property('adp')
expect(newRecord.cveMetadata.state).to.equal('REJECTED')
})
})
22 changes: 22 additions & 0 deletions test/unit-tests/cve/validateCveWithAdpTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const chai = require('chai')
const expect = chai.expect
const _ = require('lodash')
const cveRecordPublished = require('../../schemas/5.0/CVE-2017-4024_published.json')

const Cve = require('../../../src/model/cve')
const cveCopy = _.cloneDeep(cveRecordPublished)

describe('Testing validating CVE record that has an ADP container', () => {
it('Should return TRUE for valid Cve record ADP container', () => {
const validationObj = Cve.validateCveRecord(cveCopy)
expect(validationObj.isValid).to.be.equal(true)
})

it('Should return FALSE for Cve record with invalid ADP container', () => {
// providerMetadata is a required adpContainer field, so validation will fail
delete cveCopy.containers.adp[0].providerMetadata

const validationObj = Cve.validateCveRecord(cveCopy)
expect(validationObj.isValid).to.be.equal(false)
})
})

0 comments on commit f07301a

Please sign in to comment.