We got an SDH where it was possible to create new issues in ServiceNow with the state as closed due to race conditions. Taking a look at the following code
const { correlationId, incidentId } = params;
let incidentToBeClosed = null;
if (correlationId == null && incidentId == null) {
throw new Error('No correlationId or incidentId found.');
}
if (incidentId) {
incidentToBeClosed = await getIncident(incidentId);
} else if (correlationId) {
incidentToBeClosed = await getIncidentByCorrelationId(correlationId);
}
if (incidentToBeClosed === null) {
logger.warn(
`[ServiceNow][CloseIncident] No incident found with correlation_id: ${correlationId} or incidentId: ${incidentId}.`
);
return null;
}
if (incidentToBeClosed.state === '7') {
logger.warn(
`[ServiceNow][CloseIncident] Incident with correlation_id: ${correlationId} or incidentId: ${incidentId} is closed.`
);
return {
title: incidentToBeClosed.number,
id: incidentToBeClosed.sys_id,
pushedDate: getPushedDate(incidentToBeClosed.sys_updated_on),
url: getIncidentViewURL(incidentToBeClosed.sys_id),
};
}
const closedIncident = await updateIncident({
incidentId: incidentToBeClosed.sys_id,
incident: {
state: '7', // used for "closed" status in serviceNow
close_code: 'Closed/Resolved by Caller',
close_notes: 'Closed by Caller',
},
});
return closedIncident;
we can see that for this to happen the incidentToBeClosed === null checks need to be bypassed so the await updateIncident({...}) can be called. This is possible only if getIncident or getIncidentByCorrelationId returns {}. This is possible if the user does not have permission on all records of the incident table (ServiceNow will return an empty object in this case). A possible fix would be to do the check as incidentToBeClosed == null || isEmpty(incidentToBeClosed) || isEmpty(incidentToBeClosed.sys_id).
We got an SDH where it was possible to create new issues in ServiceNow with the state as closed due to race conditions. Taking a look at the following code
we can see that for this to happen the
incidentToBeClosed === null
checks need to be bypassed so theawait updateIncident({...})
can be called. This is possible only ifgetIncident
orgetIncidentByCorrelationId
returns{}
. This is possible if the user does not have permission on all records of the incident table (ServiceNow will return an empty object in this case). A possible fix would be to do the check asincidentToBeClosed == null || isEmpty(incidentToBeClosed) || isEmpty(incidentToBeClosed.sys_id)
.