1+ const { PackageURL } = require ( 'packageurl-js' )
12const { body, validationResult } = require ( 'express-validator' )
23const errors = require ( './error' )
34const error = new errors . CveControllerError ( )
@@ -184,6 +185,69 @@ function validateCveAdpContainerJsonSchema (req, res, next) {
184185 next ( )
185186}
186187
188+ // PURL validator middleware
189+ function validatePURL ( pURLIndex ) {
190+ return body ( pURLIndex ) . optional ( { nullable : true } ) . bail ( ) . custom ( ( affected ) => {
191+ for ( const affObj of affected ) {
192+ const purlStr = affObj . packageURL
193+ let purlObj
194+ let parsedPurlArray
195+ // Passes first validation check if PackageURL can build a PURL from the string
196+ try {
197+ // PURL class from PackageURL
198+ purlObj = PackageURL . fromString ( purlStr )
199+ // PURL string broken up by component and store in array. Used for additional validation
200+ parsedPurlArray = PackageURL . parseString ( purlStr )
201+ console . log ( purlObj )
202+ console . log ( parsedPurlArray )
203+ // console.log(PackageURL.fromString(purlObj.toString()))
204+ } catch ( e ) {
205+ throw new Error ( e . message )
206+ }
207+
208+ // PURL's with versions are not allowed
209+ if ( purlObj . version !== undefined ) {
210+ throw new Error ( 'The PURL version component is currently not supported by the CVE schema' )
211+ }
212+
213+ // PackageURL does not properly account for certain Subpath situations
214+ // so adding additional validation to account for them
215+ if ( purlObj . subpath !== undefined ) {
216+ // Checks if any subpaths contain invalid characters
217+ // Subpaths cannot be '.' or '..'
218+ const parsedSubpaths = subpathHelper ( parsedPurlArray [ 5 ] )
219+
220+ console . log ( parsedSubpaths )
221+
222+ if ( parsedSubpaths . includes ( '..' ) || parsedSubpaths . includes ( '.' ) ) {
223+ throw new Error ( "Subpaths cannot be '.' or '..' " )
224+ }
225+
226+ if ( parsedSubpaths . includes ( '' ) ) {
227+ throw new Error ( "Subpaths cannot be empty or contain only a '/' " )
228+ }
229+ }
230+ }
231+ return true
232+ }
233+ )
234+ }
235+
236+ // Parses subpaths into array, stripping leading and trailing '/'
237+ function subpathHelper ( subpathStr ) {
238+ // remove leading and trailing '/'s
239+ if ( subpathStr [ 0 ] === '/' ) {
240+ subpathStr = subpathStr . slice ( 1 )
241+ }
242+
243+ if ( subpathStr [ subpathStr . length - 1 ] === '/' ) {
244+ subpathStr = subpathStr . slice ( 0 , subpathStr . length - 1 )
245+ }
246+
247+ const parsedSubpaths = subpathStr . split ( '/' )
248+ return parsedSubpaths
249+ }
250+
187251module . exports = {
188252 parseGetParams,
189253 parsePostParams,
@@ -195,5 +259,6 @@ module.exports = {
195259 validateDescription,
196260 validateRejectBody,
197261 validateDatePublic,
198- datePublicHelper
262+ datePublicHelper,
263+ validatePURL
199264}
0 commit comments