import get from 'lodash.get' ; import { isJsonString , trimArray , shortenNodePath } from './common' ; import { color , getSeverityBgColor } from './color' ; import { printExceptionReport } from './print' ; import { analyzeExpiry } from './date' ; import { NpmAuditJson , v7VulnerabilityVia , ProcessedResult , ProcessedReport , v6Advisory , v7Vulnerability , NsprcConfigs , NsprcFile , AuditLevel , AuditNumber , } from 'src/types' ; const MAX_PATHS_SIZE = 5 ; param { String } auditLevel return { Number } export function mapLevelToNumber ( auditLevel ) { switch ( auditLevel ) { case 'info' : return 0 ; case 'low' : return 1 ; case 'moderate' : return 2 ; case 'high' : return 3 ; case 'critical' : return 4 ; default : return 0 ; } } param { String } jsonBuffer param { String } auditLevel param { Array } exceptionIds return { Object } export function processAuditJson ( jsonBuffer = '' , auditLevel = 'info' , exceptionIds = [ ] ) { if ( ! isJsonString ( jsonBuffer ) ) { return { unhandledIds : [ ] , vulnerabilityIds : [ ] , report : [ ] , failed : true , } ; } const { advisories , vulnerabilities } = JSON . parse ( jsonBuffer ) ; if ( advisories ) { return Object . values ( advisories ) . reduce ( ( acc , cur ) => { const shouldAudit = mapLevelToNumber ( cur . severity ) >= mapLevelToNumber ( auditLevel ) ; const isExcepted = exceptionIds . includes ( Number ( cur . id ) ) ; acc . report . push ( [ color ( cur . id , isExcepted ? '' : 'yellow' ) , color ( cur . module_name , isExcepted ? '' : 'yellow' ) , color ( cur . title , isExcepted ? '' : 'yellow' ) , color ( trimArray ( cur . findings . reduce ( ( a , c ) => [ ... a , ... c . paths ] as [ ] , [ ] ) , MAX_PATHS_SIZE ) . join ( '\n' ) , isExcepted ? '' : 'yellow' ) , color ( cur . severity , isExcepted ? '' : 'yellow' , getSeverityBgColor ( cur . severity ) ) , color ( cur . url , isExcepted ? '' : 'yellow' ) , isExcepted ? 'y' : color ( 'n' , 'yellow' ) , ] ) ; acc . vulnerabilityIds . push ( Number ( cur . id ) ) ; if ( shouldAudit && ! isExcepted ) { acc . unhandledIds . push ( Number ( cur . id ) ) ; } return acc ; } , { unhandledIds : [ ] , vulnerabilityIds : [ ] , report : [ ] , } ) ; } if ( vulnerabilities ) { return Object . values ( vulnerabilities ) . reduce ( ( acc , cur ) => { get ( cur , 'via' , [ ] ) . forEach ( ( vul ) => { const id = get ( vul , 'source' , '' ) ; if ( ! id || typeof id === 'string' || typeof vul === 'string' ) { return ; } const shouldAudit = mapLevelToNumber ( vul . severity ) >= mapLevelToNumber ( auditLevel ) ; const isExcepted = exceptionIds . includes ( id ) ; acc . report . push ( [ color ( String ( id ) , isExcepted ? '' : 'yellow' ) , color ( vul . name , isExcepted ? '' : 'yellow' ) , color ( vul . title , isExcepted ? '' : 'yellow' ) , color ( trimArray ( get ( cur , 'nodes' , [ ] ) . map ( shortenNodePath ) , MAX_PATHS_SIZE ) . join ( '\n' ) , isExcepted ? '' : 'yellow' ) , color ( vul . severity , isExcepted ? '' : 'yellow' , getSeverityBgColor ( vul . severity ) ) , color ( vul . url , isExcepted ? '' : 'yellow' ) , isExcepted ? 'y' : color ( 'n' , 'yellow' ) , ] ) ; acc . vulnerabilityIds . push ( id ) ; if ( shouldAudit && ! isExcepted ) { acc . unhandledIds . push ( id ) ; } } ) ; return acc ; } , { unhandledIds : [ ] , vulnerabilityIds : [ ] , report : [ ] , } ) ; } return { unhandledIds : [ ] , vulnerabilityIds : [ ] , report : [ ] , failed : true , } ; } param { Object | Boolean } nsprc param { Array } cmdExceptions return { Array } export function getExceptionsIds ( nsprc ? , cmdExceptions = [ ] ) { if ( ! nsprc || typeof nsprc !== 'object' ) { if ( cmdExceptions . length ) { console . info ( `Exception IDs: ${ cmdExceptions . join ( ', ' ) }` ) ; return cmdExceptions ; } return [ ] ; } const { exceptionIds , report } = processExceptions ( nsprc , cmdExceptions ) ; printExceptionReport ( report ) ; return exceptionIds ; } param { Object } nsprc param { Array } cmdExceptions return { Object } export function processExceptions ( nsprc , cmdExceptions = [ ] ) { return Object . entries ( nsprc ) . reduce ( ( acc , [ id , details ] ) => { const numberId = Number ( id ) ; const isValidId = ! isNaN ( numberId ) ; const isActive = Boolean ( get ( details , 'active' , true ) ) ; const notes = typeof details === 'string' ? details : get ( details , 'notes' , '' ) ; const { valid , expired , years } = analyzeExpiry ( get ( details , 'expiry' ) ) ; let status = color ( 'active' , 'green' ) ; if ( expired ) { status = color ( 'expired' , 'red' ) ; } else if ( ! isValidId || ! valid ) { status = color ( 'invalid' , 'red' ) ; } else if ( ! isActive ) { status = color ( 'inactive' , 'yellow' ) ; } let expiryDate = get ( details , 'expiry' ) ? new Date ( get ( details , 'expiry' ) ) . toUTCString ( ) : '' ; if ( years && years <= - 5 ) { expiryDate = color ( expiryDate , 'red' ) ; } else if ( years && years <= - 1 ) { expiryDate = color ( expiryDate , 'yellow' ) ; } acc . report . push ( [ id , status , expiryDate , notes ] ) ; if ( isValidId && isActive && ! expired ) { acc . exceptionIds . push ( numberId ) ; } return acc ; } , { exceptionIds : cmdExceptions , report : cmdExceptions . map ( ( id ) => [ String ( id ) , color ( 'active' , 'green' ) , '' , '' ] ) , } ) ; }