This commit is contained in:
Anaïs Saraiva
2026-08-15 00:35:22 +02:00
parent 954384d1e4
commit d8b9fbe993
8 changed files with 578 additions and 388 deletions
+37 -26
View File
@@ -9,7 +9,9 @@
set -euo pipefail
BASE="${BASE_URL:-http://127.0.0.1:3000}"
PW="hunter2"
TMP="$(mktemp -d)"
COOKIES="$TMP/cookies.txt"
trap 'rm -rf "$TMP"' EXIT
pass=0
@@ -30,61 +32,70 @@ get() { # get <jsonfile> <key>
bun -e 'const d = JSON.parse(await Bun.file(process.argv[3]).text()); console.log(d[process.argv[2]])' _ "$2" "$1"
}
up() { # up <file> [name] -> upload with the test password, writes json
curl -sS -f -F "password=$PW" -F "file=@$1;filename=${2:-$(basename "$1")}" "$BASE/api/upload"
}
auth() { # auth <key> -> POST password, stores cookie
rm -f "$COOKIES"
curl -sS -c "$COOKIES" -X POST -d "password=$PW" "$BASE/api/auth/$1" >/dev/null
}
fetch_auth() { # fetch_auth <key> <outfile>
curl -sS -b "$COOKIES" -o "$2" "$BASE/d/$1"
}
printf 'hello world\n' > "$TMP/plain.txt"
dd if=/dev/urandom of="$TMP/random.bin" bs=1M count=16 2>/dev/null
check "health endpoint" curl -sS -f "$BASE/api/health" >/dev/null
check "upload plain file" curl -sS -f -F "file=@$TMP/plain.txt" "$BASE/api/upload" > "$TMP/up.json"
check "upload without password is rejected (400)" test \
"$(curl -sS -o /dev/null -w '%{http_code}' -F "file=@$TMP/plain.txt" "$BASE/api/upload")" = "400"
up "$TMP/plain.txt" > "$TMP/up.json"
KEY="$(get "$TMP/up.json" key)"
ID="$(get "$TMP/up.json" id)"
URL="$(get "$TMP/up.json" url)"
[ -n "$KEY" ] && check "upload returns a key" true
check "download with key" curl -sS -f -o "$TMP/down.txt" "$BASE$URL"
check "downloaded content matches" cmp "$TMP/plain.txt" "$TMP/down.txt"
check "protected file serves a password form" test \
"$(curl -sS -o /dev/null -w '%{content_type}' "$BASE$URL")" = "text/html; charset=utf-8"
check "invalid key returns 404" test \
"$(curl -sS -o /dev/null -w '%{http_code}' "$BASE/d/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")" = "404"
check "id alone cannot download" test \
"$(curl -sS -o /dev/null -w '%{http_code}' "$BASE/d/$ID")" = "404"
check "storage directory not served" test \
"$(curl -sS -o /dev/null -w '%{http_code}' "$BASE/storage/")" = "404"
check "unicode filename upload" \
curl -sS -f -F "file=@$TMP/plain.txt;filename=caf%C3%A9-%E6%96%87%E4%BB%B6.txt" "$BASE/api/upload" > "$TMP/upU.json"
check "wrong password is rejected (redirect to error)" test \
"$(curl -sS -o /dev/null -w '%{http_code}' -X POST -d 'password=nope' "$BASE/api/auth/$KEY")" = "302"
auth "$KEY"
fetch_auth "$KEY" "$TMP/down.txt"
check "download with cookie matches" cmp "$TMP/plain.txt" "$TMP/down.txt"
up "$TMP/plain.txt" "caf%C3%A9-%E6%96%87%E4%BB%B6.txt" > "$TMP/upU.json"
KU="$(get "$TMP/upU.json" key)"
check "unicode filename download" curl -sS -f -o /dev/null "$BASE/d/$KU"
auth "$KU"
fetch_auth "$KU" "$TMP/downU.txt"
check "unicode filename download" test -s "$TMP/downU.txt"
check "path traversal filename sanitized" \
curl -sS -f -F "file=@$TMP/plain.txt;filename=../../../../etc/passwd" "$BASE/api/upload" > "$TMP/upT.json"
up "$TMP/plain.txt" "../../../../etc/passwd" > "$TMP/upT.json"
check "path traversal filename sanitized" true
check "upload 16MB binary" curl -sS -f -F "file=@$TMP/random.bin" "$BASE/api/upload" > "$TMP/upL.json"
up "$TMP/random.bin" > "$TMP/upL.json"
KL="$(get "$TMP/upL.json" key)"
check "download 16MB binary" curl -sS -f -o "$TMP/random.out" "$BASE/d/$KL"
auth "$KL"
fetch_auth "$KL" "$TMP/random.out"
check "16MB round-trip identical" cmp "$TMP/random.bin" "$TMP/random.out"
check "delete requires key" test \
check "delete requires key (no header -> 404)" test \
"$(curl -sS -o /dev/null -w '%{http_code}' -X DELETE "$BASE/api/files/$ID")" = "404"
check "delete with key succeeds" \
curl -sS -f -X DELETE -H "X-Delete-Key: $KEY" "$BASE/api/files/$ID" >/dev/null
check "file gone after delete" test \
"$(curl -sS -o /dev/null -w '%{http_code}' "$BASE$URL")" = "404"
echo
echo "-- password protection --"
check "upload with password" curl -sS -f -F "password=hunter2" -F "file=@$TMP/plain.txt" "$BASE/api/upload" > "$TMP/upP.json"
KP="$(get "$TMP/upP.json" key)"
check "protected file serves a password form" test \
"$(curl -sS -o /dev/null -w '%{content_type}' "$BASE/d/$KP")" = "text/html; charset=utf-8"
check "wrong password is rejected" test \
"$(curl -sS -o /dev/null -w '%{http_code}' -X POST -d 'password=nope' "$BASE/api/auth/$KP")" = "302"
check "correct password returns redirect" curl -sS -c "$TMP/cj.txt" -X POST -d "password=hunter2" "$BASE/api/auth/$KP" >/dev/null
curl -sS -b "$TMP/cj.txt" -o "$TMP/downP.txt" "$BASE/d/$KP"
check "download with cookie matches" cmp "$TMP/plain.txt" "$TMP/downP.txt"
echo
echo "passed: $pass, failed: $fail"
[ "$fail" -eq 0 ] || exit 1