diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -59,11 +59,13 @@
     isVerbose :: Bool,
     format :: Hadolint.OutputFormat,
     dockerfiles :: [String],
-    lintingOptions :: Hadolint.LintOptions
+    lintingOptions :: Hadolint.LintOptions,
+    filePathInReportOption :: Maybe FilePath
   }
 
 toOutputFormat :: String -> Maybe Hadolint.OutputFormat
 toOutputFormat "json" = Just Hadolint.Json
+toOutputFormat "sonarqube" = Just Hadolint.SonarQube
 toOutputFormat "tty" = Just Hadolint.TTY
 toOutputFormat "codeclimate" = Just Hadolint.CodeclimateJson
 toOutputFormat "gitlab_codeclimate" = Just Hadolint.GitlabCodeclimateJson
@@ -73,6 +75,7 @@
 
 showFormat :: Hadolint.OutputFormat -> String
 showFormat Hadolint.Json = "json"
+showFormat Hadolint.SonarQube = "sonarqube"
 showFormat Hadolint.TTY = "tty"
 showFormat Hadolint.CodeclimateJson = "codeclimate"
 showFormat Hadolint.GitlabCodeclimateJson = "gitlab_codeclimate"
@@ -99,6 +102,7 @@
     <*> outputFormat
     <*> files
     <*> lintOptions
+    <*> filePathInReportOption
   where
     version = switch (long "version" <> short 'v' <> help "Show version")
 
@@ -206,6 +210,14 @@
         <*> parseRulesConfig
         <*> noFailCutoff
 
+    filePathInReportOption =
+      optional
+        ( strOption
+            ( long "file-path-in-report" <> metavar "FILEPATHINREPORT"
+                <> help "The file path referenced in the generated report. This only applies for the 'checkstyle' format and is useful when running Hadolint with Docker to set the correct file path."
+            )
+        )
+
     labels =
       Map.fromList
         <$> many
@@ -247,7 +259,7 @@
 noFailure :: Hadolint.Result s e -> Rule.DLSeverity -> Bool
 noFailure (Hadolint.Result _ Seq.Empty Seq.Empty) _ = True
 noFailure (Hadolint.Result _ Seq.Empty fails) cutoff =
-  Seq.null (Seq.filter (\f -> Rule.severity f < cutoff) fails)
+  Seq.null (Seq.filter (\f -> Rule.severity f <= cutoff) fails)
 noFailure _ _ = False
 
 exitProgram ::
@@ -267,7 +279,8 @@
   res <- Hadolint.lintIO conf files
   noColorEnv <- lookupEnv "NO_COLOR"
   let noColor = nocolor cmd || isJust noColorEnv
-  Hadolint.printResults (format cmd) noColor res
+  let filePathInReport = filePathInReportOption cmd
+  Hadolint.printResults (format cmd) noColor filePathInReport res
   exitProgram cmd conf res
 
 main :: IO ()
diff --git a/hadolint.cabal b/hadolint.cabal
--- a/hadolint.cabal
+++ b/hadolint.cabal
@@ -3,11 +3,9 @@
 -- This file has been generated from package.yaml by hpack version 0.34.4.
 --
 -- see: https://github.com/sol/hpack
---
--- hash: 81ce3bbf6ac259bb1aeda5e670d68ec5cbcb3bf9d955d085de125eb4e39f3fc8
 
 name:           hadolint
-version:        2.4.1
+version:        2.5.0
 synopsis:       Dockerfile Linter JavaScript API
 description:    A smarter Dockerfile linter that helps you build best practice Docker images.
 category:       Development
@@ -39,6 +37,7 @@
       Hadolint.Formatter.Codeclimate
       Hadolint.Formatter.Format
       Hadolint.Formatter.Json
+      Hadolint.Formatter.SonarQube
       Hadolint.Formatter.TTY
       Hadolint.Ignore
       Hadolint.Lint
diff --git a/src/Hadolint.hs b/src/Hadolint.hs
--- a/src/Hadolint.hs
+++ b/src/Hadolint.hs
@@ -16,6 +16,7 @@
 import qualified Hadolint.Formatter.Codeclimate
 import Hadolint.Formatter.Format (Result (..))
 import qualified Hadolint.Formatter.Json
