diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
-## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.0.2.0...main)
+## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.0.2.1...main)
 
 - None.
+
+## [v1.0.2.1](https://github.com/freckle/freckle-app/compare/v1.0.2.0...v1.0.2.1)
+
+- Add `denyFrameEmbeddingMiddleware` for denying HTML frame embedding.
 
 ## [v1.0.2.0](https://github.com/freckle/freckle-app/compare/v1.0.1.0...v1.0.2.0)
 
diff --git a/freckle-app.cabal b/freckle-app.cabal
--- a/freckle-app.cabal
+++ b/freckle-app.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.12
 name:               freckle-app
-version:            1.0.2.0
+version:            1.0.2.1
 license:            MIT
 license-file:       LICENSE
 maintainer:         Freckle Education
diff --git a/library/Freckle/App/Wai.hs b/library/Freckle/App/Wai.hs
--- a/library/Freckle/App/Wai.hs
+++ b/library/Freckle/App/Wai.hs
@@ -8,6 +8,7 @@
   , makeRequestMetricsMiddleware
   , noCacheMiddleware
   , corsMiddleware
+  , denyFrameEmbeddingMiddleware
   ) where
 
 import Prelude
@@ -199,6 +200,10 @@
 corsMiddleware validateOrigin extraExposedHeaders =
   handleOptions validateOrigin extraExposedHeaders
     . addCORSHeaders validateOrigin extraExposedHeaders
+
+-- | Middleware that adds header to deny all frame embedding
+denyFrameEmbeddingMiddleware :: Middleware
+denyFrameEmbeddingMiddleware = addHeaders [("X-Frame-Options", "DENY")]
 
 handleOptions :: (ByteString -> Bool) -> [ByteString] -> Middleware
 handleOptions validateOrigin extraExposedHeaders app req sendResponse =
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -1,6 +1,6 @@
 ---
 name: freckle-app
-version: 1.0.2.0
+version: 1.0.2.1
 maintainer: Freckle Education
 category: Utils
 github: freckle/freckle-app
diff --git a/tests/Freckle/App/WaiSpec.hs b/tests/Freckle/App/WaiSpec.hs
--- a/tests/Freckle/App/WaiSpec.hs
+++ b/tests/Freckle/App/WaiSpec.hs
@@ -1,14 +1,14 @@
 module Freckle.App.WaiSpec
   ( spec
-  )
-where
+  ) where
 
 import Prelude
 
 import Data.ByteString (ByteString)
 import Data.Function (on)
 import Data.List (deleteBy)
-import Freckle.App.Wai (corsMiddleware, noCacheMiddleware)
+import Freckle.App.Wai
+  (corsMiddleware, denyFrameEmbeddingMiddleware, noCacheMiddleware)
 import Network.HTTP.Types.Method (Method)
 import Network.HTTP.Types.Status (status200)
 import Network.Wai
@@ -83,6 +83,17 @@
             "Access-Control-Expose-Headers"
             "Set-Cookie, Content-Disposition, Link, X-Foo"
             response
+
+  describe "denyFrameEmbeddingMiddleware" $ do
+    let
+      runTestSession :: Session a -> IO a
+      runTestSession f = runSession f $ denyFrameEmbeddingMiddleware app
+
+    it "adds an appropriate X-Frame-Options header" $ runTestSession $ do
+      response <- request defaultRequest
+
+      assertHeader "X-Frame-Options" "DENY" response
+      assertBody "Test" response
 
 app :: Application
 app _req respond = respond $ responseLBS status200 [] "Test"
