From 88209f3a821dd01c1f48e4b7422be60df6a7c6ef Mon Sep 17 00:00:00 2001 From: Gautier DI FOLCO Date: Thu, 2 Jul 2026 23:17:19 +0200 Subject: [PATCH 1/5] saml2-web-sso: stop failing signature verification on stdout/stderr noise verifyIO wrapped signature verification in hCapture [stdout, stderr] and threw BadSamlResponseInvalidSignature ("noise on stdout/stderr from hsaml2 package") whenever any output appeared during the window. The capture is process-global, so spar's own concurrent Debug logging in the same SSO request (SCIM user creation, IdP validation, verdict handling) was swept in, causing flaky false signature failures -- e.g. testSparExpiredIdpCertStillWorks. Drop the capture' wrapper and the now-unused 'silently' dependency so verifyIO relies solely on the Either SignatureError result. The signer already self-verifies its own signature (DSig.hs signRootAt), so this does not weaken actual signature checking. --- libs/saml2-web-sso/default.nix | 3 --- libs/saml2-web-sso/saml2-web-sso.cabal | 2 -- libs/saml2-web-sso/src/Text/XML/DSig.hs | 19 +++++-------------- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/libs/saml2-web-sso/default.nix b/libs/saml2-web-sso/default.nix index c2cf3618c3..80d9ef7b90 100644 --- a/libs/saml2-web-sso/default.nix +++ b/libs/saml2-web-sso/default.nix @@ -57,7 +57,6 @@ , servant-multipart , servant-server , shelly -, silently , string-conversions , temporary , text @@ -137,7 +136,6 @@ mkDerivation { servant-multipart servant-server shelly - silently string-conversions temporary text @@ -211,7 +209,6 @@ mkDerivation { servant-multipart servant-server shelly - silently string-conversions temporary text diff --git a/libs/saml2-web-sso/saml2-web-sso.cabal b/libs/saml2-web-sso/saml2-web-sso.cabal index 5959492d60..69f5b72fc7 100644 --- a/libs/saml2-web-sso/saml2-web-sso.cabal +++ b/libs/saml2-web-sso/saml2-web-sso.cabal @@ -131,7 +131,6 @@ library , servant-multipart >=0.12 , servant-server >=0.16.2 , shelly >=1.8.1 - , silently >=1.2.5.1 , string-conversions >=0.4.0.1 , temporary >=1.3 , text >=1.2.3.1 @@ -259,7 +258,6 @@ test-suite saml2-web-sso-tests , servant-multipart >=0.12 , servant-server >=0.16.2 , shelly >=1.8.1 - , silently >=1.2.5.1 , string-conversions >=0.4.0.1 , temporary >=1.3 , text >=1.2.3.1 diff --git a/libs/saml2-web-sso/src/Text/XML/DSig.hs b/libs/saml2-web-sso/src/Text/XML/DSig.hs index 73af3106c3..cbee8d1164 100644 --- a/libs/saml2-web-sso/src/Text/XML/DSig.hs +++ b/libs/saml2-web-sso/src/Text/XML/DSig.hs @@ -77,8 +77,6 @@ import Network.Wai.Utilities.Exception import SAML2.XML qualified as HS hiding (Node, URI) import SAML2.XML.Canonical qualified as HS import SAML2.XML.Signature qualified as HS -import System.IO (stderr, stdout) -import System.IO.Silently (hCapture) import System.IO.Unsafe (unsafePerformIO) import System.Random (mkStdGen, random) import Text.XML as XML @@ -236,11 +234,10 @@ mkSignCredsWithCertWithLifespan validSinceRaw validUntilRaw size = do -- -- NB: The call to 'unsafePerformIO' in this function is sound under the assumption that -- 'verifyIO' has no effects in 'IO' other than throwing 'SomeException' (which are captured --- by 'try'. Technically, it does have other effects, like opening temp files for capturing --- stderr (if any), but we do not care about those. The only thing we care about is that the --- conceptually pure function of validating a signature will either be called twice with the --- same arguments and return the same result value, or not be called a second time with the --- same arguments, in which case that same value will be used. +-- by 'try'). The only thing we care about is that the conceptually pure function of +-- validating a signature will either be called twice with the same arguments and return the +-- same result value, or not be called a second time with the same arguments, in which case +-- that same value will be used. {-# NOINLINE verify #-} verify :: forall m. (MonadError String m) => NonEmpty SignCreds -> LBS -> String -> m HXTC.XmlTree verify creds el sid = case unsafePerformIO (try @SomeException $ verifyIO creds el sid) of @@ -266,17 +263,11 @@ verifyRoot creds el = do -- | Try a list of creds against a document. If all fail, return a list of errors for each cert; if -- *any* succeed, return the empty list. verifyIO :: NonEmpty SignCreds -> LBS -> String -> IO (SignCreds, Either HS.SignatureError HXTC.XmlTree) -verifyIO creds el sid = capture' $ do +verifyIO creds el sid = do results <- NL.zip creds <$> forM creds (\cred -> verifyIO' cred el sid) case NL.filter (isRight . snd) results of [result] -> pure result _ -> throwIO . ErrorCall $ "all credentials failed to verify signature" - where - capture' :: IO a -> IO a - capture' action = - hCapture [stdout, stderr] action >>= \case - ("", out) -> pure out - (noise, _) -> throwIO . ErrorCall $ "noise on stdout/stderr from hsaml2 package: " <> noise verifyIO' :: SignCreds -> LBS -> String -> IO (Either HS.SignatureError HXTC.XmlTree) verifyIO' (SignCreds SignDigestSha256 (SignKeyRSA key)) el sid = runExceptT $ do From d8c39e337415a68aeab8512697879ef09df6e97a Mon Sep 17 00:00:00 2001 From: Gautier DI FOLCO Date: Fri, 3 Jul 2026 00:38:22 +0200 Subject: [PATCH 2/5] Hello CI From 9d28dc51825e5418600f17f3df77901794607921 Mon Sep 17 00:00:00 2001 From: Gautier DI FOLCO Date: Fri, 3 Jul 2026 08:00:43 +0200 Subject: [PATCH 3/5] Hello CI From 15729fa85b12c55d1aa45b96c3083e91b93973cc Mon Sep 17 00:00:00 2001 From: Gautier DI FOLCO Date: Fri, 3 Jul 2026 09:02:21 +0200 Subject: [PATCH 4/5] Hello CI From e6bfa584ccefddcf4046480cccbaafb7159528be Mon Sep 17 00:00:00 2001 From: Gautier DI FOLCO Date: Fri, 3 Jul 2026 10:09:13 +0200 Subject: [PATCH 5/5] Hello CI