- name: Verify [make check/install]
run: make check/install
+ # Handles Android (Termux)
+ termux-test:
+ runs-on: ubuntu-latest
+ container:
+ image: termux/termux-docker:latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install dependencies
+ run: pkg update && pkg install -y git make
+
+ - name: Run your test script
+ run: ./my-test-script.sh
+
# Lint job
lint:
runs-on: ubuntu-latest
echo "Error: --hard requires --force" >&2
exit 1
fi
- if [ "${FORCE_INIT:-}" = "yes" ] && [ -z "$FORCE_CLEAN" ]; then
- echo "Error: --init requires --force" >&2
- echo "(To scan a repository, use 'clean' without arguments)" >&2
- exit 1
- fi
break # Stop parsing outer loop
;;
stat)
if [ -e "$fet_head" ]; then
command mv -f "$fet_head" "$fet_head.$$~" || :
fi
- if git fetch -q -f "$1" "$Gref_rbranch:$Gref" >/dev/null; then
- obj_id="$(git ls-tree "$Gref" | xgrep -E '\b'"$2"'$' | awk '{print $3}')"
+ if git fetch -q -f "$1" "$Gref_rbranch:$Gref-fetch" >/dev/null; then
+ obj_id="$(git ls-tree "$Gref-fetch" | xgrep -E '\b'"$2"'$' | awk '{print $3}')"
if isnonnull "$obj_id" && git cat-file blob "$obj_id"; then
ret_=:
else
local commit_id="" empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
# get any file to update Gref, and if it's not updated we create empty
git update-ref -d "$Gref" || :
- gitception_get "$1" "x" 2>/dev/null >&2 || :
+ if gitception_get "$1" "x" 2>/dev/null >&2; then
+ git update-ref "$Gref" "$Gref-fetch"
+ fi
git rev-parse -q --verify "$Gref" >/dev/null && return 0 ||
commit_id=$(anon_commit "$empty_tree") &&
git update-ref "$Gref" "$commit_id"
rungpg()
{
if isnonnull "$Conf_gpg_args"; then
- set -- "$Conf_gpg_args" "$@"
+ # shellcheck disable=SC2086
+ set -- $Conf_gpg_args "$@"
fi
# gpg will fail to run when there is no controlling tty,
# due to trying to print messages to it, even if a gpg agent is set
print_debug "Getting manifest from $URL file $Manifestfile"
# GET "$URL" "$Manifestfile" "$tmp_manifest" 2>| "$tmp_stderr" || {
# Debugging: don't capture stderr, let it flow to console
+ git update-ref -d "$Gref-fetch" || :
GET "$URL" "$Manifestfile" "$tmp_manifest" || {
if ! isnull "$Repoid"; then
cat >&2 "$tmp_stderr"
fi
}
+ # gitception: populate Gref from fetch
+ if git rev-parse -q --verify "$Gref-fetch" >/dev/null; then
+ git update-ref "$Gref" "$Gref-fetch"
+ fi
+
Did_find_repo=yes
echo_info "Decrypting manifest"
if ! manifest_=$(PRIVDECRYPT "$r_sigmatch" "$r_signers" < "$tmp_manifest") || \
fi
echo_info "Removing files..."
+
+ # If we are forcing clean on uninitialized repo, Gref might be missing.
+ # Fetch it so gitception_remove has a base.
+ if [ "$Did_find_repo" != "yes" ] && isnonnull "$Gref_rbranch"; then
+ git fetch -q -f "$URL" "$Gref_rbranch:$Gref" 2>/dev/null || :
+ fi
+
REMOVE "$URL" "$bad_files"
if [ "${DO_REPACK:-}" = "yes" ]; then
DOT_GARBAGE_BLOB=$(echo "HIDDEN GARBAGE" | $GIT hash-object -w --stdin)
export GIT_INDEX_FILE=index.dotgarbage
$GIT read-tree "$NEW_TREE"
-$GIT update-index --add --cacheinfo 100644 "$DOT_GARBAGE_BLOB" ".garbage_file"
+$GIT update-index --add --cacheinfo 100644 "$DOT_GARBAGE_BLOB" ".garbage (file)"
NEW_TREE_DOT=$($GIT write-tree)
rm index.dotgarbage
NEW_COMMIT_DOT=$(echo "Inject dot garbage" | $GIT commit-tree "$NEW_TREE_DOT" -p "$NEW_COMMIT")
$GIT update-ref "$GREF" "$NEW_COMMIT_DOT"
-if ! $GIT ls-tree -r "$GREF" | grep -q "\.garbage_file"; then
- print_err "Failed to inject .garbage_file into $GREF"
+if ! $GIT ls-tree -r "$GREF" | grep -F -q ".garbage (file)"; then
+ print_err "Failed to inject .garbage (file) into $GREF"
exit 1
fi
-print_info "Injected .garbage_file into remote $GREF"
+print_info "Injected '.garbage (file)' into remote $GREF"
# 3. Scan (expect to find garbage_file)
set -x
output=$("$SCRIPT_DIR/git-remote-gcrypt" clean "gcrypt::$tempdir/valid.git" 2>&1)
set +x
assert_grep "garbage_file" "$output" "clean identified unencrypted file in valid repo"
-assert_grep "\.garbage_file" "$output" "clean identified unencrypted DOTFILE in valid repo"
+assert_grep "\.garbage (file)" "$output" "clean identified unencrypted DOTFILE in valid repo"
assert_grep "NOTE: This is a scan" "$output" "clean scan-only mode confirmed"
# 4. Clean Force
-"$SCRIPT_DIR/git-remote-gcrypt" clean "gcrypt::$tempdir/valid.git" --force >/dev/null 2>&1
+"$SCRIPT_DIR/git-remote-gcrypt" clean "gcrypt::$tempdir/valid.git" --force
# Verify garbage_file is GONE from the GREF tree
UPDATED_TREE=$($GIT rev-parse "$GREF^{tree}")
mkdir -p "$GNUPGHOME"
chmod 700 "$GNUPGHOME"
-cat <<EOF >"${GNUPGHOME}/gpg"
+cat <<'EOF' >"${GNUPGHOME}/gpg"
#!/usr/bin/env bash
export GNUPGHOME="$GNUPGHOME"
set -efuC -o pipefail; shopt -s inherit_errexit
-args=( "\${@}" )
-for ((i = 0; i < \${#}; ++i)); do
- if [[ \${args[\${i}]} = "--secret-keyring" ]]; then
- unset "args[\${i}]" "args[\$(( i + 1 ))]"
+args=( "${@}" )
+for ((i = 0; i < ${#}; ++i)); do
+ if [[ ${args[${i}]} = "--secret-keyring" ]]; then
+ unset "args[${i}]" "args[$(( i + 1 ))]"
break
fi
done
-exec gpg "\${args[@]}"
+exec gpg "${args[@]}"
EOF
chmod +x "${GNUPGHOME}/gpg"
# Start should have 3 commits (init, push1, push2, push3) -> wait, init is implicit.
# Each push updates the manifested repo.
-# Run clean --repack
+# Inject garbage to verify cleanup AND repack
+echo "GARBAGE" >garbage.txt
+GARBAGE_BLOB=$(git hash-object -w garbage.txt)
+echo "Created garbage blob: $GARBAGE_BLOB"
+# Manually inject into backend (simulate inconsistency)
+# But here we are simulating a gitception remote.
+# To simulate "garbage" (unencrypted file), we can push one or hack the backend.
+# Using 'git-remote-gcrypt' clean mechanism relies on files existing in the remote manifest (or filesystem for other backends).
+# For git backend, "garbage" is a file in the remote repo's HEAD tree that isn't in the manifest/packed list.
+# Let's clone backend, add file, push.
+cd "$TEST_DIR/raw_backend"
+echo "Garbage Data" >".garbage (file)"
+git add ".garbage (file)"
+git commit -m "Inject unencrypted garbage"
+git push origin master
+
+# Verify garbage exists
cd "$REPO_DIR"
-echo "Running clean --repack..."
-git-remote-gcrypt clean --repack origin
+# Run clean --repack --force (needed because we have garbage now)
+echo "Running clean --repack --force..."
+git-remote-gcrypt clean --repack --force origin
+
+# Verify garbage removal from backend
+cd "$TEST_DIR/raw_backend"
+git pull origin master
+
+if [ -f ".garbage (file)" ]; then
+ echo "Failure: .garbage (file) still exists in backend!"
+ exit 1
+else
+ echo "Success: .garbage (file) removed."
+fi
# Verify result
# Clone backend again (pull) and check structure
git init
git remote add origin "${tempdir}/remote-repo"
echo "API_KEY=12345-SUPER-SECRET" >.env
-git add .env
+git add -f .env
git commit -m "Oops, pushed secret keys"
+LEAK_SHA=$(git rev-parse master)
git push origin master
print_info "Step 3: Switch to git-remote-gcrypt usage"
# But we know it persists.
cd "${tempdir}/remote-repo"
-if git ls-tree -r master | grep -q ".env"; then
- print_warn "PRIVACY LEAK DETECTED: .env file matches found in remote!"
- print_warn "Content of .env in remote:"
- git show master:.env
- print_success "Test Passed: Vulnerability successfully reproduced."
+if git cat-file -e "$LEAK_SHA"; then
+ print_warn "PRIVACY LEAK DETECTED: Leaked commit $LEAK_SHA still exists in remote objects!"
+ if git cat-file -p "$LEAK_SHA:.env" >/dev/null; then
+ print_warn "Content of .env is reachable."
+ print_success "Test Passed: Vulnerability successfully reproduced."
+ else
+ print_err "Commit exists but .env unreadable?"
+ exit 1
+ fi
else
- print_err "Unexpected: .env file NOT found. Did gcrypt overwrite it?"
- # detecting it is 'failure' of the vulnerability check, but 'success' for privacy
+ print_err "Unexpected: Leaked commit NOT found. Did gcrypt prune it?"
exit 1
fi