safer git sha object filename

Rather than use the filename provided by INPUT, which could come from user
input, and so could be something that looks like a dashed parameter,
use a .git/object/<sha> filename.

This avoids user input passing through INPUT and back out, with the file
path then passed to a command, which could do something unexpected with
a dashed parameter, or other special parameter.

Added a note in the design about being careful of passing user input to
commands. They still have to be careful of that in general, just not in
this case.
This commit is contained in:
Joey Hess 2025-03-04 14:54:13 -04:00
parent 1ee4d018f3
commit a2fc471e14
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
2 changed files with 17 additions and 5 deletions

View file

@ -425,10 +425,9 @@ runComputeProgram (ComputeProgram program) state (ImmutableState immutablestate)
Nothing -> pure Nothing Nothing -> pure Nothing
Just (Right f'') -> liftIO $ Just (Right f'') -> liftIO $
Just <$> relPathDirToFile subdir f'' Just <$> relPathDirToFile subdir f''
Just (Left gitsha) -> do Just (Left gitsha) ->
liftIO . F.writeFile (subdir </> f') Just <$> (liftIO . relPathDirToFile subdir
=<< catObject gitsha =<< populategitsha gitsha tmpdir)
return (Just f')
liftIO $ hPutStrLn (stdinHandle p) $ liftIO $ hPutStrLn (stdinHandle p) $
maybe "" fromOsPath mp maybe "" fromOsPath mp
liftIO $ hFlush (stdinHandle p) liftIO $ hFlush (stdinHandle p)
@ -479,6 +478,17 @@ runComputeProgram (ComputeProgram program) state (ImmutableState immutablestate)
calcduration (MonotonicTimestamp starttime) (MonotonicTimestamp endtime) = calcduration (MonotonicTimestamp starttime) (MonotonicTimestamp endtime) =
fromIntegral (endtime - starttime) :: NominalDiffTime fromIntegral (endtime - starttime) :: NominalDiffTime
-- Writes to a .git/objects/ file in the tmpdir, rather than
-- using the input filename, to avoid exposing the input filename
-- to the program as a parameter, which could parse it as a dashed
-- option or other special parameter.
populategitsha gitsha tmpdir = do
let f = tmpdir </> ".git" </> "objects"
</> toOsPath (Git.fromRef' gitsha)
liftIO $ createDirectoryIfMissing True $ takeDirectory f
liftIO . F.writeFile f =<< catObject gitsha
return f
computationBehaviorChangeError :: ComputeProgram -> String -> OsPath -> Annex a computationBehaviorChangeError :: ComputeProgram -> String -> OsPath -> Annex a
computationBehaviorChangeError (ComputeProgram program) requestdesc p = computationBehaviorChangeError (ComputeProgram program) requestdesc p =
giveup $ program ++ " is not behaving the same way it used to, now " ++ requestdesc ++ ": " ++ fromOsPath p giveup $ program ++ " is not behaving the same way it used to, now " ++ requestdesc ++ ": " ++ fromOsPath p

View file

@ -23,7 +23,9 @@ that is in the form "foo=bar" will also result in an environment variable
being set, eg `ANNEX_COMPUTE_passes=10` or `ANNEX_COMPUTE_--level=9`. being set, eg `ANNEX_COMPUTE_passes=10` or `ANNEX_COMPUTE_--level=9`.
For security, the program should avoid exposing user input to the shell For security, the program should avoid exposing user input to the shell
unprotected, or otherwise executing it. unprotected, or otherwise executing it. And when running a command, make
sure that whatever user input is passed to it can result in only safe and
expected behavior.
The program is run in a temporary directory, which will be cleaned up after The program is run in a temporary directory, which will be cleaned up after
it exits. Note that it may be run in a subdirectory of a temporary it exits. Note that it may be run in a subdirectory of a temporary