diff --git a/mateclaw-server/src/main/java/vip/mate/skill/installer/GitSkillFetcher.java b/mateclaw-server/src/main/java/vip/mate/skill/installer/GitSkillFetcher.java index 2161ef5a..907e5f78 100644 --- a/mateclaw-server/src/main/java/vip/mate/skill/installer/GitSkillFetcher.java +++ b/mateclaw-server/src/main/java/vip/mate/skill/installer/GitSkillFetcher.java @@ -1,6 +1,7 @@ package vip.mate.skill.installer; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import vip.mate.skill.installer.model.SkillBundle; import vip.mate.skill.runtime.SkillFrontmatterParser; @@ -27,12 +28,23 @@ public class GitSkillFetcher { private final SkillFrontmatterParser frontmatterParser; - /** 读取环境变量 GITHUB_TOKEN,用于访问私有仓库(公有仓库不受影响) */ - private final String githubToken = System.getenv("GITHUB_TOKEN") != null - ? System.getenv("GITHUB_TOKEN") : ""; + /** + * GitHub access token used when cloning private repositories. + * Resolution order: {@code mateclaw.skill.github-token} property → {@code GITHUB_TOKEN} + * environment variable → empty (public repos only). Kept as a plain field so the value + * is never logged or embedded in URLs — it is passed to the git subprocess through + * dedicated environment variables (see {@link #cloneRepo}). + */ + private final String githubToken; - public GitSkillFetcher(SkillFrontmatterParser frontmatterParser) { + public GitSkillFetcher( + SkillFrontmatterParser frontmatterParser, + @Value("${mateclaw.skill.github-token:}") String configuredGithubToken) { this.frontmatterParser = frontmatterParser; + String token = (configuredGithubToken != null && !configuredGithubToken.isBlank()) + ? configuredGithubToken + : System.getenv("GITHUB_TOKEN"); + this.githubToken = (token == null) ? "" : token.trim(); } /** @@ -102,15 +114,15 @@ public class GitSkillFetcher { } /** - * git clone --depth 1 到临时目录 + * git clone --depth 1 to a temporary directory. + *
+ * When a GitHub token is configured and the repository is hosted on github.com,
+ * the credential is forwarded to the git subprocess through {@code GIT_CONFIG_*}
+ * environment variables — equivalent to {@code git -c http.extraHeader=...} but
+ * without ever placing the token in the process command line (visible to {@code ps})
+ * or the repository URL (visible in logs and error messages). Requires git 2.31+.
*/
private void cloneRepo(String repoUrl, String ref, Path targetDir) throws IOException, InterruptedException {
- // 如果配置了 GITHUB_TOKEN 且是 GitHub 地址,注入 token 以支持私有仓库
- // 公有仓库带 token 访问同样正常,不受影响
- if (!githubToken.isBlank() && repoUrl.contains("github.com")) {
- repoUrl = repoUrl.replaceFirst("https://", "https://" + githubToken + "@");
- }
-
var command = new java.util.ArrayList