yesod-csp 0.2.7.1 → 0.2.8.0
raw patch · 5 files changed
+52/−7 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Yesod.Csp: instance Data.Data.Data Codec.MIME.Type.MIMEParam
- Yesod.Csp: instance Data.Data.Data Codec.MIME.Type.MIMEType
- Yesod.Csp: instance Data.Data.Data Codec.MIME.Type.Multipart
- Yesod.Csp: instance Data.Data.Data Codec.MIME.Type.Type
- Yesod.Csp: instance Data.Data.Data Yesod.Csp.Directive
- Yesod.Csp: instance Data.Data.Data Yesod.Csp.EscapedText
- Yesod.Csp: instance Data.Data.Data Yesod.Csp.EscapedURI
- Yesod.Csp: instance Data.Data.Data Yesod.Csp.SandboxOptions
- Yesod.Csp: instance Data.Data.Data Yesod.Csp.Source
- Yesod.Csp: instance GHC.Show.Show Yesod.Csp.Directive
- Yesod.Csp: instance GHC.Show.Show Yesod.Csp.EscapedText
- Yesod.Csp: instance GHC.Show.Show Yesod.Csp.EscapedURI
- Yesod.Csp: instance GHC.Show.Show Yesod.Csp.SandboxOptions
- Yesod.Csp: instance GHC.Show.Show Yesod.Csp.Source
- Yesod.Csp.Example: instance GHC.Read.Read (Yesod.Routes.Class.Route Yesod.Csp.Example.Example)
- Yesod.Csp.Example: instance GHC.Show.Show (Yesod.Routes.Class.Route Yesod.Csp.Example.Example)
+ Yesod.Csp: ManifestSrc :: SourceList -> Directive
+ Yesod.Csp: PrefetchSrc :: SourceList -> Directive
+ Yesod.Csp: ReportTo :: Text -> Directive
+ Yesod.Csp: WorkerSrc :: SourceList -> Directive
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Codec.MIME.Type.MIMEParam
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Codec.MIME.Type.MIMEType
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Codec.MIME.Type.Multipart
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Codec.MIME.Type.Type
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Yesod.Csp.Directive
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Yesod.Csp.EscapedText
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Yesod.Csp.EscapedURI
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Yesod.Csp.SandboxOptions
+ Yesod.Csp: instance GHC.Internal.Data.Data.Data Yesod.Csp.Source
+ Yesod.Csp: instance GHC.Internal.Show.Show Yesod.Csp.Directive
+ Yesod.Csp: instance GHC.Internal.Show.Show Yesod.Csp.EscapedText
+ Yesod.Csp: instance GHC.Internal.Show.Show Yesod.Csp.EscapedURI
+ Yesod.Csp: instance GHC.Internal.Show.Show Yesod.Csp.SandboxOptions
+ Yesod.Csp: instance GHC.Internal.Show.Show Yesod.Csp.Source
+ Yesod.Csp.Example: instance GHC.Internal.Read.Read (Yesod.Routes.Class.Route Yesod.Csp.Example.Example)
+ Yesod.Csp.Example: instance GHC.Internal.Show.Show (Yesod.Routes.Class.Route Yesod.Csp.Example.Example)
+ Yesod.Csp.TH: reportTo :: Parser Directive
Files
- CHANGELOG.md +4/−0
- src/Yesod/Csp.hs +10/−0
- src/Yesod/Csp/TH.hs +17/−1
- test/Test.hs +20/−5
- yesod-csp.cabal +1/−1
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Changelog +## Version 0.2.8.0+++ Add support for CSP Level 3 directives: `report-to`, `worker-src`, `manifest-src` and `prefetch-src`+ ## Version 0.2.7.1 + Relax version boundaries on template-haskell to be able to build with ghc-9.10 on nixos-25.11
src/Yesod/Csp.hs view
@@ -171,6 +171,12 @@ | FormAction SourceList | BaseUri EscapedURI | PluginTypes MimeTypeList+ -- | CSP level 3 directives+ | WorkerSrc SourceList+ | ManifestSrc SourceList+ | PrefetchSrc SourceList+ -- | Names a reporting group defined by the @Reporting-Endpoints@ (or @Report-To@) response header.+ | ReportTo Text deriving (Eq, Show, Data, Typeable) @@ -202,3 +208,7 @@ textDirective (FormAction x) = w "form-action" x textDirective (BaseUri t) = mconcat ["base-uri ", (T.pack . show) t] textDirective (PluginTypes t) = mconcat ["plugin-types ", (T.unwords . fmap Mime.showType . toList) t]+textDirective (WorkerSrc x) = w "worker-src" x+textDirective (ManifestSrc x) = w "manifest-src" x+textDirective (PrefetchSrc x) = w "prefetch-src" x+textDirective (ReportTo t) = mconcat ["report-to ", t]
src/Yesod/Csp/TH.hs view
@@ -4,6 +4,7 @@ source , withSourceList , reportUri+ , reportTo , pluginTypes , sandbox , sandboxOptions@@ -110,6 +111,9 @@ <|> frameAncestors <|> childSrc <|> formAction+ <|> workerSrc+ <|> manifestSrc+ <|> prefetchSrc where defaultSrc = d "default-src" DefaultSrc scriptSrc = d "script-src" ScriptSrc styleSrc = d "style-src" StyleSrc@@ -122,6 +126,9 @@ frameAncestors = d "frame-ancestors" FrameAncestors childSrc = d "child-src" ChildSrc formAction = d "form-action" FormAction+ workerSrc = d "worker-src" WorkerSrc+ manifestSrc = d "manifest-src" ManifestSrc+ prefetchSrc = d "prefetch-src" PrefetchSrc d x y = string x >> s >> slist >>= mkWithSource y slist = sepBy1 source (char ' ') s = spaces@@ -138,6 +145,15 @@ Nothing -> fail "reportUri" -- n.b. compile time error Just uri -> return $ ReportUri uri +reportTo :: Parser Directive+reportTo = do+ _ <- string "report-to"+ _ <- spaces+ g <- takeTill separated+ if T.null g+ then fail "reportTo" -- n.b. compile time error+ else return $ ReportTo g+ baseUri :: Parser Directive baseUri = do _ <- string "base-uri"@@ -179,4 +195,4 @@ directive :: Parser DirectiveList directive = sepBy (spaces *> d) separator <* (spaces *> endOfInput)- where d = withSourceList <|> reportUri <|> baseUri <|> pluginTypes <|> sandbox+ where d = withSourceList <|> reportUri <|> reportTo <|> baseUri <|> pluginTypes <|> sandbox
test/Test.hs view
@@ -6,7 +6,6 @@ import Codec.MIME.Parse (parseMIMEType) import Data.Attoparsec.Text-import Data.Functor ((<$>)) import Data.List.NonEmpty import Data.Maybe import Test.Hspec@@ -62,6 +61,18 @@ let dom = pure $ fromJust $ parseMIMEType "text/plain" header = getCspPolicy [PluginTypes dom] assertEq "plugin-types" header "plugin-types text/plain"+ yit "works with worker-src" $ do+ let header = getCspPolicy [WorkerSrc (Self :| [])]+ assertEq "worker-src" header "worker-src 'self'"+ yit "works with manifest-src" $ do+ let header = getCspPolicy [ManifestSrc (Self :| [])]+ assertEq "manifest-src" header "manifest-src 'self'"+ yit "works with prefetch-src" $ do+ let header = getCspPolicy [PrefetchSrc (Https :| [Self])]+ assertEq "prefetch-src" header "prefetch-src https: 'self'"+ yit "works with report-to" $ do+ let header = getCspPolicy [ReportTo "csp-endpoint"]+ assertEq "report-to" header "report-to csp-endpoint" ydescribe "Headers" $ yit "get set" $ do get HomeR@@ -86,12 +97,16 @@ assertEq "unsafe-eval" (parseOnly source "unsafe-eval") (Right UnsafeEval) assertEq "default-src self data:" (parseOnly withSourceList "default-src 'self' data:") (Right $ DefaultSrc (Self :| [DataScheme])) assertEq "report-uri http://hello.com" (parseOnly reportUri "report-uri http://hello.com") (Right $ ReportUri (fromJust (escapeAndParseURI "http://hello.com")))+ assertEq "report-to csp-endpoint" (parseOnly reportTo "report-to csp-endpoint") (Right $ ReportTo "csp-endpoint")+ assertEq "worker-src self" (parseOnly withSourceList "worker-src 'self'") (Right $ WorkerSrc (Self :| []))+ assertEq "manifest-src self" (parseOnly withSourceList "manifest-src 'self'") (Right $ ManifestSrc (Self :| []))+ assertEq "prefetch-src self" (parseOnly withSourceList "prefetch-src 'self'") (Right $ PrefetchSrc (Self :| [])) assertEq "sandbox allow-forms allow-scripts" (parseOnly sandbox "sandbox allow-forms allow-scripts") (Right $ Sandbox [AllowForms, AllowScripts]) yit "works with lists" $ do- let result = [ImgSrc $ Self :| [Https], ScriptSrc $ Host (fromJust $ escapeAndParseURI "https://foo.com") :| []]- assertEq "scripts and images" (parseOnly directive "img-src 'self' https:; script-src https://foo.com") (Right result)- let result = [ImgSrc $ Self :| [DataScheme, Host (fromJust $ escapeAndParseURI "https://foo.com")]]- assertEq "data and hosts" (parseOnly directive "img-src 'self' data: https://foo.com") (Right result)+ let resultHttps = [ImgSrc $ Self :| [Https], ScriptSrc $ Host (fromJust $ escapeAndParseURI "https://foo.com") :| []]+ assertEq "scripts and images" (parseOnly directive "img-src 'self' https:; script-src https://foo.com") (Right resultHttps)+ let resultData = [ImgSrc $ Self :| [DataScheme, Host (fromJust $ escapeAndParseURI "https://foo.com")]]+ assertEq "data and hosts" (parseOnly directive "img-src 'self' data: https://foo.com") (Right resultData) yit "works with nonces and th" $ do let result = [ScriptSrc $ (nonce "foo") :| []] assertEq "nonces and th" [csp|script-src 'nonce-foo'|] result
yesod-csp.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: yesod-csp-version: 0.2.7.1+version: 0.2.8.0 synopsis: Add CSP headers to Yesod apps description: Add CSP headers to Yesod apps. This helps reduce exposure to XSS attacks and bad assets. license: MIT