Skip to content

Commit

Permalink
Merge pull request #1086 from CVEProject/dr-1075
Browse files Browse the repository at this point in the history
Resolves #1075 - Addition of cna_modified boolean
  • Loading branch information
jdaigneau5 committed Jun 22, 2023
2 parents d3d26d1 + 99c21d6 commit 596c0ce
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 6 deletions.
32 changes: 31 additions & 1 deletion src/controller/cve.controller/cve.controller.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Cve = require('../../model/cve')
const logger = require('../../middleware/logger')
const errors = require('./error')
const { toDate } = require('../../utils/utils')
const getConstants = require('../../constants').getConstants
const error = new errors.CveControllerError()
const booleanIsTrue = require('../../utils/utils').booleanIsTrue
Expand Down Expand Up @@ -44,6 +45,9 @@ async function getFilteredCves (req, res, next) {
let state = null
let assignerShortName = null
let assigner = null
let cnaModified = false
let timeModifiedGtDateObject = null
let timeModifiedLtDateObject = null
const timeModified = {
timeStamp: [],
dateOperator: []
Expand All @@ -64,15 +68,19 @@ async function getFilteredCves (req, res, next) {
if (key === 'time_modified.lt') {
timeModified.dateOperator.push('lt')
timeModified.timeStamp.push(req.ctx.query['time_modified.lt'])
timeModifiedLtDateObject = req.ctx.query['time_modified.lt']
} else if (key === 'time_modified.gt') {
timeModified.dateOperator.push('gt')
timeModified.timeStamp.push(req.ctx.query['time_modified.gt'])
timeModifiedGtDateObject = req.ctx.query['time_modified.gt']
} else if (key === 'state') {
state = req.ctx.query.state
} else if (key === 'assigner_short_name') { // the key is retrieved as lowercase
assignerShortName = req.ctx.query.assigner_short_name
} else if (key === 'assigner') {
assigner = req.ctx.query.assigner
} else if (key === 'cna_modified') {
cnaModified = req.ctx.query.cna_modified
}
})

Expand Down Expand Up @@ -134,7 +142,29 @@ async function getFilteredCves (req, res, next) {
}

const pg = await cveRepo.aggregatePaginate(agt, options)
const payload = { cveRecords: pg.itemsList.map(val => { return val.cve }) }
const payload = {
cveRecords: pg.itemsList.map(val => { return val.cve }).filter((val) => {
// If cnaModified is false, return all values.
if (!cnaModified) {
return true
}
// Check that the CNA has a date updated
if ((val.containers.cna.providerMetadata?.dateUpdated)) {
// If the time modified gt flag is set, and the dateUpdated date is less than the flag
if ((timeModifiedGtDateObject && timeModifiedGtDateObject > toDate(val.containers.cna.providerMetadata?.dateUpdated))) {
return false
}
// if the time modified lt flag is set, and the dateUpdated date is greater than the flag
if ((timeModifiedLtDateObject && timeModifiedLtDateObject < toDate(val.containers.cna.providerMetadata?.dateUpdated))) {
return false
}
// If the code gets to this point, all checks have passed.
return true
}
// Base fall through case
return false
})
}

if (pg.itemCount >= CONSTANTS.PAGINATOR_OPTIONS.limit) {
payload.totalCount = pg.itemCount
Expand Down
2 changes: 1 addition & 1 deletion src/controller/cve.controller/cve.middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function parsePostParams (req, res, next) {
}

function parseGetParams (req, res, next) {
utils.reqCtxMapping(req, 'query', ['page', 'time_modified.lt', 'time_modified.gt', 'state', 'count_only', 'assigner_short_name', 'assigner'])
utils.reqCtxMapping(req, 'query', ['page', 'time_modified.lt', 'time_modified.gt', 'state', 'count_only', 'assigner_short_name', 'assigner', 'cna_modified'])
utils.reqCtxMapping(req, 'params', ['id'])
next()
}
Expand Down
3 changes: 2 additions & 1 deletion src/controller/cve.controller/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,15 @@ router.get('/cve',
*/
mw.validateUser,
mw.onlySecretariatOrBulkDownload,
query().custom((query) => { return mw.validateQueryParameterNames(query, ['page', 'time_modified.lt', 'time_modified.gt', 'state', 'count_only', 'assigner_short_name', 'assigner']) }),
query().custom((query) => { return mw.validateQueryParameterNames(query, ['page', 'time_modified.lt', 'time_modified.gt', 'state', 'count_only', 'assigner_short_name', 'assigner', 'cna_modified']) }),
query(['page']).optional().isInt({ min: CONSTANTS.PAGINATOR_PAGE }),
query(['time_modified.lt']).optional().isString().trim().escape().customSanitizer(val => { return toDate(val) }).not().isEmpty().withMessage(errorMsgs.TIMESTAMP_FORMAT),
query(['time_modified.gt']).optional().isString().trim().escape().customSanitizer(val => { return toDate(val) }).not().isEmpty().withMessage(errorMsgs.TIMESTAMP_FORMAT),
query(['state']).optional().isString().trim().escape().customSanitizer(val => { return val.toUpperCase() }).isIn(CHOICES).withMessage(errorMsgs.CVE_FILTERED_STATES),
query(['count_only']).optional().isBoolean({ loose: true }).withMessage(errorMsgs.COUNT_ONLY),
query(['assigner_short_name']).optional().isString().trim().escape().notEmpty().isLength({ min: CONSTANTS.MIN_SHORTNAME_LENGTH, max: CONSTANTS.MAX_SHORTNAME_LENGTH }),
query(['assigner']).optional().isString().trim().escape().notEmpty(),
query(['cna_modified']).optional().isBoolean({ loose: true }).withMessage(errorMsgs.CNA_MODIFIED),
parseError,
parseGetParams,
controller.CVE_GET_FILTERED)
Expand Down
3 changes: 2 additions & 1 deletion src/middleware/errorMessages.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ module.exports = {
ID_MODIFY_STATES: 'Invalid CVE ID state. Valid states are: RESERVED, REJECTED',
CVE_FILTERED_STATES: 'Invalid record state. Valid states are: PUBLISHED, REJECTED',
COUNT_ONLY: 'Invalid count_only value. Value should be 1, true, or yes to indicate true, or 0, false, or no to indicate false',
TIMESTAMP_FORMAT: "Bad date, or invalid timestamp format: valid format is yyyy-MM-ddTHH:mm:ss or yyyy-MM-ddTHH:mm:ssZZZZ (to use '+' in timezone offset, encode as '%2B)"
TIMESTAMP_FORMAT: "Bad date, or invalid timestamp format: valid format is yyyy-MM-ddTHH:mm:ss or yyyy-MM-ddTHH:mm:ssZZZZ (to use '+' in timezone offset, encode as '%2B)",
CNA_MODIFIED: 'Invalid cna_modified value. Value should be 1, true, or yes to indicate true, or 0, false, or no to indicate false'
}
56 changes: 55 additions & 1 deletion test/integration-tests/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,60 @@ const testCve = {
}
]
}
}

