{-# LANGUAGE OverloadedStrings #-} module NVDRules where import CVE (CPE (..), CPEMatch (..), CVE (..)) import Data.Char (isDigit) import qualified Data.Text as T import OurPrelude import Text.Regex.Applicative.Text (RE', anySym, many, psym, (=~)) import Utils (Boundary (..), ProductID, Version, VersionMatcher (..)) -- Return False to discard CVE filter :: CVE -> CPEMatch -> ProductID -> Version -> Bool filter _ cpeMatch "socat" v | cpeUpdatePresentAndNotPartOfVersion cpeMatch v = False -- TODO consider if this rule should be applied to all packages filter _ cpeMatch "uzbl" v | isNothing (v =~ yearRegex) && "2009.12.22" `anyVersionInfixOf` cpeMatchVersionMatcher cpeMatch = False | isNothing (v =~ yearRegex) && "2010.04.03" `anyVersionInfixOf` cpeMatchVersionMatcher cpeMatch = False filter _ cpeMatch "go" v | "." `T.isInfixOf` v && "-" `anyVersionInfixOf` cpeMatchVersionMatcher cpeMatch = False filter _ cpeMatch "terraform" _ | cpeTargetSoftware (cpeMatchCPE cpeMatch) == Just "aws" = False filter cve _ "tor" _ | cveID cve == "CVE-2017-16541" = False filter _ cpeMatch "arena" _ | cpeVendor (cpeMatchCPE cpeMatch) == Just "rockwellautomation" || cpeVendor (cpeMatchCPE cpeMatch) == Just "openforis" = False filter _ cpeMatch "thrift" _ | cpeVendor (cpeMatchCPE cpeMatch) == Just "facebook" = False filter _ cpeMatch "kanboard" _ | cpeTargetSoftware (cpeMatchCPE cpeMatch) == Just "jenkins" = False filter _cve _match _productID _version = True anyVersionInfixOf :: Text -> VersionMatcher -> Bool anyVersionInfixOf t (SingleMatcher v) = t `T.isInfixOf` v anyVersionInfixOf t (RangeMatcher (Including v1) (Including v2)) = t `T.isInfixOf` v1 || t `T.isInfixOf` v2 anyVersionInfixOf t (RangeMatcher (Excluding v1) (Excluding v2)) = t `T.isInfixOf` v1 || t `T.isInfixOf` v2 anyVersionInfixOf t (RangeMatcher (Including v1) (Excluding v2)) = t `T.isInfixOf` v1 || t `T.isInfixOf` v2 anyVersionInfixOf t (RangeMatcher (Excluding v1) (Including v2)) = t `T.isInfixOf` v1 || t `T.isInfixOf` v2 anyVersionInfixOf t (RangeMatcher Unbounded (Including v)) = t `T.isInfixOf` v anyVersionInfixOf t (RangeMatcher Unbounded (Excluding v)) = t `T.isInfixOf` v anyVersionInfixOf t (RangeMatcher (Including v) Unbounded) = t `T.isInfixOf` v anyVersionInfixOf t (RangeMatcher (Excluding v) Unbounded) = t `T.isInfixOf` v anyVersionInfixOf _ (RangeMatcher Unbounded Unbounded) = False -- Four digits at the start followed by any number of anything else yearRegex :: RE' () yearRegex = void $ psym isDigit <* psym isDigit <* psym isDigit <* psym isDigit <* many anySym cpeUpdatePresentAndNotPartOfVersion :: CPEMatch -> Version -> Bool cpeUpdatePresentAndNotPartOfVersion cpeMatch v = maybe False (\update -> not (update `T.isInfixOf` v)) (cpeUpdate (cpeMatchCPE cpeMatch))