diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,10 +1,14 @@
 # Changelog for biscuit-haskell
 
+## 0.4.0.1
+
+- force datalog evaluation to WHNF when running the maxtime watchdog
+
 ## 0.4.0.0
 
 - abort authorization on evaluation error as mandated by the spec
 - use utf8 byte count in `{string}.length()` as mandated by the spec
-- fix security issue with third-party blocks public key interning
+- fix security issue with third-party blocks public key interning, see [advisory](https://github.com/biscuit-auth/biscuit/security/advisories/GHSA-rgqv-mwc3-c78m)
 
 ## 0.3.0.1
 
diff --git a/biscuit-haskell.cabal b/biscuit-haskell.cabal
--- a/biscuit-haskell.cabal
+++ b/biscuit-haskell.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.0
 
 name:           biscuit-haskell
-version:        0.4.0.0
+version:        0.4.0.1
 category:       Security
 synopsis:       Library support for the Biscuit security token
 description:    Please see the README on GitHub at <https://github.com/biscuit-auth/biscuit-haskell#readme>
@@ -49,7 +49,7 @@
   build-depends:
     base                 >= 4.7 && <5,
     async                ^>= 2.2,
-    base16               >= 0.3 && <2.0,
+    base16               >= 0.3 && <2,
     bytestring           >= 0.10 && <0.12,
     text                 >= 1.2 && <3,
     containers           ^>= 0.6,
@@ -82,6 +82,8 @@
       Spec.ScopedExecutor
       Spec.Verification
       Paths_biscuit_haskell
+  autogen-modules:
+      Paths_biscuit_haskell
   hs-source-dirs:
       test
   ghc-options: -threaded -rtsopts -with-rtsopts=-N
@@ -89,7 +91,7 @@
       async
     , aeson
     , base >=4.7 && <5
-    , base16 >=0.3 && <2.0
+    , base16 >=0.3 && <2
     , base64
     , biscuit-haskell
     , bytestring
diff --git a/src/Auth/Biscuit/Datalog/ScopedExecutor.hs b/src/Auth/Biscuit/Datalog/ScopedExecutor.hs
--- a/src/Auth/Biscuit/Datalog/ScopedExecutor.hs
+++ b/src/Auth/Biscuit/Datalog/ScopedExecutor.hs
@@ -25,6 +25,7 @@
   , collectWorld
   ) where
 
+import           Control.Exception             (evaluate)
 import           Control.Monad                 (unless, when)
 import           Control.Monad.State           (StateT (..), evalStateT, get,
                                                 gets, lift, put)
@@ -111,7 +112,7 @@
                       -- ^ A authorizer
                       -> IO (Either ExecutionError AuthorizationSuccess)
 runAuthorizerWithLimits l@Limits{..} authority blocks v = do
-  resultOrTimeout <- timer maxTime $ pure $ runAuthorizerNoTimeout l authority blocks v
+  resultOrTimeout <- timer maxTime $ evaluate $ runAuthorizerNoTimeout l authority blocks v
   pure $ case resultOrTimeout of
     Nothing -> Left Timeout
     Just r  -> r
@@ -160,7 +161,12 @@
                        -> BlockWithRevocationId
                        -> [BlockWithRevocationId]
                        -> Authorizer
-                       -> Either ExecutionError AuthorizationSuccess
+                       -> -- NB: The return type here requires all checks and policies to be checked before
+                          -- the value can be forced to WHNF (we can only decide between Left _ and Right _
+                          -- based on the result of these checks). The implementation of the maxTime limit
+                          -- depends on this property, if this type changes the property will need to be
+                          -- preserved or the maxTime limit respected some other way
+                          Either ExecutionError AuthorizationSuccess
 runAuthorizerNoTimeout limits authority blocks authorizer = do
   let fst' (a,_,_) = a
       trd' (_,_,c) = c
