Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Resolves #1176 For GET /cve-id, redacts requested_by.user value for situations when cve-ids changes orgs, and when users change orgs #1179

Merged
merged 3 commits into from
Feb 8, 2024
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/controller/cve-id.controller/cve-id.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ async function getFilteredCveId (req, res, next) {
const users = await userRepo.getAllUsers()

const orgMap = {}
const userMap = {}

orgs.forEach(org => {
orgMap[org.UUID] = { shortname: org.short_name, users: {} }
})

users.forEach(user => {
userMap[user.UUID] = user.username
if (!orgMap[user.org_UUID]) {
orgMap[user.org_UUID] = { shortname: `MISSING ORG ${user.org_UUID}`, users: {} }
}
Expand Down Expand Up @@ -122,7 +125,31 @@ async function getFilteredCveId (req, res, next) {
cve_ids: pg.itemsList.map((i) => {
const cnaid = i.requested_by.cna
i.requested_by.cna = orgMap[cnaid].shortname
i.requested_by.user = orgMap[cnaid].users[i.requested_by.user]

// User value is redacted in certain cases
// Checks if requested_by.user is in requested_by.cna org
if (!orgMap[cnaid].users[i.requested_by.user]) {
// Never redact for secretariat users
if (isSecretariat) {
i.requested_by.user = userMap[i.requested_by.user]
} else {
// Redact because requested_by.user is not in requested_by.cna org
i.requested_by.user = 'REDACTED'
}
// Check is current owning_cna is also requested_by.cna (if a CVE-ID changes orgs)
} else if (cnaid !== i.owning_cna) {
// Never redact for secretariat
if (isSecretariat) {
i.requested_by.user = userMap[i.requested_by.user]
} else {
// Redact because current owner is not requested_by.cna and shouldn't see requested_by.user
i.requested_by.user = 'REDACTED'
}
} else {
// No redaction, original requested_by.user is in requested_by.cna and owning_cna
i.requested_by.user = orgMap[cnaid].users[i.requested_by.user]
}

i.owning_cna = orgMap[i.owning_cna].shortname
return i
})
Expand Down
14 changes: 14 additions & 0 deletions test/integration-tests/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ const nonSecretariatUserHeaders = {
'CVE-API-USER': 'jasminesmith@win_5.com'
}

const nonSecretariatUserHeaders2 = {
'CVE-API-ORG': 'win_5',
'CVE-API-Key': 'TCF25YM-39C4H6D-KA32EGF-V5XSHN3',
'CVE-API-USER': 'win_5_admin@win_5.com'
}

const nonSecretariatUserHeaders3 = {
'CVE-API-ORG': 'evidence_15',
'CVE-API-Key': 'TCF25YM-39C4H6D-KA32EGF-V5XSHN3',
'CVE-API-USER': 'timothymyers@evidence_15.com'
}

const nonSecretariatUserHeadersWithAdp2 = {
'CVE-API-ORG': 'range_4',
'CVE-API-Key': 'TCF25YM-39C4H6D-KA32EGF-V5XSHN3',
Expand Down Expand Up @@ -272,6 +284,8 @@ const existingOrg = {
module.exports = {
headers,
nonSecretariatUserHeaders,
nonSecretariatUserHeaders2,
nonSecretariatUserHeaders3,
badNonSecretariatUserHeaders,
nonSecretariatUserHeadersWithAdp2,
testCve,
Expand Down
79 changes: 79 additions & 0 deletions test/integration-tests/cve-id/getCveIdTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const _ = require('lodash')
const expect = chai.expect

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

describe('Testing Get CVE-ID endpoint', () => {
Expand Down Expand Up @@ -109,6 +110,84 @@ describe('Testing Get CVE-ID endpoint', () => {
expect(res).to.have.status(200)
})
})
it('For non Secretariat users, should redact requested_by.user values not in requested_by.cna org', async () => {
const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential')

// change users org for testing
await helpers.userOrgUpdateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'mitre')

await chai.request(app)
.get('/api/cve-id?state=RESERVED')
.set(constants.nonSecretariatUserHeaders2)
.then(async (res, err) => {
const cveIdObject = _.find(res.body.cve_ids, obj => {
return obj.cve_id === cveId
})
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(cveIdObject.requested_by.user).to.equal('REDACTED')

// Reset user to original org
await helpers.userOrgUpdateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], 'mitre', 'win_5')
})
})
it('For non Secretariat users, should redact requested_by.user values when requested_by.cna is not owning_cna', async () => {
const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential')

// change cve-id's owning_org for testing
await helpers.updateOwningOrgAsSecHelper(cveId, constants.nonSecretariatUserHeaders3['CVE-API-ORG'])

await chai.request(app)
.get('/api/cve-id?state=RESERVED')
.set(constants.nonSecretariatUserHeaders3)
.then(async (res, err) => {
const cveIdObject = _.find(res.body.cve_ids, obj => {
return obj.cve_id === cveId
})
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(cveIdObject.requested_by.user).to.equal('REDACTED')
})
})
it('For Secretariat users, should redact requested_by.user values not in requested_by.cna org', async () => {
const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential')

// change users org for testing
await helpers.userOrgUpdateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'mitre')

await chai.request(app)
.get('/api/cve-id?state=RESERVED')
.set(constants.headers)
.then(async (res, err) => {
const cveIdObject = _.find(res.body.cve_ids, obj => {
return obj.cve_id === cveId
})
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(cveIdObject.requested_by.user).to.equal(constants.nonSecretariatUserHeaders['CVE-API-USER'])

// Reset user to original org
await helpers.userOrgUpdateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], 'mitre', 'win_5')
})
})
it('For Secretariat users, should redact requested_by.user values when requested_by.cna is not owning_cna', async () => {
const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential')

// change cve-id's owning_org for testing
await helpers.updateOwningOrgAsSecHelper(cveId, constants.nonSecretariatUserHeaders3['CVE-API-ORG'])

await chai.request(app)
.get('/api/cve-id?state=RESERVED')
.set(constants.headers)
.then(async (res, err) => {
const cveIdObject = _.find(res.body.cve_ids, obj => {
return obj.cve_id === cveId
})
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(cveIdObject.requested_by.user).to.equal(constants.nonSecretariatUserHeaders['CVE-API-USER'])
})
})
})
context('negative tests', () => {
it('Feb 29 2100 should not be valid', async () => {
Expand Down
24 changes: 23 additions & 1 deletion test/integration-tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,26 @@ async function cveUpdateAsCnaHelperWithAdpContainer (cveId, adpContainer) {
})
}

async function userOrgUpdateAsSecHelper (userName, orgShortName, newOrgShortName) {
await chai.request(app)
.put(`/api/org/${orgShortName}/user/${userName}?org_short_name=${newOrgShortName}`)
.set(constants.headers)
.then((res, err) => {
// Safety Expect
expect(res).to.have.status(200)
})
}

async function updateOwningOrgAsSecHelper (cveId, newOrgShortName) {
await chai.request(app)
.put(`/api/cve-id/${cveId}?org=${newOrgShortName}`)
.set(constants.headers)
.then((res, err) => {
// Safety Expect
expect(res).to.have.status(200)
})
}

module.exports = {
cveIdReserveHelper,
cveIdBulkReserveHelper,
Expand All @@ -104,5 +124,7 @@ module.exports = {
cveRequestAsSecHelper,
cveUpdatetAsCnaHelperWithCnaContainer,
cveUpdateAsSecHelper,
cveUpdateAsCnaHelperWithAdpContainer
cveUpdateAsCnaHelperWithAdpContainer,
userOrgUpdateAsSecHelper,
updateOwningOrgAsSecHelper
}
Loading