+import qualified Hadolint.Formatter.SonarQube
 import qualified Hadolint.Formatter.TTY
 import Hadolint.Lint
 import Hadolint.Process
@@ -23,6 +24,7 @@
 
 data OutputFormat
   = Json
+  | SonarQube
   | TTY
   | CodeclimateJson
   | GitlabCodeclimateJson
@@ -33,12 +35,13 @@
 shallSkipErrorStatus :: OutputFormat -> Bool
 shallSkipErrorStatus format = format `elem` [CodeclimateJson, Codacy]
 
-printResults :: Foldable f => OutputFormat -> Bool -> f (Result Text DockerfileError) -> IO ()
-printResults format nocolor allResults =
+printResults :: Foldable f => OutputFormat -> Bool -> Maybe FilePath -> f (Result Text DockerfileError) -> IO ()
+printResults format nocolor filePathInReport allResults =
   case format of
     TTY -> Hadolint.Formatter.TTY.printResults allResults nocolor
+    SonarQube -> Hadolint.Formatter.SonarQube.printResults allResults
     Json -> Hadolint.Formatter.Json.printResults allResults
-    Checkstyle -> Hadolint.Formatter.Checkstyle.printResults allResults
+    Checkstyle -> Hadolint.Formatter.Checkstyle.printResults allResults filePathInReport
     CodeclimateJson -> Hadolint.Formatter.Codeclimate.printResults allResults
     GitlabCodeclimateJson -> Hadolint.Formatter.Codeclimate.printGitlabResults allResults
     Codacy -> Hadolint.Formatter.Codacy.printResults allResults
diff --git a/src/Hadolint/Formatter/Checkstyle.hs b/src/Hadolint/Formatter/Checkstyle.hs
--- a/src/Hadolint/Formatter/Checkstyle.hs
+++ b/src/Hadolint/Formatter/Checkstyle.hs
@@ -81,8 +81,8 @@
         else "&#" <> Text.pack (show (ord c)) <> ";"
     isOk x = any (\check -> check x) [isAsciiUpper, isAsciiLower, isDigit, (`elem` [' ', '.', '/'])]
 
-formatResult :: (VisualStream s, TraversableStream s, ShowErrorComponent e) => Result s e -> Builder.Builder
-formatResult (Result filename errors checks) = header <> xmlBody <> footer
+formatResult :: (VisualStream s, TraversableStream s, ShowErrorComponent e) => Result s e -> Maybe FilePath -> Builder.Builder
+formatResult (Result filename errors checks) filePathInReport = header <> xmlBody <> footer
   where
     xmlBody = Foldl.fold (Foldl.premap toXml Foldl.mconcat) issues
 
@@ -91,21 +91,29 @@
     checkstyleChecks = fmap ruleToCheckStyle checks
 
     isEmpty = null checks && null errors
+    name = if null filePathInReport then filename else getFilePath filePathInReport
     header =
       if isEmpty
         then ""
-        else "<file " <> attr "name" (encode filename) <> ">"
+        else "<file " <> attr "name" (encode name) <> ">"
     footer = if isEmpty then "" else "</file>"
 
 printResults ::
   (Foldable f, VisualStream s, TraversableStream s, ShowErrorComponent e) =>
-  f (Result s e) ->
+  f (Result s e) -> Maybe FilePath ->
   IO ()
-printResults results = do
+printResults results filePathInReport = do
   B.putStr header
   mapM_ put results
   B.putStr footer
   where
     header = "<?xml version='1.0' encoding='UTF-8'?><checkstyle version='4.3'>"
     footer = "</checkstyle>"
