diff --git a/language-docker.cabal b/language-docker.cabal
--- a/language-docker.cabal
+++ b/language-docker.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: f5a50fe92ae4dd5da15e1c9273d27b742ae2ea0d62734a8be7e7a292a0f94571
+-- hash: f0209fb0b94b9ef4e99737b0a42828ca0f218151812c325b9f54b54141eadebc
 
 name:           language-docker
-version:        10.1.1
+version:        10.1.2
 synopsis:       Dockerfile parser, pretty-printer and embedded DSL
 description:    All functions for parsing and pretty-printing Dockerfiles are exported through @Language.Docker@. For more fine-grained operations look for specific modules that implement a certain functionality.
                 See the <https://github.com/hadolint/language-docker GitHub project> for the source-code and examples.
diff --git a/src/Language/Docker/Parser/Prelude.hs b/src/Language/Docker/Parser/Prelude.hs
--- a/src/Language/Docker/Parser/Prelude.hs
+++ b/src/Language/Docker/Parser/Prelude.hs
@@ -153,18 +153,9 @@
 brackets :: (?esc :: Char) => Parser a -> Parser a
 brackets = between (symbol "[" *> whitespace) (whitespace *> symbol "]")
 
-justWhitespace :: Parser Text
-justWhitespace = do
-  c <- choice
-    [ char ' ',
-      char '\t',
-      char '\n'
-    ]
-  return (T.pack [c])
-
 untilWS :: Parser Text
 untilWS = do
-  s <- manyTill L.charLiteral justWhitespace
+  s <- manyTill anySingle spaceChar
   return $ T.pack s
 
 heredocMarker :: Parser Text
@@ -182,7 +173,10 @@
 
 heredocContent :: Text -> Parser Text
 heredocContent marker = do
-  doc <- manyTill anySingle (string marker)
+  foo <- observing $ string $ marker <> "\n"
+  doc <- case foo of
+    Left _ -> manyTill anySingle (string $ "\n" <> marker <> "\n")
+    Right _ -> pure ""
   return $ T.strip $ T.pack doc
 
 heredoc :: Parser Text
diff --git a/test/Language/Docker/ParseRunSpec.hs b/test/Language/Docker/ParseRunSpec.hs
--- a/test/Language/Docker/ParseRunSpec.hs
+++ b/test/Language/Docker/ParseRunSpec.hs
@@ -317,9 +317,9 @@
           flags = def { security = Nothing }
        in assertAst file [ Run $ RunArgs (ArgumentsText "") flags ]
     it "evil heredoc" $
-      let file = Text.unlines [ "RUN <<EOF foo", "bar EOF"]
+      let file = Text.unlines [ "RUN <<EOF foo", "bar EOF", "EOF"]
           flags = def { security = Nothing }
-       in assertAst file [ Run $ RunArgs (ArgumentsText "foo\nbar") flags ]
+       in assertAst file [ Run $ RunArgs (ArgumentsText "foo\nbar EOF") flags ]
     it "heredoc with redirection to file" $
       let file = Text.unlines [ "RUN <<EOF > /file", "foo", "EOF" ]
           flags = def {security = Nothing }
@@ -343,3 +343,7 @@
                       )
                       flags
             ]
+    it "heredoc correct termination" $
+      let file = Text.unlines [ "RUN <<EOF", "echo $EOF", "EOF" ]
+          flags = def {security = Nothing }
+       in assertAst file [ Run $ RunArgs (ArgumentsText "echo $EOF") flags ]
