From 2f3eba0cb190ea98bd27f936f29357ca5fe757f3 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Thu, 29 Oct 2026 22:09:39 +0100 Subject: [PATCH] fix(34): WR-03 refuse user info in https git URLs validateGitURL refused only a password, but GitHub, GitLab and Gitea take a token as the user part of an https URL. Such a URL was printed and written to .gitmodules by git submodule add, and so committed with the application. An https URL with any user info is now refused with a hint to use a credential helper; the user of an ssh URL stays allowed. --- docs/plugins/marketplace.md | 2 +- internal/build/install_smoke_test.go | 3 +++ internal/build/source.go | 9 ++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/plugins/marketplace.md b/docs/plugins/marketplace.md index c6b5b8a4..6857db35 100644 --- a/docs/plugins/marketplace.md +++ b/docs/plugins/marketplace.md @@ -152,7 +152,7 @@ The repository is cloned with your own git setup (credential helpers, SSH keys, The plugin's required plugins are looked up in the registry by ID and installed as submodules too. With `--offline` no registry call is made, so every required plugin must already be in `summer.yaml`; a missing one stops the install and is named. -Only `https://`, `ssh://` and scp-like `user@host:path` addresses are accepted. Git runs with `GIT_ALLOW_PROTOCOL=https:ssh`, so `ext::` and `file::` transports, `file://` and plain `http://` are refused, as is an address that starts with `-` or carries a password (use a credential helper instead). +Only `https://`, `ssh://` and scp-like `user@host:path` addresses are accepted. Git runs with `GIT_ALLOW_PROTOCOL=https:ssh`, so `ext::` and `file::` transports, `file://` and plain `http://` are refused, as is an address that starts with `-` or carries a password, and an `https://` address with any user part, since a token there (`https://@github.com/...`) would be written to `.gitmodules` and committed. Use a credential helper instead; the user of an `ssh://` or `user@host:path` address is fine. ### Updating plugins diff --git a/internal/build/install_smoke_test.go b/internal/build/install_smoke_test.go index 5a01d744..4ddf2e2a 100644 --- a/internal/build/install_smoke_test.go +++ b/internal/build/install_smoke_test.go @@ -576,6 +576,9 @@ func TestInstallSmoke(t *testing.T) { "http://git.example.com/acme/blog.git", "git://git.example.com/acme/blog.git", "https://user:secret@git.example.com/acme/blog.git", + "https://ghp_token@github.com/acme/blog.git", + "https://oauth2@git.example.com/acme/blog.git", + "ssh://git:secret@git.example.com/acme/blog.git", "https://git.example.com/-x", "git@git.example.com:-oProxyCommand=x", "https://git.example.com/a b.git", diff --git a/internal/build/source.go b/internal/build/source.go index 358197c2..7458e2ec 100644 --- a/internal/build/source.go +++ b/internal/build/source.go @@ -78,7 +78,8 @@ func isGitURL(arg string) bool { // validateGitURL accepts https://, ssh:// and scp-like user@host:path // addresses (file:// only when cliGitProtocols allows it, in tests). It // refuses a leading "-", transport::address forms, http, credentials in -// the URL and control characters. +// the URL (any user info in an https URL, a password in any URL) and +// control characters. func validateGitURL(raw string) error { switch { case raw == "": @@ -117,6 +118,12 @@ func validateGitURL(raw string) error { if _, hasPassword := u.User.Password(); hasPassword { return fmt.Errorf("git URL must not carry a password; use a git credential helper") } + // GitHub, GitLab and Gitea take a token as the user part of an https + // URL; it would be printed and written to .gitmodules (WR-03). The + // user of an ssh URL is not a secret. + if scheme == "https" && u.User != nil { + return fmt.Errorf("an https git URL must not carry user info (a token in the user part ends up in .gitmodules); use a git credential helper") + } if strings.HasPrefix(u.Path, "/-") || u.Path == "" || u.Path == "/" { return fmt.Errorf("git URL %q has an invalid path", raw) }