Skip to content

Commit 0c68096

Browse files
Update hsec-tool to use the new CWE data and validation
1 parent 43bd750 commit 0c68096

File tree

7 files changed

+37
-15
lines changed

7 files changed

+37
-15
lines changed

.github/workflows/haskell-ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ jobs:
183183
touch cabal.project
184184
echo "packages: $GITHUB_WORKSPACE/source/code/hsec-tools" >> cabal.project
185185
echo "packages: $GITHUB_WORKSPACE/source/code/cvss" >> cabal.project
186+
echo "packages: $GITHUB_WORKSPACE/source/code/cwe" >> cabal.project
186187
cat cabal.project
187188
- name: sdist
188189
run: |

cabal.project

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ packages: code/*/*.cabal
22

33
package hsec-tools
44
package cvss
5+
package cwe

code/cwe/src/Security/CWE.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{-# LANGUAGE DerivingStrategies #-}
33
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
44
{-# LANGUAGE OverloadedStrings #-}
5-
module Security.CWE (CWEID, mkCWEID, cweNames, cweIds) where
5+
module Security.CWE (CWEID, unCWEID, mkCWEID, cweNames, cweIds) where
66

77
import Security.CWE.Data
88
import Data.Text (Text)
@@ -14,6 +14,10 @@ import Data.Bits
1414
newtype CWEID = CWEID Word
1515
deriving newtype (Eq, Ord, Show)
1616

17+
-- | Access the underlying data.
18+
unCWEID :: CWEID -> Word
19+
unCWEID (CWEID cwe) = cwe
20+
1721
mkCWEID :: (Integral a, Bits a) => a -> Maybe CWEID
1822
mkCWEID num = CWEID <$> toIntegralSized num
1923

code/hsec-tools/hsec-tools.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ library
4949
, commonmark ^>=0.2.2
5050
, commonmark-pandoc >=0.2 && <0.3
5151
, containers >=0.6 && <0.7
52-
, cvss
52+
, cvss >=0.1 && <2
53+
, cwe >=0.1 && <2
5354
, directory <2
5455
, extra ^>=1.7.5
5556
, filepath >=1.4 && <1.5

code/hsec-tools/src/Security/Advisories/Definition.hs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ module Security.Advisories.Definition
44
( Advisory(..)
55
-- * Supporting types
66
, Affected(..)
7-
, CWE(..)
7+
, CWEID
88
, Architecture(..)
99
, AffectedVersionRange(..)
1010
, OS(..)
1111
, Keyword(..)
1212
)
1313
where
1414

15+
import Security.CWE (CWEID)
1516
import Data.Text (Text)
1617
import Data.Time (ZonedTime)
1718
import Distribution.Types.Version (Version)
@@ -27,7 +28,7 @@ data Advisory = Advisory
2728
{ advisoryId :: HsecId
2829
, advisoryModified :: ZonedTime
2930
, advisoryPublished :: ZonedTime
30-
, advisoryCWEs :: [CWE]
31+
, advisoryCWEs :: [CWEID]
3132
, advisoryKeywords :: [Keyword]
3233
, advisoryAliases :: [Text]
3334
, advisoryRelated :: [Text]
@@ -54,9 +55,6 @@ data Affected = Affected
5455
}
5556
deriving stock (Show)
5657

57-
newtype CWE = CWE {unCWE :: Integer}
58-
deriving stock (Show)
59-
6058
data Architecture
6159
= AArch64
6260
| Alpha

code/hsec-tools/src/Security/Advisories/Parse.hs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Security.Advisories.Parse
1414
)
1515
where
1616

17+
import qualified Security.CWE as CWE
1718
import Data.Bifunctor (first)
1819
import Data.Foldable (toList)
1920
import Data.List (intercalate)
@@ -25,6 +26,7 @@ import GHC.Generics (Generic)
2526
import qualified Data.Map as Map
2627
import Data.Sequence (Seq((:<|)))
2728
import qualified Data.Text as T
29+
import qualified Data.Text.Read as T
2830
import qualified Data.Text.Lazy as T (toStrict)
2931
import Data.Time (ZonedTime(..), LocalTime (LocalTime), midnight, utc)
3032
import 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
322324
instance 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

331348
instance Toml.FromValue Keyword where
332349
fromValue v = Keyword <$> Toml.fromValue v

flake.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
pkgs.haskell.lib.doJailbreak (pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.unmarkBroken pkg));
2121

2222
cvss = pkgs.haskellPackages.callCabal2nix "cvss" ./code/cvss {};
23+
cwe = pkgs.haskellPackages.callCabal2nix "cwe" ./code/cwe {};
2324

2425
hsec-tools = returnShellEnv:
2526
pkgs.haskellPackages.developPackage {
@@ -28,10 +29,9 @@
2829
root = ./code/hsec-tools;
2930
withHoogle = false;
3031
overrides = self: super: {
31-
inherit cvss;
32+
inherit cvss cwe;
3233
Cabal-syntax = super.Cabal-syntax_3_8_1_0;
3334
toml-parser = jailbreakUnbreak (super.callCabal2nix "toml-parser" toml-parser { });
34-
cwe = super.callCabal2nix "cwe" ./code/cwe {};
3535
};
3636

3737
modifier = drv:

0 commit comments

Comments
 (0)