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

Standardize all timestamps values to UTC #1308

Merged
merged 5 commits into from
Dec 20, 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
4 changes: 3 additions & 1 deletion src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ function getConstants () {
CVE_ID_PATTERN: cveSchemaV5.definitions.cveId.pattern,
// Ajv's pattern validation uses the "u" (unicode) flag:
// https://ajv.js.org/json-schema.html#pattern
CVE_ID_REGEX: new RegExp(cveSchemaV5.definitions.cveId.pattern, 'u')
CVE_ID_REGEX: new RegExp(cveSchemaV5.definitions.cveId.pattern, 'u'),
DATE_FIELDS: ['cveMetadata.datePublished', 'cveMetadata.dateUpdated', 'cveMetadata.dateReserved', 'providerMetadata.dateUpdated', 'datePublic', 'dateAssigned'
]
}

return defaults
Expand Down
16 changes: 9 additions & 7 deletions src/controller/cve.controller/cve.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const errors = require('./error')
const getConstants = require('../../constants').getConstants
const error = new errors.CveControllerError()
const booleanIsTrue = require('../../utils/utils').booleanIsTrue
const convertDatesToISO = require('../../utils/utils').convertDatesToISO
const isEnrichedContainer = require('../../utils/utils').isEnrichedContainer
const url = process.env.NODE_ENV === 'staging' ? 'https://test.cve.org/' : 'https://cve.org/'

Expand Down Expand Up @@ -332,7 +333,7 @@ async function submitCve (req, res, next) {
const CONSTANTS = getConstants()

try {
const newCve = new Cve({ cve: req.ctx.body })
const newCve = new Cve({ cve: convertDatesToISO(req.ctx.body, CONSTANTS.DATE_FIELDS) })
const id = req.ctx.params.id
const cveId = newCve.cve.cveMetadata.cveId
const state = newCve.cve.cveMetadata.state
Expand Down Expand Up @@ -392,7 +393,8 @@ async function updateCve (req, res, next) {
const CONSTANTS = getConstants()

try {
const newCve = new Cve({ cve: req.ctx.body })
// All CVE fields are stored in UTC format, we need to check and convert dates to ISO before storing in the database.
const newCve = new Cve({ cve: convertDatesToISO(req.ctx.body, CONSTANTS.DATE_FIELDS) })
const cveId = req.ctx.params.id
const cveRepo = req.ctx.repositories.getCveRepository()
const cveIdRepo = req.ctx.repositories.getCveIdRepository()
Expand Down Expand Up @@ -486,7 +488,7 @@ async function submitCna (req, res, next) {
return res.status(403).json(error.cveRecordExists())
}

const cnaContainer = req.ctx.body.cnaContainer
const cnaContainer = convertDatesToISO(req.ctx.body.cnaContainer, CONSTANTS.DATE_FIELDS)
if (erlCheck && !isEnrichedContainer(cnaContainer)) {
// Process the ERL check here
return res.status(403).json(error.erlCheckFailed())
Expand Down Expand Up @@ -582,7 +584,7 @@ async function updateCna (req, res, next) {
return res.status(403).json(error.cveRecordDne())
}

const cnaContainer = req.ctx.body.cnaContainer
const cnaContainer = convertDatesToISO(req.ctx.body.cnaContainer, CONSTANTS.DATE_FIELDS)
if (erlCheck && !isEnrichedContainer(cnaContainer)) {
// Process the ERL check here
return res.status(403).json(error.erlCheckFailed())
Expand Down Expand Up @@ -684,7 +686,7 @@ async function rejectCVE (req, res, next) {

const providerMetadata = createProviderMetadata(providerOrgObj.UUID, req.ctx.org, (new Date()).toISOString())
const rejectedCve = Cve.newRejectedCve(cveIdObj, req.ctx.body, owningCnaShortName, providerMetadata)
const newCveObj = new Cve({ cve: rejectedCve })
const newCveObj = new Cve({ cve: convertDatesToISO(rejectedCve, CONSTANTS.DATE_FIELDS) })

result = Cve.validateCveRecord(newCveObj.cve)
if (!result.isValid) {
Expand Down Expand Up @@ -757,7 +759,7 @@ async function rejectExistingCve (req, res, next) {

// update CVE record to rejected
const updatedRecord = Cve.updateCveToRejected(id, providerMetadata, result.cve, req.ctx.body)
const updatedCve = new Cve({ cve: updatedRecord })
const updatedCve = new Cve({ cve: convertDatesToISO(updatedRecord, CONSTANTS.DATE_FIELDS) })

result = Cve.validateCveRecord(updatedCve.cve)
if (!result.isValid) {
Expand Down Expand Up @@ -867,7 +869,7 @@ async function insertAdp (req, res, next) {
cveRecord.containers.adp.push(adpContainer)
}

const cveModel = new Cve({ cve: cveRecord })
const cveModel = new Cve({ cve: convertDatesToISO(cveRecord, CONSTANTS.DATE_FIELDS) })
result = Cve.validateCveRecord(cveModel.cve)
if (!result.isValid) {
logger.error(JSON.stringify({ uuid: req.ctx.uuid, message: 'CVE JSON schema validation FAILED.' }))
Expand Down
61 changes: 60 additions & 1 deletion src/utils/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Org = require('../model/org')
const User = require('../model/user')
const getConstants = require('../constants').getConstants
const _ = require('lodash')
const { DateTime } = require('luxon')

async function getOrgUUID (shortName) {
Expand Down Expand Up @@ -154,6 +155,62 @@ function toDate (val) {
return result
}

// Covert Dates to ISO format
function convertDatesToISO (obj, dateKeys) {
// Helper function to check if a value is a valid date
function isValidDate (value) {
return value instanceof Date && !isNaN(value)
}

// Helper function to check if a string is a valid date
function isStringDate (value) {
const date = new Date(value)
return !isNaN(date.getTime())
}

function updateDateValue (objectToUpdate, key, value) {
if (isValidDate(value)) {
_.set(objectToUpdate, key, value.toISOString())
} else if (typeof value === 'string' && isStringDate(value)) {
_.set(objectToUpdate, key, new Date(value).toISOString())
}
}

// For the top layer object
for (const key of dateKeys) {
if (_.has(obj, key)) {
const value = _.get(obj, key)
updateDateValue(obj, key, value)
}
}

// For the ADP(s)
if (_.has(obj, 'containers.adp')) {
// Use lodash for each to loop over array and check for date keys
_.each(obj.containers.adp, (adp) => {
for (const key of dateKeys) {
if (_.has(adp, key)) {
const value = _.get(adp, key)
updateDateValue(adp, key, value)
}
}
})
}
// For the CNAs

if (_.has(obj, 'containers.cna')) {
// Use lodash to check the containers.cna object for date keys
for (const key of dateKeys) {
if (_.has(obj.containers.cna, key)) {
const value = _.get(obj.containers.cna, key)
updateDateValue(obj.containers.cna, key, value)
}
}
}

return obj
}

function isEnrichedContainer (container) {
const hasCvss = container?.metrics?.some(item => 'cvssV4_0' in item || 'cvssV3_1' in item || 'cvssV3_0' in item || 'cvssV2_0' in item)
const hasCwe = container?.problemTypes?.some(pItem => pItem?.descriptions?.some(dItem => 'cweId' in dItem))
Expand All @@ -174,5 +231,7 @@ module.exports = {
getUserUUID,
reqCtxMapping,
booleanIsTrue,
toDate
toDate,
convertDatesToISO

}
Loading