diff --git a/.github/workflows/call-check-advisories.yml b/.github/workflows/call-check-advisories.yml index 03b9cb2e..c3d5e7c7 100644 --- a/.github/workflows/call-check-advisories.yml +++ b/.github/workflows/call-check-advisories.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-20.04 needs: populate_cache steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: source # We need to retrieve full history to determine the correct diff --git a/.github/workflows/call-nix.yml b/.github/workflows/call-nix.yml index 97608d42..e59d8f85 100644 --- a/.github/workflows/call-nix.yml +++ b/.github/workflows/call-nix.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Nix uses: DeterminateSystems/nix-installer-action@main with: @@ -29,12 +29,12 @@ jobs: code_hash=$(git rev-parse HEAD:code) echo "code-hash=$code_hash" >> "$GITHUB_OUTPUT" - uses: actions/cache/save@v3 - if: ${{ github.event_name == 'push' && github.ref_name == 'main' }} with: key: hsec-tools-${{ steps.code-hash.outputs.code-hash}} path: ~/.local/dockerImages - name: upload executable uses: actions/upload-artifact@v3 + if: ${{ github.event_name == 'push' && github.ref_name == 'main' }} with: name: hsec-tools-${{ github.sha }} path: ~/.local/dockerImages diff --git a/.github/workflows/check-advisories.yml b/.github/workflows/check-advisories.yml index 47adfe21..6e244390 100644 --- a/.github/workflows/check-advisories.yml +++ b/.github/workflows/check-advisories.yml @@ -9,7 +9,7 @@ jobs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - id: skip_check - uses: fkirc/skip-duplicate-actions@v5.3.0 + uses: fkirc/skip-duplicate-actions@v5.3.1 with: concurrent_skipping: "never" skip_after_successful_duplicate: "true" @@ -23,7 +23,7 @@ jobs: changed_files: ${{ steps.process-changed-files.outputs.out }} steps: - id: skip_check - uses: fkirc/skip-duplicate-actions@v5.3.0 + uses: fkirc/skip-duplicate-actions@v5.3.1 with: concurrent_skipping: "never" skip_after_successful_duplicate: "true" @@ -45,7 +45,7 @@ jobs: code_hash: ${{ steps.code-hash.outputs.code-hash }} steps: - name: git checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - id: code-hash run: | code_hash=$(git rev-parse HEAD:code) diff --git a/.github/workflows/haskell-ci.yml b/.github/workflows/haskell-ci.yml index 55caf438..2f43a344 100644 --- a/.github/workflows/haskell-ci.yml +++ b/.github/workflows/haskell-ci.yml @@ -24,7 +24,7 @@ jobs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - id: skip_check - uses: fkirc/skip-duplicate-actions@v5.3.0 + uses: fkirc/skip-duplicate-actions@v5.3.1 with: concurrent_skipping: "never" skip_after_successful_duplicate: "true" @@ -175,7 +175,7 @@ jobs: key: ${{ runner.os }}-${{ matrix.compiler }}-tools-d8b62173 path: ~/.haskell-ci-tools - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: source - name: initial cabal.project for sdist diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 4c051a19..ddf7eb3f 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -10,7 +10,7 @@ jobs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - id: skip_check - uses: fkirc/skip-duplicate-actions@v5.3.0 + uses: fkirc/skip-duplicate-actions@v5.3.1 with: concurrent_skipping: "never" skip_after_successful_duplicate: "true" @@ -56,10 +56,9 @@ jobs: cp generatedWebsite/by-dates.html generatedWebsite/index.html rm -Rf generatedWebsite/advisories || echo "Markdown links issue has been fixed" - name: Deploy - uses: s0/git-publish-subdir-action@develop - env: - REPO: self - BRANCH: generated/gh-pages - FOLDER: generatedWebsite - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SQUASH_HISTORY: true + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./generatedWebsite + publish_branch: generated/gh-pages + force_orphan: true diff --git a/advisories/hackage/bz2/HSEC-2024-0002.md b/advisories/hackage/bz2/HSEC-2024-0002.md new file mode 120000 index 00000000..cb2989c5 --- /dev/null +++ b/advisories/hackage/bz2/HSEC-2024-0002.md @@ -0,0 +1 @@ +../bzlib/HSEC-2024-0002.md \ No newline at end of file diff --git a/advisories/hackage/bzlib-conduit/HSEC-2024-0002.md b/advisories/hackage/bzlib-conduit/HSEC-2024-0002.md new file mode 120000 index 00000000..cb2989c5 --- /dev/null +++ b/advisories/hackage/bzlib-conduit/HSEC-2024-0002.md @@ -0,0 +1 @@ +../bzlib/HSEC-2024-0002.md \ No newline at end of file diff --git a/advisories/hackage/bzlib/HSEC-2024-0002.md b/advisories/hackage/bzlib/HSEC-2024-0002.md new file mode 100644 index 00000000..d9e49d1f --- /dev/null +++ b/advisories/hackage/bzlib/HSEC-2024-0002.md @@ -0,0 +1,61 @@ +```toml +[advisory] +id = "HSEC-2024-0002" +cwe = [787] +keywords = ["corruption", "vendored-code", "language-c"] +aliases = ["CVE-2019-12900"] + +[[references]] +type = "DISCUSSION" +url = "https://gnu.wildebeest.org/blog/mjw/2019/08/02/bzip2-and-the-cve-that-wasnt/" + +[[references]] +type = "DISCUSSION" +url = "http://scary.beasts.org/security/CESA-2008-005.html" + +[[references]] +type = "ADVISORY" +url = "https://access.redhat.com/security/cve/cve-2019-12900" + +[[references]] +type = "FIX" +url = "https://sourceware.org/git/?p=bzip2.git;a=commit;h=7ed62bfb46e87a9e878712603469440e6882b184" + +[[affected]] +package = "bzlib" +cvss = "CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N" + +[[affected.versions]] +introduced = "0.4" +fixed = "0.5.2.0" + +[[affected]] +package = "bz2" +cvss = "CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N" + +[[affected.versions]] +introduced = "0.1.0.0" +fixed = "1.0.1.1" + +[[affected]] +package = "bzlib-conduit" +cvss = "CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N" + +[[affected.versions]] +introduced = "0.1.0.0" +fixed = "0.3.0.3" +``` + +# out-of-bounds write when there are many bzip2 selectors + +A malicious bzip2 payload may produce a memory corruption +resulting in a denial of service and/or remote code execution. +Network services or command line utilities decompressing +untrusted bzip2 payloads are affected. + +Note that the exploitation of this bug relies on an undefined +behavior that appears to be handled safely by current compilers. + +The Haskell libraires are vulnerable when they are built using +the bundled C library source code, which is the default +in most cases. diff --git a/advisories/hackage/keter/HSEC-2024-0001.md b/advisories/hackage/keter/HSEC-2024-0001.md new file mode 100644 index 00000000..0b795b48 --- /dev/null +++ b/advisories/hackage/keter/HSEC-2024-0001.md @@ -0,0 +1,30 @@ +```toml +[advisory] +id = "HSEC-2024-0001" +cwe = [79] +keywords = ["http", "xss", "rxss", "historic"] + +[[references]] +type = "FIX" +url = "https://github.com/snoyberg/keter/pull/246" + +[[affected]] +package = "keter" +cvss = "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N" +declarations."Keter.Proxy.toResponse" = ">= 0.3.4 && < 1.0.1" +declarations."Keter.Proxy.unknownHostResponse" = ">= 1.0.1 && < 1.8.4" + +[[affected.versions]] +introduced = "0.3.4" +fixed = "1.8.4" +``` + +# Reflected XSS vulnerability in keter + +Keter is an app-server/reverse-proxy often used with webapps build on Yesod web-framework. + +In the logic handling VHost dispatch, Keter was echoing back `Host` header value, unescaped, +as part of an HTML error page. This constitutes a reflected-XSS vulnerability. Although +not readily exploitable directly from a browser (where `Host` header can't generally assume +arbitrary values), it may become such in presence of further weaknesses in components +upstream of Keter in the http proxying chain. Therefore, AC:High in CVSS evaluation. diff --git a/code/cvss/test/Spec.hs b/code/cvss/test/Spec.hs index dd17033e..5faccf73 100644 --- a/code/cvss/test/Spec.hs +++ b/code/cvss/test/Spec.hs @@ -27,6 +27,7 @@ examples = , ("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", 6.1, CVSS.Medium) , ("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N", 6.4, CVSS.Medium) , ("CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N", 3.1, CVSS.Low) + , ("CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N", 4.0, CVSS.Medium) , ("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H", 9.9, CVSS.Critical) , ("CVSS:3.0/AV:L/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:L", 4.2, CVSS.Medium) , ("CVSS:2.0/AV:N/AC:L/Au:N/C:N/I:N/A:C", 7.8, CVSS.High) diff --git a/code/hsec-tools/hsec-tools.cabal b/code/hsec-tools/hsec-tools.cabal index 00d3bc61..531d55c9 100644 --- a/code/hsec-tools/hsec-tools.cabal +++ b/code/hsec-tools/hsec-tools.cabal @@ -51,6 +51,7 @@ library , extra ^>=1.7.5 , filepath >=1.4 && <1.5 , hsec-core + , feed ==1.3.* , lucid >=2.9.0 , mtl >=2.2 && <2.4 , osv @@ -61,7 +62,7 @@ library , safe >=0.3 , text >=1.2 && <3 , time >=1.9 && <1.14 - , toml-parser ^>=1.3.0.0 + , toml-parser ^>=2.0.0.0 , validation-selective >=0.1 && <1 hs-source-dirs: src diff --git a/code/hsec-tools/src/Security/Advisories/Generate/HTML.hs b/code/hsec-tools/src/Security/Advisories/Generate/HTML.hs index 90bd988b..b5cbe9e4 100644 --- a/code/hsec-tools/src/Security/Advisories/Generate/HTML.hs +++ b/code/hsec-tools/src/Security/Advisories/Generate/HTML.hs @@ -11,21 +11,24 @@ import Control.Monad (forM_) import Data.List (sortOn) import Data.List.Extra (groupSort) import qualified Data.Map.Strict as Map +import Data.Maybe (listToMaybe) import Data.Ord (Down (..)) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as T -import System.Exit (exitFailure) -import System.IO (stderr, hPrint) - +import qualified Data.Text.Lazy as TL +import Data.Time (ZonedTime, zonedTimeToUTC) import Distribution.Pretty (prettyShow) import Lucid -import Validation (Validation(..)) - import qualified Security.Advisories as Advisories +import Security.Advisories.Filesystem (listAdvisories) import System.Directory (createDirectoryIfMissing) +import System.Exit (exitFailure) import System.FilePath (()) -import Security.Advisories.Filesystem (listAdvisories) +import System.IO (hPrint, stderr) +import qualified Text.Atom.Feed as Feed +import qualified Text.Atom.Feed.Export as FeedExport +import Validation (Validation (..)) -- * Actions @@ -41,33 +44,35 @@ renderAdvisoriesIndex src dst = do Success advisories -> return advisories - let renderToFile' path content = do + let renderHTMLToFile path content = do putStrLn $ "Rendering " <> path renderToFile path content createDirectoryIfMissing False dst let indexAdvisories = map toAdvisoryR advisories - renderToFile' (dst "by-dates.html") $ listByDates indexAdvisories - renderToFile' (dst "by-packages.html") $ listByPackages indexAdvisories + renderHTMLToFile (dst "by-dates.html") $ listByDates indexAdvisories + renderHTMLToFile (dst "by-packages.html") $ listByPackages indexAdvisories let advisoriesDir = dst "advisory" createDirectoryIfMissing False advisoriesDir forM_ advisories $ \advisory -> - renderToFile' (advisoriesDir advisoryHtmlFilename (Advisories.advisoryId advisory)) $ + renderHTMLToFile (advisoriesDir advisoryHtmlFilename (Advisories.advisoryId advisory)) $ inPage PageAdvisory $ div_ [class_ "pure-u-1"] $ toHtmlRaw (Advisories.advisoryHtml advisory) - writeFile (dst ".nojekyll") "" + putStrLn $ "Rendering " <> (dst "atom.xml") + writeFile (dst "atom.xml") $ T.unpack $ renderFeed indexAdvisories -- * Rendering types data AdvisoryR = AdvisoryR { advisoryId :: Advisories.HsecId, advisorySummary :: Text, - advisoryAffected :: [AffectedPackageR] + advisoryAffected :: [AffectedPackageR], + advisoryModified :: ZonedTime } - deriving stock (Eq, Show) + deriving stock (Show) data AffectedPackageR = AffectedPackageR { packageName :: Text, @@ -158,6 +163,7 @@ inPage page content = head_ $ do meta_ [charset_ "UTF-8"] base_ [href_ $ baseUrlForPage page] + link_ [rel_ "alternate", type_ "application/atom+xml", href_ atomFeedUrl] link_ [rel_ "stylesheet", href_ "https://cdn.jsdelivr.net/npm/purecss@3.0.0/build/pure-min.css", integrity_ "sha384-X38yfunGUhNzHpBaEBsWLO+A0HDYOQi8ufWDkZ0k9e0eXz/tH3II7uKZ9msv++Ls", crossorigin_ "anonymous"] meta_ [name_ "viewport", content_ "width=device-width, initial-scale=1"] title_ "Haskell Security.Advisories.Core" @@ -204,7 +210,8 @@ toAdvisoryR x = AdvisoryR { advisoryId = Advisories.advisoryId x, advisorySummary = Advisories.advisorySummary x, - advisoryAffected = concatMap toAffectedPackageR $ Advisories.advisoryAffected x + advisoryAffected = concatMap toAffectedPackageR $ Advisories.advisoryAffected x, + advisoryModified = Advisories.advisoryModified x } where toAffectedPackageR :: Advisories.Affected -> [AffectedPackageR] @@ -215,3 +222,34 @@ toAdvisoryR x = introduced = T.pack $ prettyShow $ Advisories.affectedVersionRangeIntroduced versionRange, fixed = T.pack . prettyShow <$> Advisories.affectedVersionRangeFixed versionRange } + +-- * Atom/RSS feed + +feed :: [AdvisoryR] -> Feed.Feed +feed advisories = + ( Feed.nullFeed + atomFeedUrl + (Feed.TextString "Haskell Security Advisory DB") -- Title + (maybe "" (T.pack . show) $ listToMaybe $ sortOn (Down . zonedTimeToUTC . advisoryModified) advisories) + ) + { Feed.feedEntries = fmap toEntry advisories, + Feed.feedLinks = [Feed.nullLink advisoriesRootUrl] + } + where + toEntry advisory = + Feed.nullEntry + (advisoriesRootUrl <> "/" <> advisoryLink (advisoryId advisory)) + (Feed.TextString $ advisorySummary advisory) + (T.pack $ show $ advisoryModified advisory) + +renderFeed :: [AdvisoryR] -> Text +renderFeed = + maybe (error "Cannot render atom feed") TL.toStrict + . FeedExport.textFeed + . feed + +advisoriesRootUrl :: T.Text +advisoriesRootUrl = "https://haskell.github.io/security-advisories" + +atomFeedUrl :: T.Text +atomFeedUrl = advisoriesRootUrl <> "/atom.xml" diff --git a/code/hsec-tools/src/Security/Advisories/Parse.hs b/code/hsec-tools/src/Security/Advisories/Parse.hs index fd5c5431..b0dacbbe 100644 --- a/code/hsec-tools/src/Security/Advisories/Parse.hs +++ b/code/hsec-tools/src/Security/Advisories/Parse.hs @@ -36,10 +36,8 @@ import qualified Commonmark.Parser as Commonmark import Commonmark.Types (HasAttributes(..), IsBlock(..), IsInline(..), Rangeable(..), SourceRange(..)) import Commonmark.Pandoc (Cm(unCm)) import qualified Toml -import qualified Toml.Pretty as Toml -import qualified Toml.FromValue as Toml -import qualified Toml.FromValue.Matcher as Toml -import qualified Toml.ToValue as Toml +import qualified Toml.Syntax as Toml (startPos) +import qualified Toml.Schema as Toml import Text.Pandoc.Builder (Blocks, Many(..)) import Text.Pandoc.Definition (Block(..), Inline(..), Pandoc(..)) import Text.Pandoc.Walk (query) @@ -47,9 +45,8 @@ import Text.Parsec.Pos (sourceLine) import Security.Advisories.Core.HsecId import Security.Advisories.Core.Advisory -import Security.OSV (Reference(..), referenceTypes) +import Security.OSV (Reference(..), ReferenceType, referenceTypes) import qualified Security.CVSS as CVSS - -- | A source of attributes supplied out of band from the advisory -- content. Values provided out of band are treated according to -- the 'AttributeOverridePolicy'. @@ -80,7 +77,7 @@ data ParseAdvisoryError = MarkdownError Commonmark.ParseError T.Text | MarkdownFormatError T.Text | TomlError String T.Text - | AdvisoryError [Toml.MatchMessage] T.Text + | AdvisoryError [Toml.MatchMessage Toml.Position] T.Text deriving stock (Eq, Show, Generic) -- | The main parsing function. 'OutOfBandAttributes' are handled @@ -99,7 +96,7 @@ parseAdvisory policy attrs raw = do (frontMatter, rest) <- first MarkdownFormatError $ advisoryDoc markdown let doc = Pandoc mempty rest !summary <- first MarkdownFormatError $ parseAdvisorySummary doc - table <- case Toml.parse (T.unpack frontMatter) of + table <- case Toml.parse frontMatter of Left e -> Left (TomlError e (T.pack e)) Right t -> Right t @@ -129,10 +126,8 @@ parseAdvisory policy attrs raw = do (Commonmark.commonmark "input" raw :: Either Commonmark.ParseError (Html ())) case parseAdvisoryTable attrs policy doc summary details html table of - Toml.Failure es -> Left (AdvisoryError es (T.pack (unlines (map Toml.prettyMatchMessage es)))) - Toml.Success warnings adv - | null warnings -> pure adv - | otherwise -> Left (AdvisoryError warnings (T.pack (unlines (map Toml.prettyMatchMessage warnings)))) -- treat warnings as errors + Left es -> Left (AdvisoryError es (T.pack (unlines (map Toml.prettyMatchMessage es)))) + Right adv -> pure adv where firstPretty @@ -156,11 +151,11 @@ parseAdvisoryTable -> T.Text -- ^ summary -> T.Text -- ^ details -> T.Text -- ^ rendered HTML - -> Toml.Table - -> Toml.Result Toml.MatchMessage Advisory + -> Toml.Table' Toml.Position + -> Either [Toml.MatchMessage Toml.Position] Advisory parseAdvisoryTable oob policy doc summary details html tab = - Toml.runMatcher $ - do fm <- Toml.fromValue (Toml.Table tab) + Toml.runMatcherFatalWarn $ + do fm <- Toml.fromValue (Toml.Table' Toml.startPos tab) published <- mergeOobMandatory policy (oobPublished oob) @@ -211,7 +206,7 @@ instance Toml.ToValue FrontMatter where toValue = Toml.defaultTableToValue instance Toml.ToTable FrontMatter where - toTable x = Map.fromList + toTable x = Toml.table [ "advisory" Toml..= frontMatterAdvisory x , "affected" Toml..= frontMatterAffected x , "references" Toml..= frontMatterReferences x @@ -253,7 +248,7 @@ instance Toml.ToValue AdvisoryMetadata where toValue = Toml.defaultTableToValue instance Toml.ToTable AdvisoryMetadata where - toTable x = Map.fromList $ + toTable x = Toml.table $ ["id" Toml..= amdId x] ++ ["modified" Toml..= y | Just y <- [amdModified x]] ++ ["date" Toml..= y | Just y <- [amdPublished x]] ++ @@ -283,7 +278,7 @@ instance Toml.ToValue Affected where toValue = Toml.defaultTableToValue instance Toml.ToTable Affected where - toTable x = Map.fromList $ + toTable x = Toml.table $ [ "package" Toml..= affectedPackage x , "cvss" Toml..= affectedCVSS x , "versions" Toml..= affectedVersions x @@ -307,7 +302,7 @@ instance Toml.ToValue AffectedVersionRange where toValue = Toml.defaultTableToValue instance Toml.ToTable AffectedVersionRange where - toTable x = Map.fromList $ + toTable x = Toml.table $ ("introduced" Toml..= affectedVersionRangeIntroduced x) : ["fixed" Toml..= y | Just y <- [affectedVersionRangeFixed x]] @@ -316,7 +311,7 @@ instance Toml.FromValue HsecId where fromValue v = do s <- Toml.fromValue v case parseHsecId s of - Nothing -> fail "invalid HSEC-ID: expected HSEC-[0-9]{4,}-[0-9]{4,}" + Nothing -> Toml.failAt (Toml.valueAnn v) "invalid HSEC-ID: expected HSEC-[0-9]{4,}-[0-9]{4,}" Just x -> pure x instance Toml.ToValue HsecId where @@ -335,11 +330,11 @@ instance Toml.ToValue Keyword where toValue (Keyword x) = Toml.toValue x -- | Get a datetime with the timezone defaulted to UTC and the time defaulted to midnight -getDefaultedZonedTime :: Toml.Value -> Toml.Matcher ZonedTime -getDefaultedZonedTime (Toml.ZonedTime x) = pure x -getDefaultedZonedTime (Toml.LocalTime x) = pure (ZonedTime x utc) -getDefaultedZonedTime (Toml.Day x) = pure (ZonedTime (LocalTime x midnight) utc) -getDefaultedZonedTime _ = fail "expected a date with optional time and timezone" +getDefaultedZonedTime :: Toml.Value' l -> Toml.Matcher l ZonedTime +getDefaultedZonedTime (Toml.ZonedTime' _ x) = pure x +getDefaultedZonedTime (Toml.LocalTime' _ x) = pure (ZonedTime x utc) +getDefaultedZonedTime (Toml.Day' _ x) = pure (ZonedTime (LocalTime x midnight) utc) +getDefaultedZonedTime v = Toml.failAt (Toml.valueAnn v) "expected a date with optional time and timezone" advisoryDoc :: Blocks -> Either T.Text (T.Text, [Block]) advisoryDoc (Many blocks) = case blocks of @@ -375,21 +370,22 @@ inlineText = query f instance Toml.FromValue Reference where fromValue = Toml.parseTableFromValue $ - do refTypeStr <- Toml.reqKey "type" - refType <- case lookup refTypeStr (fmap swap referenceTypes) of - Just a -> pure a - Nothing -> - fail $ - "Invalid format for reference.type: " ++ T.unpack refTypeStr ++ - " should be one of: " ++ intercalate ", " (T.unpack . snd <$> referenceTypes) - url <- Toml.reqKey "url" - pure $ Reference refType url + do refType <- Toml.reqKey "type" + url <- Toml.reqKey "url" + pure (Reference refType url) + +instance Toml.FromValue ReferenceType where + fromValue (Toml.Text' _ refTypeStr) + | Just a <- lookup refTypeStr (fmap swap referenceTypes) = pure a + fromValue v = + Toml.failAt (Toml.valueAnn v) $ + "reference.type should be one of: " ++ intercalate ", " (T.unpack . snd <$> referenceTypes) instance Toml.ToValue Reference where toValue = Toml.defaultTableToValue instance Toml.ToTable Reference where - toTable x = Map.fromList + toTable x = Toml.table [ "type" Toml..= fromMaybe "UNKNOWN" (lookup (referencesType x) referenceTypes) , "url" Toml..= referencesUrl x ] @@ -405,7 +401,7 @@ instance Toml.FromValue OS where "mingw32" -> pure Windows "netbsd" -> pure NetBSD "openbsd" -> pure OpenBSD - other -> fail ("Invalid OS: " ++ show other) + other -> Toml.failAt (Toml.valueAnn v) ("Invalid OS: " ++ show other) instance Toml.ToValue OS where toValue x = @@ -448,7 +444,7 @@ instance Toml.FromValue Architecture where "sparc64" -> pure SPARC64 "vax" -> pure VAX "x86_64" -> pure X86_64 - other -> fail ("Invalid architecture: " ++ show other) + other -> Toml.failAt (Toml.valueAnn v) ("Invalid architecture: " ++ show other) instance Toml.ToValue Architecture where toValue x = @@ -484,7 +480,7 @@ instance Toml.FromValue Version where fromValue v = do s <- Toml.fromValue v case eitherParsec s of - Left err -> fail ("parse error in version range: " ++ err) + Left err -> Toml.failAt (Toml.valueAnn v) ("parse error in version range: " ++ err) Right affected -> pure affected instance Toml.ToValue Version where @@ -494,7 +490,7 @@ instance Toml.FromValue VersionRange where fromValue v = do s <- Toml.fromValue v case eitherParsec s of - Left err -> fail ("parse error in version range: " ++ err) + Left err -> Toml.failAt (Toml.valueAnn v) ("parse error in version range: " ++ err) Right affected -> pure affected instance Toml.ToValue VersionRange where @@ -504,7 +500,7 @@ instance Toml.FromValue CVSS.CVSS where fromValue v = do s <- Toml.fromValue v case CVSS.parseCVSS s of - Left err -> fail ("parse error in cvss: " ++ show err) + Left err -> Toml.failAt (Toml.valueAnn v) ("parse error in cvss: " ++ show err) Right cvss -> pure cvss instance Toml.ToValue CVSS.CVSS where diff --git a/code/hsec-tools/test/golden/MISSING_AFFECTED.md.golden b/code/hsec-tools/test/golden/MISSING_AFFECTED.md.golden index 9d67c8f2..c08d6850 100644 --- a/code/hsec-tools/test/golden/MISSING_AFFECTED.md.golden +++ b/code/hsec-tools/test/golden/MISSING_AFFECTED.md.golden @@ -1,10 +1,17 @@ Left ( AdvisoryError [ MatchMessage - { matchPath = [] + { matchAnn = Just + ( Position + { posIndex = 0 + , posLine = 1 + , posColumn = 1 + } + ) + , matchPath = [] , matchMessage = "missing key: affected" } - ] "missing key: affected in top + ] "1:1: missing key: affected in " ) diff --git a/flake.lock b/flake.lock index d378e273..bd1ba001 100644 --- a/flake.lock +++ b/flake.lock @@ -181,7 +181,8 @@ "haskell-flake": "haskell-flake", "nixpkgs": "nixpkgs", "parts": "parts", - "pre-commit-hooks": "pre-commit-hooks" + "pre-commit-hooks": "pre-commit-hooks", + "toml-parser": "toml-parser" } }, "systems": { @@ -198,6 +199,19 @@ "repo": "default", "type": "github" } + }, + "toml-parser": { + "flake": false, + "locked": { + "lastModified": 1000000000, + "narHash": "sha256-ORXJIeAEb2fTAqLVhOurubDrz7Ddh7weZNEDkTkNP4k=", + "type": "tarball", + "url": "https://hackage.haskell.org/package/toml-parser-2.0.0.0/toml-parser-2.0.0.0.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://hackage.haskell.org/package/toml-parser-2.0.0.0/toml-parser-2.0.0.0.tar.gz" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 6fdb0edb..d6ba06f4 100644 --- a/flake.nix +++ b/flake.nix @@ -6,6 +6,9 @@ parts.url = "github:hercules-ci/flake-parts"; haskell-flake.url = "github:srid/haskell-flake"; pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; + + toml-parser.url = "https://hackage.haskell.org/package/toml-parser-2.0.0.0/toml-parser-2.0.0.0.tar.gz"; + toml-parser.flake = false; }; outputs = inputs: inputs.parts.lib.mkFlake { inherit inputs; } { @@ -34,6 +37,7 @@ haskellProjects.default = { packages = { Cabal-syntax.source = "3.10.2.0"; + toml-parser.source = inputs.toml-parser; }; settings = { }; projectRoot = ./code; diff --git a/meeting-notes/2024-02-07.md b/meeting-notes/2024-02-07.md new file mode 100644 index 00000000..55185031 --- /dev/null +++ b/meeting-notes/2024-02-07.md @@ -0,0 +1,22 @@ +# SRT meeting 2024-02-07 + +Previous meeting notes: +https://github.com/haskell/security-advisories/blob/main/meeting-notes/2024-01-24.md + +## Ongoing security issue (embargoed) + +- SRT agrees it matters, but it is out of our hands. +- All we can do is make recommendations. +- Mihai will lead response. + +## hackage-server + +- Gautier filed a PR adding link to security-advisories repo: + https://github.com/haskell/hackage-server/pull/1292 + +## Small CLI improvements + +- A community member worked on small fix in + [#147](https://github.com/haskell/security-advisories/pull/147) and + bootstrapped the cabal audit command in + [#148](https://github.com/haskell/security-advisories/pull/148). diff --git a/meeting-notes/2024-02-21.md b/meeting-notes/2024-02-21.md new file mode 100644 index 00000000..fcebdd90 --- /dev/null +++ b/meeting-notes/2024-02-21.md @@ -0,0 +1,17 @@ +# SRT meeting 2024-02-21 + +Previous meeting notes: +https://github.com/haskell/security-advisories/blob/main/meeting-notes/2024-02-07.md + +## Ongoing security issue (embargoed) + +- Mihai wits for Google approval to share the guidelines (hopefully today or tomorrow) + +## Small CLI improvements + +- [#148](https://github.com/haskell/security-advisories/pull/148) some progress have been made, but the PR is still in draft + +## ZuriHac workshop + +- Two days has been nearly filled +- Jose will coordinate HRT and Hackage team diff --git a/meeting-notes/2024-03-06.md b/meeting-notes/2024-03-06.md new file mode 100644 index 00000000..f164a36e --- /dev/null +++ b/meeting-notes/2024-03-06.md @@ -0,0 +1,33 @@ +# SRT meeting 2024-03-06 + +- Previous meeting: + https://github.com/haskell/security-advisories/blob/main/meeting-notes/2024-02-21.md + +## pre-ZuriHac ecosystem workshop + +- 6-7 June (before ZuriHac) +- https://haskell.foundation/events/2024-haskell-ecosystem-workshop.html +- Registration is open; fee can be waived for SRT members +- SRT members attending: + - Gautier confirmed, others looking into it. + - Jose wants all of us to attend, if we can. + Other SRT members want to come but need to work out if we can. + + +## Other updates (things that happened) + +- Update hsec-tools to toml-parser v2 +- Fixed web advisory index publishing. +- One historical advisory added (external contributor) +- Mihai has approval to publish the GHA documentation/guide. + He will send to SRT list first, then to researcher. + +## Outstanding PRs + +- CWE module + ([#116](https://github.com/haskell/security-advisories/pull/116)) + +## Other work to be done + +- Publishing our libraries on Hackage. +- What is the state of our package docs? Might need some work...