@@ -14,6 +14,7 @@ module Security.Advisories.Parse
1414 )
1515 where
1616
17+ import qualified Security.CWE as CWE
1718import Data.Bifunctor (first )
1819import Data.Foldable (toList )
1920import Data.List (intercalate )
@@ -25,6 +26,7 @@ import GHC.Generics (Generic)
2526import qualified Data.Map as Map
2627import Data.Sequence (Seq ((:<|) ))
2728import qualified Data.Text as T
29+ import qualified Data.Text.Read as T
2830import qualified Data.Text.Lazy as T (toStrict )
2931import Data.Time (ZonedTime (.. ), LocalTime (LocalTime ), midnight , utc )
3032import Distribution.Parsec (eitherParsec )
@@ -223,7 +225,7 @@ data AdvisoryMetadata = AdvisoryMetadata
223225 { amdId :: HsecId
224226 , amdModified :: Maybe ZonedTime
225227 , amdPublished :: Maybe ZonedTime
226- , amdCWEs :: [CWE ]
228+ , amdCWEs :: [CWE. CWEID ]
227229 , amdKeywords :: [Keyword ]
228230 , amdAliases :: [T. Text ]
229231 , amdRelated :: [T. Text ]
@@ -322,11 +324,26 @@ instance Toml.FromValue HsecId where
322324instance Toml. ToValue HsecId where
323325 toValue = Toml. toValue . printHsecId
324326
325- instance Toml. FromValue CWE where
326- fromValue v = CWE <$> Toml. fromValue v
327-
328- instance Toml. ToValue CWE where
329- toValue (CWE x) = Toml. toValue x
327+ instance Toml. FromValue CWE. CWEID where
328+ fromValue v = case v of
329+ -- Check if the cwe number is known
330+ Toml. Integer int | Just cwe <- CWE. mkCWEID int, Map. member cwe CWE. cweNames -> pure cwe
331+ -- Check if the cwe text match "number: description"
332+ Toml. String string -> case T. breakOn " :" (T. pack string) of
333+ (numTxt, name) -> case T. decimal numTxt of
334+ Right (num, " " ) -> do
335+ -- Value is a "num: text", now validate if it's known
336+ cwe <- Toml. fromValue (Toml. Integer num)
337+ case T. strip (T. drop 1 name) of
338+ " " -> pure cwe
339+ expectedName -> case Map. lookup cwe CWE. cweNames of
340+ Just cweName | expectedName == cweName -> pure cwe
341+ _ -> fail (" unexpected description, got: " <> show cwe <> " , expected: " <> show expectedName)
342+ _ -> fail (" expected a number, got: " <> show numTxt)
343+ _ -> fail " expected a valid number or a cwe text description"
344+
345+ instance Toml. ToValue CWE. CWEID where
346+ toValue = Toml. toValue . CWE. unCWEID
330347
331348instance Toml. FromValue Keyword where
332349 fromValue v = Keyword <$> Toml. fromValue v
0 commit comments