-    put result = Builder.hPutBuilder stdout (formatResult result)
+    put result = Builder.hPutBuilder stdout (formatResult result filePathInReport)
+
+getFilePath :: Maybe FilePath -> Text.Text 
+getFilePath Nothing = ""
+getFilePath (Just filePath) = toText [filePath]
+
+toText :: [FilePath] -> Text.Text 
+toText = foldMap Text.pack
diff --git a/src/Hadolint/Formatter/SonarQube.hs b/src/Hadolint/Formatter/SonarQube.hs
new file mode 100644
--- /dev/null
+++ b/src/Hadolint/Formatter/SonarQube.hs
@@ -0,0 +1,103 @@
+module Hadolint.Formatter.SonarQube
+  ( formatResult,
+    printResults
+  )
+  where
+
+import qualified Control.Foldl as Foldl
+import Data.Aeson hiding (Result)
+import qualified Data.ByteString.Lazy.Char8 as B
+import Data.Sequence (Seq)
+import qualified Data.Text as Text
+import Hadolint.Formatter.Format
+  ( Result (..),
+    errorPosition,
+    errorMessage
+  )
+import Hadolint.Rule
+  ( CheckFailure (..),
+    DLSeverity (..),
+    unRuleCode
+  )
+import Text.Megaparsec (TraversableStream)
+import Text.Megaparsec.Error
+import Text.Megaparsec.Pos
+  ( sourceColumn,
+    sourceLine,
+    sourceName,
+    unPos
+  )
+import Text.Megaparsec.Stream (VisualStream)
+
+
+data SonarQubeFormat s e
+  = SonarQubeCheck Text.Text CheckFailure
+  | SonarQubeError (ParseErrorBundle s e)
+
+instance (VisualStream s,
+  TraversableStream s,
+  ShowErrorComponent e) => ToJSON (SonarQubeFormat s e) where
+  toJSON (SonarQubeCheck filename CheckFailure {..}) =
+    object
+      [ "engineId" .= Text.pack "Hadolint",
+        "ruleId" .= unRuleCode code,
+        "severity" .= toSeverity severity,
+        "type" .= toType severity,
+        "primaryLocation" .= object
+          [ "message" .= message,
+            "filePath" .= filename,
+            "textRange" .= object
+              [ "startLine" .= line,
+                "endLine" .= line,
+                "startColumn" .= (1 :: Int),
+                "endColumn" .= (1 :: Int)
+              ]
+          ]
+      ]
+  toJSON (SonarQubeError err) =
+    object
+      [ "engineId" .= Text.pack "Hadolint",
+        "ruleId" .= Text.pack "DL1000",
+        "severity" .= Text.pack "BLOCKER",
+        "type" .= Text.pack "BUG",
+        "primaryLocation" .= object
+          [ "message" .= errorMessage err,
+            "filePath" .= Text.pack (sourceName pos),
+            "textRange" .= object
+              [ "startLine" .= linenumber,
+                "endLine" .= linenumber,
+                "startColumn" .= column,
+                "endColumn" .= column
+              ]
+          ]
+      ]
+    where
+      pos = errorPosition err
+      linenumber = unPos $ sourceLine pos
+      column = unPos $ sourceColumn pos
+
+
+formatResult :: Result s e -> Seq (SonarQubeFormat s e)
+formatResult (Result filename errors checks) = allMessages
+  where
+    allMessages = errorMessages <> checkMessages
+    errorMessages = fmap SonarQubeError errors
+    checkMessages = fmap (SonarQubeCheck filename) checks
+
+printResults :: (VisualStream s,
+  TraversableStream s,
+  ShowErrorComponent e,
+  Foldable f) => f (Result s e) -> IO ()
+printResults results = B.putStr . encode $ object [ "issues" .= flattened ]
+  where
+    flattened = Foldl.fold (Foldl.premap formatResult Foldl.mconcat) results
+
+toType :: DLSeverity -> Text.Text
+toType DLErrorC = "BUG"
+toType _ = "CODE_SMELL"
+
+toSeverity :: DLSeverity -> Text.Text
+toSeverity DLErrorC = "CRITICAL"
+toSeverity DLWarningC = "MAJOR"
+toSeverity DLInfoC = "MINOR"
+toSeverity _ = "INFO"
diff --git a/src/Hadolint/Rule/DL4006.hs b/src/Hadolint/Rule/DL4006.hs
--- a/src/Hadolint/Rule/DL4006.hs
+++ b/src/Hadolint/Rule/DL4006.hs
@@ -18,14 +18,15 @@
 
     check _ st From {} = st |> replaceWith False -- Reset the state each time we find a new FROM
     check _ st (Shell args)
-      | foldArguments isPowerShell args = st |> replaceWith True
+      | foldArguments isNonPosixShell args = st |> replaceWith True
       | otherwise = st |> replaceWith (foldArguments hasPipefailOption args)
     check line st@(State _ False) (Run (RunArgs args _))
       | foldArguments hasPipes args = st |> addFail CheckFailure {..}
       | otherwise = st
     check _ st _ = st
 
