diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -153,12 +153,13 @@
 | [DL3022](https://github.com/hadolint/hadolint/wiki/DL3022)   | `COPY --from` should reference a previously defined `FROM` alias                                                                                    |
 | [DL3023](https://github.com/hadolint/hadolint/wiki/DL3023)   | `COPY --from` cannot reference its own `FROM` alias                                                                                                 |
 | [DL3024](https://github.com/hadolint/hadolint/wiki/DL3024)   | `FROM` aliases (stage names) must be unique                                                                                                         |
-| [DL3025](https://github.com/hadolint/hadolint/wiki/DL3025)   | Use argumens JSON notation for CMD and ENTRYPOINT arguments                                                                                         |
+| [DL3025](https://github.com/hadolint/hadolint/wiki/DL3025)   | Use arguments JSON notation for CMD and ENTRYPOINT arguments                                                                                        |
 | [DL4000](https://github.com/hadolint/hadolint/wiki/DL4000)   | MAINTAINER is deprecated.                                                                                                                           |
 | [DL4001](https://github.com/hadolint/hadolint/wiki/DL4001)   | Either use Wget or Curl but not both.                                                                                                               |
 | [DL4003](https://github.com/hadolint/hadolint/wiki/DL4003)   | Multiple `CMD` instructions found.                                                                                                                  |
 | [DL4004](https://github.com/hadolint/hadolint/wiki/DL4004)   | Multiple `ENTRYPOINT` instructions found.                                                                                                           |
 | [DL4005](https://github.com/hadolint/hadolint/wiki/DL4005)   | Use `SHELL` to change the default shell.                                                                                                            |
+| [DL4006](https://github.com/hadolint/hadolint/wiki/DL4006)   | Set the `SHELL` option -o pipefail before `RUN` with a pipe in it                                                                                   |
 | [SC1000](https://github.com/koalaman/shellcheck/wiki/SC1000) | `$` is not used specially and should therefore be escaped.                                                                                          |
 | [SC1001](https://github.com/koalaman/shellcheck/wiki/SC1001) | This `\c` will be a regular `'c'`  in this context.                                                                                                 |
 | [SC1007](https://github.com/koalaman/shellcheck/wiki/SC1007) | Remove space after `=` if trying to assign a value (or for empty string, use `var='' ...`).                                                         |
diff --git a/hadolint.cabal b/hadolint.cabal
--- a/hadolint.cabal
+++ b/hadolint.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: ed40f7e723efb830715c051c8b06bf4693ace2a9f94c7a53e035fd1fc237febb
+-- hash: 0723e0fb6351589066a83e427a444fd8297f43911d23ac2c3a053888a957f94b
 
 name:           hadolint
-version:        1.8.0
+version:        1.9.0
 synopsis:       Dockerfile Linter JavaScript API
 description:    A smarter Dockerfile linter that helps you build best practice Docker images.
 category:       Development
diff --git a/src/Hadolint/Bash.hs b/src/Hadolint/Bash.hs
--- a/src/Hadolint/Bash.hs
+++ b/src/Hadolint/Bash.hs
@@ -43,17 +43,31 @@
               }
     }
 
-findCommands :: ParsedBash -> [Token]
-findCommands (ParsedBash _ ast) =
+extractTokensWith :: (Token -> Maybe Token) -> ParsedBash -> [Token]
+extractTokensWith extractor (ParsedBash _ ast) =
     case prRoot ast of
         Nothing -> []
         Just script -> nub . execWriter $ ShellCheck.AST.doAnalysis extract script
   where
     extract :: Token -> Writer [Token] ()
-    extract t =
-        case ShellCheck.ASTLib.getCommand t of
-            Nothing -> return ()
-            Just cmd -> tell [cmd]
+    extract token =
+      case extractor token of
+        Nothing -> return ()
+        Just t -> tell [t]
+
+findPipes :: ParsedBash -> [Token]
+findPipes = extractTokensWith pipesExtractor
+  where
+    pipesExtractor pipe@T_Pipe{} = Just pipe
+    pipesExtractor _ = Nothing
+
+hasPipes :: ParsedBash -> Bool
+hasPipes = not . null . findPipes
+
+findCommands :: ParsedBash -> [Token]
+findCommands = extractTokensWith commandsExtractor
+  where
+    commandsExtractor = ShellCheck.ASTLib.getCommand
 
 allCommands :: (Token -> Bool) -> ParsedBash -> Bool
 allCommands check script = all check (findCommands script)
diff --git a/src/Hadolint/Rules.hs b/src/Hadolint/Rules.hs
--- a/src/Hadolint/Rules.hs
+++ b/src/Hadolint/Rules.hs
@@ -175,6 +175,7 @@
     , multipleEntrypoints
     , useShell
     , useJsonArgs
+    , usePipefail
     ]
 
 commentMetadata :: ShellCheck.Interface.Comment -> Metadata
@@ -709,7 +710,30 @@
   where
     code = "DL3025"
     severity = WarningC
-    message = "Use argumens JSON notation for CMD and ENTRYPOINT arguments"
-    check (Cmd (ArgumentsText _ )) = False
-    check (Entrypoint (ArgumentsText _ )) = False
+    message = "Use arguments JSON notation for CMD and ENTRYPOINT arguments"
+    check (Cmd (ArgumentsText _)) = False
+    check (Entrypoint (ArgumentsText _)) = False
     check _ = True
+
+usePipefail :: Rule
+usePipefail = instructionRuleState code severity message check False
+  where
+    code = "DL4006"
+    severity = WarningC
+    message = "Set the SHELL option -o pipefail before RUN with a pipe in it"
+    check _ _ From {} = (False, True) -- Reset the state each time we find a new FROM
+    check _ _ (Shell args) = (argumentsRule hasPipefailOption args, True)
+    check False _ (Run args) = (False, argumentsRule notHasPipes args)
+    check st _ _ = (st, True)
+    notHasPipes script = not (Bash.hasPipes script)
+    hasPipefailOption script =
+        not $
+        null
+            [ True
+            | cmd <- Bash.findCommands script
+            , validShell <- ["/bin/bash", "/bin/zsh", "/bin/ash", "bash", "zsh", "ash"]
+            , Bash.getCommandName cmd == Just validShell
+            , Bash.hasFlag "o" cmd
+            , arg <- Bash.getAllArgs cmd
+            , arg == "pipefail"
+            ]
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -757,6 +757,74 @@
                         ]
                 in ruleCatchesNot useJsonArgs $ Text.unlines dockerFile
 
+        --
+        describe "Detects missing pipefail option" $ do
+            it "warn on missing pipefail" $
+                let dockerFile =
+                        [ "FROM scratch"
+                        , "RUN wget -O - https://some.site | wc -l > /number"
+                        ]
+                in ruleCatches usePipefail $ Text.unlines dockerFile
+            it "don't warn on commands with no pipes" $
+                let dockerFile =
+                        [ "FROM scratch as build"
+                        , "RUN wget -O - https://some.site && wc -l file > /number"
+                        ]
+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile
+            it "don't warn on commands with pipes and the pipefail option" $
+                let dockerFile =
+                        [ "FROM scratch as build"
+                        , "SHELL [\"/bin/bash\", \"-eo\", \"pipefail\", \"-c\"]"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        ]
+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile
+            it "don't warn on commands with pipes and the pipefail option 2" $
+                let dockerFile =
+                        [ "FROM scratch as build"
+                        , "SHELL [\"/bin/bash\", \"-e\", \"-o\", \"pipefail\", \"-c\"]"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        ]
+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile
+            it "don't warn on commands with pipes and the pipefail option 3" $
+                let dockerFile =
+                        [ "FROM scratch as build"
+                        , "SHELL [\"/bin/bash\", \"-o\", \"errexit\", \"-o\", \"pipefail\", \"-c\"]"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        ]
+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile
+            it "don't warn on commands with pipes and the pipefail zsh" $
+                let dockerFile =
+                        [ "FROM scratch as build"
+                        , "SHELL [\"/bin/zsh\", \"-o\", \"pipefail\", \"-c\"]"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        ]
+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile
+            it "warns when using plain sh" $
+                let dockerFile =
+                        [ "FROM scratch as build"
+                        , "SHELL [\"/bin/sh\", \"-o\", \"pipefail\", \"-c\"]"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        ]
+                in ruleCatches usePipefail $ Text.unlines dockerFile
+            it "warn on missing pipefail in the next image" $
+                let dockerFile =
+                        [ "FROM scratch as build"
+                        , "SHELL [\"/bin/bash\", \"-o\", \"pipefail\", \"-c\"]"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        , "FROM scratch as build2"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        ]
+                in ruleCatches usePipefail $ Text.unlines dockerFile
+            it "warn on missing pipefail if next SHELL is not using it" $
+                let dockerFile =
+                        [ "FROM scratch as build"
+                        , "SHELL [\"/bin/bash\", \"-o\", \"pipefail\", \"-c\"]"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        , "SHELL [\"/bin/sh\", \"-c\"]"
+                        , "RUN wget -O - https://some.site | wc -l file > /number"
+                        ]
+                in ruleCatches usePipefail $ Text.unlines dockerFile
+
 assertChecks :: HasCallStack => Rule -> Text.Text -> ([RuleCheck] -> IO a) -> IO a
 assertChecks rule s makeAssertions =
     case parseText (s <> "\n") of
