compute: add response to OUTPUT

This allows rejecting output filenames that are outside the repository,
and also handles converting eg "-foo" to "./-foo" to prevent a command
that it's passed to interpreting the output filename as a dashed option.
This commit is contained in:
Joey Hess 2025-03-07 14:47:34 -04:00
parent 6a8e57f0e9
commit 81ce4264df
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 19 additions and 12 deletions

View file

@ -472,6 +472,10 @@ runComputeProgram (ComputeProgram program) state (ImmutableState immutablestate)
Just (ProcessOutput f) -> do
let f' = toOsPath f
checksafefile tmpdir subdir f' "output"
-- Modify filename so eg "-foo" becomes "./-foo"
liftIO $ hPutStrLn (stdinHandle p) $
toCommand' (File f)
liftIO $ hFlush (stdinHandle p)
knownoutput <- case M.lookup f' (computeOutputs $ computeState result) of
Nothing -> return False
Just mk -> do

View file

@ -10,6 +10,7 @@
module Utility.SafeCommand (
CommandParam(..),
toCommand,
toCommand',
boolSystem,
boolSystem',
boolSystemEnv,

View file

@ -16,15 +16,15 @@ Whatever values the user passes to `git-annex addcomputed` are passed to
the program in `ARGV`, followed by any values that the user provided to
`git-annex initremote`.
To simplify the program's option parsing, any value that the user provides
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`.
For security, the program should avoid exposing user input to the shell
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.
To simplify the program's option parsing, any value that the user provides
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`.
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
directory. This is done when `git-annex addcomputed` was run in a subdirectory
@ -58,6 +58,12 @@ line to stdout:
OUTPUT file.jpeg
Then it can read a line from stdin. This will be a sanitized version of the
output filename. It's important to use that sanitized version to avoid path
traversal attacks, as well as problems like filenames that look like
dashed options. If there is a path traversal attack, the program's stdin will
be closed without a path being written to it.
The filename of the output file is both the filename in the program's
temporary directory, and also the filename that will be added to the
git-annex repository by `git-annex compute`.
@ -100,10 +106,9 @@ An example `git-annex-compute-foo` shell script follows:
echo "INPUT $2"
read input
echo "OUTPUT $3"
# Prefixing with ./ makes sure that the output is treated as a
# filename, rather than a dashed option.
output="./$3"
read output
echo REPRODUCIBLE
if [ -n "$input" ]; then
mkdir -p "$(dirname "$output")"
frobnicate --passes="$ANNEX_COMPUTE_passes" <"$input" >"$output"

View file

@ -1,5 +1,5 @@
#!/bin/sh
# git-annex compute special remote program that uses imagemagic's convert
# git-annex compute remote program that uses imagemagic's convert
# to convert one type of image format into another. Eg, jpeg to gif.
#
# Copyright 2025 Joey Hess; licenced under the GNU GPL version 3 or higher.
@ -14,10 +14,7 @@ fi
echo "INPUT $1"
read input
echo "OUTPUT $2"
# Prefixing with ./ makes sure that the output is treated as a
# filename, rather than a dashed option.
output="./$2"
read output
if [ -n "$input" ]; then
mkdir -p "$(dirname "$output")"