-    isPowerShell (Shell.ParsedShell orig _ _) = "pwsh" `Text.isPrefixOf` orig
+    isNonPosixShell (Shell.ParsedShell orig _ _) =
+      any (`Text.isPrefixOf` orig) Shell.nonPosixShells
     hasPipes script = Shell.hasPipes script
     hasPipefailOption script =
       not $
diff --git a/src/Hadolint/Shell.hs b/src/Hadolint/Shell.hs
--- a/src/Hadolint/Shell.hs
+++ b/src/Hadolint/Shell.hs
@@ -61,8 +61,8 @@
 
 shellcheck :: ShellOpts -> ParsedShell -> [PositionedComment]
 shellcheck (ShellOpts sh env) (ParsedShell txt _ _) =
-  if "pwsh" `Text.isPrefixOf` sh
-    then [] -- Do no run for powershell
+  if any (`Text.isPrefixOf` sh) nonPosixShells
+    then [] -- Do no run for non-posix shells i.e. powershell, cmd.exe
     else runShellCheck
   where
     runShellCheck = crComments $ runIdentity $ checkScript si spec
@@ -84,6 +84,9 @@
 
     extractShell s = fromMaybe "" (listToMaybe . Text.words $ s)
     printVars = Text.unlines . Set.toList $ Set.map (\v -> "export " <> v <> "=1") env
+
+nonPosixShells :: [Text.Text]
+nonPosixShells = ["pwsh", "powershell", "cmd"]
 
 parseShell :: Text.Text -> ParsedShell
 parseShell txt = ParsedShell {original = txt, parsed = parsedResult, presentCommands = commands}
diff --git a/test/DL4006.hs b/test/DL4006.hs
--- a/test/DL4006.hs
+++ b/test/DL4006.hs
@@ -81,3 +81,24 @@
               "RUN wget -O - https://some.site | wc -l file > /number"
             ]
        in ruleCatches "DL4006" $ Text.unlines dockerFile
+    it "ignore non posix shells: pwsh" $
+      let dockerFile =
+            [ "FROM mcr.microsoft.com/powershell:ubuntu-16.04",
+              "SHELL [ \"pwsh\", \"-c\" ]",
+              "RUN Get-Variable PSVersionTable | Select-Object -ExpandProperty Value"
+            ]
+       in ruleCatchesNot "DL4006" $ Text.unlines dockerFile
+    it "ignore non posix shells: powershell" $
+      let dockerFile =
+            [ "FROM mcr.microsoft.com/powershell:ubuntu-16.04",
+              "SHELL [ \"powershell.exe\" ]",
+              "RUN Get-Variable PSVersionTable | Select-Object -ExpandProperty Value"
+            ]
+       in ruleCatchesNot "DL4006" $ Text.unlines dockerFile
+    it "ignore non posix shells: cmd.exe" $
+      let dockerFile =
+            [ "FROM mcr.microsoft.com/powershell:ubuntu-16.04",
+              "SHELL [ \"cmd.exe\", \"/c\" ]",
+              "RUN Get-Variable PSVersionTable | Select-Object -ExpandProperty Value"
+            ]
+       in ruleCatchesNot "DL4006" $ Text.unlines dockerFile
diff --git a/test/Shellcheck.hs b/test/Shellcheck.hs
--- a/test/Shellcheck.hs
+++ b/test/Shellcheck.hs
@@ -110,10 +110,19 @@
             assertChecks dockerFile passesShellcheck
             assertOnBuildChecks dockerFile passesShellcheck
 
-    it "Does not complain on powershell" $
+    it "Does not complain on non-posix shells: pwsh" $
       let dockerFile =
             Text.unlines
               [ "SHELL [\"pwsh\", \"-c\"]",
+                "RUN Get-Variable PSVersionTable | Select-Object -ExpandProperty Value"
+              ]
+       in do
+            assertChecks dockerFile passesShellcheck
+            assertOnBuildChecks dockerFile passesShellcheck
+    it "Does not complain on non-posix shells: cmd.exe" $
+      let dockerFile =
+            Text.unlines
+              [ "SHELL [\"cmd.exe\", \"/c\"]",
                 "RUN Get-Variable PSVersionTable | Select-Object -ExpandProperty Value"
               ]
        in do
