packages feed

hsec-core (empty) → 0.1.0.0

raw patch · 5 files changed

+281/−0 lines, 5 filesdep +Cabal-syntaxdep +basedep +cvss

Dependencies added: Cabal-syntax, base, cvss, hsec-core, osv, pandoc-types, safe, tasty, tasty-hunit, text, time

Files

+ CHANGELOG.md view
+ hsec-core.cabal view
@@ -0,0 +1,67 @@+cabal-version:      2.4+name:               hsec-core+version:            0.1.0.0++-- A short (one-line) description of the package.+synopsis:           Core package representing Haskell advisories++-- A longer description of the package.+description:        Core package representing Haskell advisories.++-- A URL where users can report bugs.+-- bug-reports:++-- The license under which the package is released.+license:            BSD-3-Clause+author:             Haskell Security Response Team+maintainer:         security-advisories@haskell.org++-- A copyright notice.+-- copyright:+category:           Data+extra-doc-files:    CHANGELOG.md++tested-with:+  GHC ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.8 || ==9.6.3 || ==9.8.1++library+  exposed-modules:+    Security.Advisories.Core.Advisory+    Security.Advisories.Core.HsecId++  build-depends:+    , base          >=4.14    && <4.20+    , Cabal-syntax  >=3.8.1.0 && <3.11+    , cvss >= 0.1 && < 0.2+    , osv >= 0.1 && < 0.2+    , pandoc-types  >=1.22    && <2+    , safe          >=0.3+    , text          >=1.2     && <3+    , time          >=1.9     && <1.14++  -- , commonmark            ^>=0.2.2+  -- , commonmark-pandoc     >=0.2     && <0.3+  -- , containers            >=0.6     && <0.7+  -- , mtl                   >=2.2     && <2.4+  hs-source-dirs:   src+  default-language: Haskell2010+  ghc-options:+    -Wall -Wcompat -Widentities -Wincomplete-record-updates+    -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints++test-suite spec+  type:             exitcode-stdio-1.0+  hs-source-dirs:   test+  main-is:          Spec.hs+  build-depends:+    , base         <5+    , cvss+    , hsec-core+    , tasty        <1.5+    , tasty-hunit  <0.11+    , text++  default-language: Haskell2010+  ghc-options:+    -Wall -Wcompat -Widentities -Wincomplete-record-updates+    -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints
+ src/Security/Advisories/Core/Advisory.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE DerivingVia #-}++module Security.Advisories.Core.Advisory+  ( Advisory(..)+    -- * Supporting types+  , Affected(..)+  , CAPEC(..)+  , CWE(..)+  , Architecture(..)+  , AffectedVersionRange(..)+  , OS(..)+  , Keyword(..)+  )+  where++import Data.Text (Text)+import Data.Time (ZonedTime)+import Distribution.Types.Version (Version)+import Distribution.Types.VersionRange (VersionRange)++import Text.Pandoc.Definition (Pandoc)++import Security.Advisories.Core.HsecId+import qualified Security.CVSS as CVSS+import Security.OSV (Reference)++data Advisory = Advisory+  { advisoryId :: HsecId+  , advisoryModified :: ZonedTime+  , advisoryPublished :: ZonedTime+  , advisoryCAPECs :: [CAPEC]+  , advisoryCWEs :: [CWE]+  , advisoryKeywords :: [Keyword]+  , advisoryAliases :: [Text]+  , advisoryRelated :: [Text]+  , advisoryAffected :: [Affected]+  , advisoryReferences :: [Reference]+  , advisoryPandoc :: Pandoc  -- ^ Parsed document, without TOML front matter+  , advisoryHtml :: Text+  , advisorySummary :: Text+    -- ^ A one-line, English textual summary of the vulnerability+  , advisoryDetails :: Text+    -- ^ Details of the vulnerability (CommonMark), without TOML front matter+  }+  deriving stock (Show)++-- | An affected package (or package component).  An 'Advisory' must+-- mention one or more packages.+data Affected = Affected+  { affectedPackage :: Text+  , affectedCVSS :: CVSS.CVSS+  , affectedVersions :: [AffectedVersionRange]+  , affectedArchitectures :: Maybe [Architecture]+  , affectedOS :: Maybe [OS]+  , affectedDeclarations :: [(Text, VersionRange)]+  }+  deriving stock (Show)++newtype CAPEC = CAPEC {unCAPEC :: Integer}+  deriving stock (Show)++newtype CWE = CWE {unCWE :: Integer}+  deriving stock (Show)++data Architecture+  = AArch64+  | Alpha+  | Arm+  | HPPA+  | HPPA1_1+  | I386+  | IA64+  | M68K+  | MIPS+  | MIPSEB+  | MIPSEL+  | NIOS2+  | PowerPC+  | PowerPC64+  | PowerPC64LE+  | RISCV32+  | RISCV64+  | RS6000+  | S390+  | S390X+  | SH4+  | SPARC+  | SPARC64+  | VAX+  | X86_64+  deriving stock (Show)++data OS+  = Windows+  | MacOS+  | Linux+  | FreeBSD+  | Android+  | NetBSD+  | OpenBSD+  deriving stock (Show)++newtype Keyword = Keyword Text+  deriving stock (Eq, Ord)+  deriving (Show) via Text++data AffectedVersionRange = AffectedVersionRange+  { affectedVersionRangeIntroduced :: Version,+    affectedVersionRangeFixed :: Maybe Version+  }+  deriving stock (Show)
+ src/Security/Advisories/Core/HsecId.hs view
@@ -0,0 +1,93 @@+module Security.Advisories.Core.HsecId+  (+    HsecId+  , hsecIdYear+  , hsecIdSerial+  , mkHsecId+  , placeholder+  , isPlaceholder+  , parseHsecId+  , printHsecId+  , nextHsecId+  , getNextHsecId+  ) where++import Control.Monad (guard, join)++import Data.Time (getCurrentTime, utctDay)+import Data.Time.Calendar.OrdinalDate (toOrdinalDate)++import Safe (readMay)++data HsecId = HsecId Integer Integer+  deriving (Eq, Ord)++instance Show HsecId where+  show = printHsecId++-- | Make an 'HsecId'.  Year and serial must both be positive, or+-- else both must be zero (the 'placeholder').+mkHsecId+  :: Integer -- ^ Year+  -> Integer -- ^ Serial number within year+  -> Maybe HsecId+mkHsecId y n+  | y > 0 && n > 0 || y == 0 && n == 0 = Just $ HsecId y n+  | otherwise = Nothing++hsecIdYear :: HsecId -> Integer+hsecIdYear (HsecId y _) = y++hsecIdSerial :: HsecId -> Integer+hsecIdSerial (HsecId _ n) = n++-- | The placeholder ID: __HSEC-0000-0000__.+-- See also 'isPlaceholder'.+placeholder :: HsecId+placeholder = HsecId 0 0++-- | Test whether an ID is the 'placeholder'+isPlaceholder :: HsecId -> Bool+isPlaceholder = (==) placeholder++-- | Parse an 'HsecId'.  The 'placeholder' is accepted.+parseHsecId :: String -> Maybe HsecId+parseHsecId s = case s of+  'H':'S':'E':'C':'-':t ->+    let+      (y, t') = break (== '-') t+      n = drop 1 t'+    in do+      guard $ length y >= 4  -- year must have at least 4 digits+      guard $ length n >= 4  -- serial must have at least 4 digits+      join $ mkHsecId <$> readMay y <*> readMay n+  _ -> Nothing++printHsecId :: HsecId -> String+printHsecId (HsecId y n) = "HSEC-" <> pad (show y) <> "-" <> pad (show n)+  where+  pad s = replicate (4 - length s) '0' <> s++-- | Given a year and an HSEC ID, return a larger HSEC ID.  This+-- function, when given the current year and the greatest allocated+-- HSEC ID, returns the next HSEC ID to allocate.+--+nextHsecId+  :: Integer -- ^ Current year+  -> HsecId+  -> HsecId+nextHsecId curYear (HsecId idYear n)+  | curYear > idYear = HsecId curYear 1+  | otherwise = HsecId idYear (n + 1)++-- | Get the current time, and return an HSEC ID greater than the+-- given HSEC ID.  The year of the returned HSEC ID is the current+-- year.+--+getNextHsecId+  :: HsecId+  -> IO HsecId+getNextHsecId oldId = do+  t <- getCurrentTime+  let (year, _dayOfYear) = toOrdinalDate (utctDay t)+  pure $ nextHsecId year oldId
+ test/Spec.hs view
@@ -0,0 +1,10 @@+module Main where++import Test.Tasty++main :: IO ()+main =+  defaultMain $+    testGroup+      "Tests"+      []