@@ -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 )
@@ -218,7 +220,7 @@ data AdvisoryMetadata = AdvisoryMetadata
218220 { amdId :: HsecId
219221 , amdModified :: Maybe ZonedTime
220222 , amdPublished :: Maybe ZonedTime
221- , amdCWEs :: [CWE ]
223+ , amdCWEs :: [CWE. CWEID ]
222224 , amdKeywords :: [Keyword ]
223225 , amdAliases :: [T. Text ]
224226 , amdRelated :: [T. Text ]
@@ -317,11 +319,26 @@ instance Toml.FromValue HsecId where
317319instance Toml. ToValue HsecId where
318320 toValue = Toml. toValue . printHsecId
319321
320- instance Toml. FromValue CWE where
321- fromValue v = CWE <$> Toml. fromValue v
322-
323- instance Toml. ToValue CWE where
324- toValue (CWE x) = Toml. toValue x
322+ instance Toml. FromValue CWE. CWEID where
323+ fromValue v = case v of
324+ -- Check if the cwe number is known
325+ Toml. Integer int | Just cwe <- CWE. mkCWEID int, Map. member cwe CWE. cweNames -> pure cwe
326+ -- Check if the cwe text match "number: description"
327+ Toml. String string -> case T. breakOn " :" (T. pack string) of
328+ (numTxt, name) -> case T. decimal numTxt of
329+ Right (num, " " ) -> do
330+ -- Value is a "num: text", now validate if it's known
331+ cwe <- Toml. fromValue (Toml. Integer num)
332+ case T. strip (T. drop 1 name) of
333+ " " -> pure cwe
334+ expectedName -> case Map. lookup cwe CWE. cweNames of
335+ Just cweName | expectedName == cweName -> pure cwe
336+ _ -> fail (" unexpected description, got: " <> show cwe <> " , expected: " <> show expectedName)
337+ _ -> fail (" expected a number, got: " <> show numTxt)
338+ _ -> fail " expected a valid number or a cwe text description"
339+
340+ instance Toml. ToValue CWE. CWEID where
341+ toValue = Toml. toValue . CWE. unCWEID
325342
326343instance Toml. FromValue Keyword where
327344 fromValue v = Keyword <$> Toml. fromValue v
0 commit comments