const testCveEdited = {
cnaContainer: {
affected: [
{
vendor: 'n/a',
product: 'n/a',
versions: [
{
version: 'n/a',
status: 'unknown'
}
]
}
],
descriptions: [
{
lang: 'en',
value: 'Cross-site scripting 2 (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'
}
]
}
],
providerMetadata: {
orgId: '9cbfeea8-dea2-4923-b772-1ab41730e742'
},
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'
}
]
}

}

Expand Down Expand Up @@ -188,5 +242,5 @@ const testAdp2 = {
}

module.exports = {
headers, nonSecretariatUserHeaders, badNonSecretariatUserHeaders, nonSecretariatUserHeadersWithAdp2, testCve, testAdp, testAdp2
headers, nonSecretariatUserHeaders, badNonSecretariatUserHeaders, nonSecretariatUserHeadersWithAdp2, testCve, testCveEdited, testAdp, testAdp2
}
85 changes: 85 additions & 0 deletions test/integration-tests/cve/getCveCnaModifiedTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* eslint-disable no-unused-expressions */

const chai = require('chai')
chai.use(require('chai-http'))
const expect = chai.expect

const constants = require('../constants.js')
const app = require('../../../src/index.js')
const helpers = require('../helpers.js')
const _ = require('lodash')

const shortName = 'win_5'

describe('Test cna_modified parameter for get CVE', () => {
let cveId
before(async () => {
cveId = await helpers.cveIdReserveHelper(1, '2023', shortName, 'non-sequential')
await helpers.cveRequestAsCnaHelper(cveId)
})
context('Positive Test', () => {
it('CVE should be returned with cna_modified true as it has been created', async () => {
await chai.request(app)
.get('/api/cve/?cna_modified=true')
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.true
})
})
it('Get CVE with cna_modified set to true should be returned after being edited', async () => {
// Edit the CNA container
await helpers.cveUpdatetAsCnaHelperWithCnaContainer(cveId, constants.testCveEdited)
await chai.request(app)
.get('/api/cve/?cna_modified=true')
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.true
})
})
it('Get CVE with cna_modified set to true AND date.gt should return when searched with a known earlier than date', async () => {
await chai.request(app)
.get('/api/cve/?time_modified.gt=2022-01-01T00:00:00&cna_modified=true')
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.true
})
})
it('Get CVE with cna_modified set to true AND date.gt should return and empty list when searched with a known bad earlier than date', async () => {
await chai.request(app)
.get('/api/cve/?time_modified.gt=2100-01-01T00:00:00&cna_modified=true')
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.false
})
})

it('Get CVE with cna_modified set to true AND date.lt should return when searched with a known later than date', async () => {
await chai.request(app)
.get('/api/cve/?time_modified.lt=2100-01-01T00:00:00&cna_modified=true')
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.true
})
})
it('Get CVE with cna_modified set to true AND date.lt should return and empty list when searched with a known bad later than date', async () => {
await chai.request(app)
.get('/api/cve/?time_modified.lt=2022-01-01T00:00:00&cna_modified=true')
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.false
})
})
})
})
24 changes: 23 additions & 1 deletion test/integration-tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,26 @@ async function cveRequestAsCnaHelper (cveId) {
})
}

module.exports = { cveIdReserveHelper, cveRequestAsCnaHelper }
async function cveRequestAsCnaHelperWithCnaContainer (cveId, cnaContainer) {
await chai.request(app)
.post(`/api/cve/${cveId}/cna`)
.set(constants.nonSecretariatUserHeaders)
.send(cnaContainer)
.then((res, err) => {
// Safety Expect
expect(res).to.have.status(200)
})
}

async function cveUpdatetAsCnaHelperWithCnaContainer (cveId, cnaContainer) {
await chai.request(app)
.put(`/api/cve/${cveId}/cna`)
.set(constants.nonSecretariatUserHeaders)
.send(cnaContainer)
.then((res, err) => {
// Safety Expect
expect(res).to.have.status(200)
})
}

module.exports = { cveIdReserveHelper, cveRequestAsCnaHelper, cveRequestAsCnaHelperWithCnaContainer, cveUpdatetAsCnaHelperWithCnaContainer }

0 comments on commit 596c0ce

Please sign in to comment.