From 828378cdff995b5f9f2230e1a9e2e47171b4f4b2 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Sat, 23 May 2015 13:03:07 -0700 Subject: [PATCH] Warn about injecting filenames into sh -c strings with find. --- ShellCheck/Analytics.hs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/ShellCheck/Analytics.hs b/ShellCheck/Analytics.hs index 63da3ca..bdbb31e 100644 --- a/ShellCheck/Analytics.hs +++ b/ShellCheck/Analytics.hs @@ -203,6 +203,7 @@ nodeChecks = [ ,checkFindExecWithSingleArgument ,checkReturn ,checkMaskedReturns + ,checkInjectableFindSh ] @@ -3348,6 +3349,30 @@ checkMaskedReturns _ t@(T_SimpleCommand id _ (cmd:rest)) = potentially $ do _ -> False checkMaskedReturns _ _ = return () +prop_checkInjectableFindSh1 = verify checkInjectableFindSh "find . -exec sh -c 'echo {}' \\;" +prop_checkInjectableFindSh2 = verify checkInjectableFindSh "find . -execdir bash -c 'rm \"{}\"' ';'" +prop_checkInjectableFindSh3 = verifyNot checkInjectableFindSh "find . -exec sh -c 'rm \"$@\"' _ {} \\;" +checkInjectableFindSh _ = checkCommand "find" (const check) + where + check args = do + let idStrings = map (\x -> (getId x, onlyLiteralString x)) args + match pattern idStrings + + match _ [] = return () + match [] (next:_) = action next + match (p:tests) ((id, arg):args) = do + when (p arg) $ match tests args + match (p:tests) args + + pattern = [ + (`elem` ["-exec", "-execdir"]), + (`elem` ["sh", "bash", "ksh"]), + (== "-c") + ] + action (id, arg) = + when ("{}" `isInfixOf` arg) $ + warn id 2156 "Injecting filenames is fragile and insecure. Use parameters." + return [] runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])