From ce9ab9a269523d556d59b5aade6b0ad0147c26cd Mon Sep 17 00:00:00 2001 From: Pierre BLONDEAU Date: Wed, 21 Jan 2026 23:30:00 +0100 Subject: [PATCH 1/2] Ignore comment in credentials --- main.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/main.go b/main.go index d0e8d6a..1b94562 100644 --- a/main.go +++ b/main.go @@ -234,11 +234,18 @@ func getCredential(req *credential, credFile string) *credential { scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() + + if strings.HasPrefix(strings.TrimSpace(line), "#") || strings.HasPrefix(strings.TrimSpace(line), "//") { + log.Printf("ignore comment : %s", line) + continue + } + cred := parseCredential(line) if cred == nil { log.Printf("err malformed credential line: %s", line) continue } + if cred.match(req) { return cred } From 794d7afa86c8a24e6d7ba0fe29b6e2244b4c0228 Mon Sep 17 00:00:00 2001 From: Pierre BLONDEAU Date: Thu, 22 Jan 2026 00:28:38 +0100 Subject: [PATCH 2/2] Improved Usernames / Organization / Groups Path Matching in credentials MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old version only supported host verification. When combined with useHttpPath, it could only check a single-level path for usernames, organizations, or groups, not the full path. If the first line matched the host or the first-level path, those credentials were returned, even if a later line specified a more precise path. Example: https://USERNAME:TOKEN1@gitlab.com/group/subgroup1/project.git https://USERNAME:TOKEN2@gitlab.com/group/subgroup2/project2.git https://USERNAME:TOKEN3@gitlab.com/group/subgroup2/ https://USERNAME:TOKEN4@gitlab.com/group/ For the repository: https://USERNAME:TOKEN2@gitlab.com/group/subgroup2/project2.git Without useHttpPath: Only the host, protocol, and HTTP username (if specified) are checked. It returns TOKEN1. With useHttpPath (old version), only the first-level path was checked, even though the rest of the path did not match. In this case, it’s the same as above, so it returns TOKEN1. Now, The system checks if the path configured in the credentials is the beginning of the requested path. For the same repository: https://USERNAME:TOKEN2@gitlab.com/group/subgroup2/project2.git Without useHttpPath: Behavior remains unchanged (returns TOKEN1). With useHttpPath (new version): It can now match the full path or a partial path, regardless of the number of username/organization/group levels. Since the full path of the first line doesn’t match the request, it continues to the second line, which does match. It returns TOKEN2. Notes: The third line provides global credentials for other projects under /group/subgroup2/. The fourth line provides global credentials for other projects under /group/. Important: The order of lines in the credentials file matters. More specific paths should be listed before broader ones. --- main.go | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/main.go b/main.go index 1b94562..9153220 100644 --- a/main.go +++ b/main.go @@ -100,19 +100,9 @@ func (c *credential) match(req *credential) bool { } if req.path != "" { - // get username or org from repo path like `username-or-org/reponame.git` - reqOrg, _, hasSep := strings.Cut(req.path, "/") - if hasSep && reqOrg != "" { - matchReqPath := strings.TrimRight(reqOrg, "/") - matchConfigPath := strings.TrimRight(c.path, "/") - match = match && matchReqPath == matchConfigPath - log.Printf("match path by username or org: req.path=%v,config.path=%v,result=%v", - matchReqPath, matchConfigPath, match) - } else { - match = match && c.path == req.path - log.Printf("match path: req.path=%v,other.path=%v,result=%v", - c.path, req.path, match) - } + match = match && strings.HasPrefix(req.path, c.path) + log.Printf("match path by username or org: req.path=%v,config.path=%v,result=%v", + req.path, c.path, match) } return match }