diff --git a/README.md b/README.md index f1c8397..3808f07 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ The setup script configures your identity (git author for AUR commits), SSH acce | `github-asset` | GitHub Releases API | Assets re-uploaded on a fixed tag | | `gitlab-tag` | GitLab Tags API | Any GitLab instance | | `gitea-tag` | Gitea/Forgejo API | Codeberg, self-hosted Gitea | -| `git-latest` | `git clone --bare` | `-git` packages, any git repo | +| `git-latest` | `git clone --bare` | `-git` packages, any HTTPS git repo | | `pypi` | PyPI JSON API | Python packages | | `npm` | npm registry | Node.js packages | | `crates` | crates.io API | Rust crates | diff --git a/docs/WORKFLOW.md b/docs/WORKFLOW.md index ca7ef03..dd29afb 100644 --- a/docs/WORKFLOW.md +++ b/docs/WORKFLOW.md @@ -309,7 +309,7 @@ upstream: ### 3.7 git-latest -**What it checks:** any git repository, through a bare clone. +**What it checks:** any git repository with an HTTPS URL, through a bare clone. **When to use:** `-git` AUR packages that track the latest commit. @@ -320,10 +320,12 @@ upstream: | `upstream.type` | yes | One of: `github`, `gitlab`, `git` | | `upstream.host` | depends | Required for the `gitlab` type | | `upstream.project` | depends | Required for the `github` and `gitlab` types | -| `upstream.url` | depends | Required for the `git` type: full clone URL | +| `upstream.url` | depends | Required for the `git` type: full clone URL, `https://` only | **How the version is extracted:** makes a bare clone into a temporary directory, counts the commits on `HEAD` (`git rev-list --count HEAD`), takes the short hash (`git rev-parse --short=7 HEAD`) and prints the usual `-git` format `r.`, for example `r431.66db9ce`. +The clone runs with `GIT_ALLOW_PROTOCOL=http:https`. A URL in a package YAML that comes with a pull request therefore cannot read a local repository or connect to an ssh host with the SSH key of the machine that runs the check. + **Example YAML (GitHub):** ```yaml @@ -345,7 +347,7 @@ upstream: project: network/my-kde-app ``` -**Example YAML (any git URL):** +**Example YAML (any HTTPS git URL):** ```yaml name: my-package-git diff --git a/packages/example.yml.sample b/packages/example.yml.sample index 8678345..c074950 100644 --- a/packages/example.yml.sample +++ b/packages/example.yml.sample @@ -129,7 +129,7 @@ upstream: # type: github # required: github|gitlab|git # project: owner/repo # required for github|gitlab # host: gitlab.example.com # required for gitlab -# url: https://example.com/repo.git # required for type=git +# url: https://example.com/repo.git # required for type=git, https only # --- pypi / npm / crates ---------------------------------------------------- # Language registries. PyPI and crates return stable releases only. diff --git a/scripts/validate-pkg.sh b/scripts/validate-pkg.sh index f89731f..f451a00 100755 --- a/scripts/validate-pkg.sh +++ b/scripts/validate-pkg.sh @@ -177,6 +177,9 @@ validate_pkg() { if [[ -z "$url" || "$url" == "null" ]]; then log_err "$file: git-latest type 'git' requires 'upstream.url'" ((errors++)) + elif [[ "$url" != https://* ]]; then + log_err "$file: upstream.url must use HTTPS: $url" + ((errors++)) fi ;; *) diff --git a/strategies/git-latest.sh b/strategies/git-latest.sh index 8398ccc..d806994 100755 --- a/strategies/git-latest.sh +++ b/strategies/git-latest.sh @@ -36,11 +36,12 @@ case "$upstream_type" in ;; esac -# Clone bare repo to get commit count + hash +# Clone bare repo to get commit count + hash. http and https only, so a URL +# from the YAML reaches no local repository and no ssh host. tmp_dir=$(mktemp -d) trap 'rm -rf "$tmp_dir"' EXIT -git clone --bare --quiet "$repo_url" "$tmp_dir/repo" || { +GIT_ALLOW_PROTOCOL=http:https git clone --bare --quiet "$repo_url" "$tmp_dir/repo" || { echo "Failed to clone $repo_url" >&2 exit 1 } diff --git a/tests/strategies.bats b/tests/strategies.bats index 9dbfea7..900c579 100644 --- a/tests/strategies.bats +++ b/tests/strategies.bats @@ -273,12 +273,55 @@ teardown() { create_test_package "test-git" "git-latest" "upstream: type: git - url: ${fake_repo}" + url: https://git.example.com/repo.git" + + # git that clones the fake repo in place of the URL, and logs the + # protocols the strategy allows + cat >"$MOCK_DIR/git" <>"$TEST_TMPDIR/git-clone" + exec env -u GIT_ALLOW_PROTOCOL /usr/bin/git clone "\${@:2:\$#-3}" "$fake_repo" "\${@: -1}" +fi +exec /usr/bin/git "\$@" +EOF + chmod +x "$MOCK_DIR/git" run "$TEST_TMPDIR/strategies/git-latest.sh" "test-git" [ "$status" -eq 0 ] # Should match r3.<7-char-hash> [[ "$output" =~ ^r3\.[0-9a-f]{7}$ ]] + [ "$(cat "$TEST_TMPDIR/git-clone")" = "http:https https://git.example.com/repo.git" ] +} + +@test "git-latest: refuses a local repository" { + git init -q "$TEST_TMPDIR/local-repo" + git -C "$TEST_TMPDIR/local-repo" -c user.name=test -c user.email=test@test \ + commit -q --allow-empty -m "commit 1" + create_test_package "test-git-file" "git-latest" "upstream: + type: git + url: file://$TEST_TMPDIR/local-repo" + + run "$TEST_TMPDIR/strategies/git-latest.sh" "test-git-file" + [ "$status" -eq 1 ] + [[ "$output" == *"transport 'file' not allowed"* ]] +} + +@test "git-latest: refuses an ssh URL without connecting" { + cat >"$MOCK_DIR/ssh" <>"$TEST_TMPDIR/ssh.args" +exit 255 +EOF + chmod +x "$MOCK_DIR/ssh" + create_test_package "test-git-ssh" "git-latest" "upstream: + type: git + url: ssh://git.example.com/repo.git" + + run "$TEST_TMPDIR/strategies/git-latest.sh" "test-git-ssh" + [ "$status" -eq 1 ] + [[ "$output" == *"transport 'ssh' not allowed"* ]] + [ ! -e "$TEST_TMPDIR/ssh.args" ] } # === github-nightly === diff --git a/tests/validate-pkg.bats b/tests/validate-pkg.bats index ee0e288..3c1991f 100644 --- a/tests/validate-pkg.bats +++ b/tests/validate-pkg.bats @@ -68,6 +68,24 @@ teardown() { [ "$status" -eq 0 ] } +@test "validate: git-latest git type fails on a URL without HTTPS" { + create_test_package "mypkg" "git-latest" "upstream: + type: git + url: file:///srv/repo" + run "$TEST_TMPDIR/scripts/validate-pkg.sh" "mypkg" + [ "$status" -eq 1 ] + [[ "$output" == *"upstream.url must use HTTPS: file:///srv/repo"* ]] +} + +@test "validate: git-latest git type fails on an HTTP URL" { + create_test_package "mypkg" "git-latest" "upstream: + type: git + url: http://git.example.com/repo.git" + run "$TEST_TMPDIR/scripts/validate-pkg.sh" "mypkg" + [ "$status" -eq 1 ] + [[ "$output" == *"upstream.url must use HTTPS: http://git.example.com/repo.git"* ]] +} + @test "validate: pypi passes" { create_test_package "mypkg" "pypi" "upstream: registry: requests"