From: Shane Jaroch Date: Sat, 17 Jan 2026 04:45:32 +0000 (-0500) Subject: Update tests & code. Add Android/Termux workflow X-Git-Url: https://git.nutra.tk/v2?a=commitdiff_plain;h=9484b87dce7b5a1c41bbf0e0397c63d62ee3d138;p=gamesguru%2Fgit-remote-gcrypt.git Update tests & code. Add Android/Termux workflow --- diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 1cf0c1e..1d651c2 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -89,6 +89,20 @@ jobs: - 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 diff --git a/git-remote-gcrypt b/git-remote-gcrypt index 3e8bb9f..bc9d938 100755 --- a/git-remote-gcrypt +++ b/git-remote-gcrypt @@ -107,11 +107,6 @@ while [ $# -gt 0 ]; do 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) @@ -367,8 +362,8 @@ gitception_get() 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 @@ -460,7 +455,9 @@ gitception_new_repo() 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" @@ -690,7 +687,8 @@ gpg_hash() 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 @@ -922,6 +920,7 @@ ensure_connected() 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" @@ -934,6 +933,11 @@ ensure_connected() 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") || \ @@ -1603,6 +1607,13 @@ cmd_clean() 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 diff --git a/tests/system-test-clean-command.sh b/tests/system-test-clean-command.sh index b5d9e78..43f35e5 100755 --- a/tests/system-test-clean-command.sh +++ b/tests/system-test-clean-command.sh @@ -222,28 +222,28 @@ print_info "Injected garbage_file into remote $GREF" 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}") diff --git a/tests/system-test-clean-repack.sh b/tests/system-test-clean-repack.sh index 29df415..edeb0f7 100755 --- a/tests/system-test-clean-repack.sh +++ b/tests/system-test-clean-repack.sh @@ -28,18 +28,18 @@ export GNUPGHOME="$TEST_DIR/gpg" mkdir -p "$GNUPGHOME" chmod 700 "$GNUPGHOME" -cat <"${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" @@ -109,10 +109,38 @@ echo "Backend SHA: $HEAD_SHA" # 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 diff --git a/tests/system-test-privacy-leaks.sh b/tests/system-test-privacy-leaks.sh index 1d79295..8d553b6 100755 --- a/tests/system-test-privacy-leaks.sh +++ b/tests/system-test-privacy-leaks.sh @@ -66,8 +66,9 @@ cd "${tempdir}/dirty-setup" 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" @@ -106,14 +107,17 @@ print_info "Step 4: Verify LEAKAGE" # 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