防止 JGit 读取本机 git 配置

Prevent JGit from reading the native git config

我正在应用程序中使用 JGit。这个应用程序有一个 SecurityManager 只允许特定的白名单 类 和产生新进程的方法。

JGit 内部发现是否安装了本机 git 并尝试在 org.eclipse.jgit.util.FS.discoverGitSystemConfig() 中读取其配置,甚至尝试在 org.eclipse.jgit.util.FS_POSIX.findHook() 中查找挂钩并查看它们是否可执行。

由于前面提到的安全管理器就位,JGit 无法运行并失败。 我试图在文档中找到是否有办法抑制这种行为?

截至目前,FS 检测 并不意味着可以在 JGit 中扩展(参见 FS.DETECTED)。它将始终引用 JGit 提供的文件系统之一。

但是...

实现您自己的 FS 似乎是可行的,这样可以避免调用受限的 API。

通过 FileRepositoryBuilder 创建 Repository 时,您可以指定 FS,从而使存储库使用您的自定义 FS。如果所有 JGit 代码都查阅要使用的文件系统的存储库,那么您的问题应该得到解决。

在JGit (3.3+) 的最新版本中,您可以将环境变量GIT_CONFIG_NOSYSTEM 设置为任意值,这将抑制本机系统范围内的读取Git 配置文件。这是通过 Constants#GIT_CONFIG_NOSYSTEM_KEY.

在 JGit 源中定义的

这模拟了一个空的系统级配置文件,它可以防止代码在随机文件路径中搜索并引发安全异常,这是最初的问题。请注意,即使在这种情况下,JGit 仍会尝试使用用户级配置文件(通常在 $HOME/.gitconfig 中)。

这个问题的一个更常见的变体大概是使用一组预定义的配置选项而不用担心任何环境污染(系统或用户级配置),所以上面的修复并没有填补所有的空白。

以下示例显示如何使用 JGit 在定义的路径中使用特定的基于用户的 Git 配置文件,它提供一个空的系统级 Git配置文件,这意味着可以通过编程方式控制整个配置。

要使用它,请在 运行 任何 JGit 命令之前使用以下代码安装您自己的 SystemReader:

File userGitConfig = new File("/my/path/foo.config");
SystemReader.setInstance(new CustomConfigSystemReader(userGitConfig));

然后提供以下新的 CustomConfigSystemReader class:

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;

import java.io.File;

public class CustomConfigSystemReader extends SystemReader
{
    private static final SystemReader proxy = SystemReader.getInstance();
    private File userGitConfig;

    public CustomConfigSystemReader(File userGitConfig)
    {
        super();
        this.userGitConfig = userGitConfig;
    }

    @Override
    public String getenv(String variable)
    {
        return proxy.getenv(variable);
    }

    @Override
    public String getHostname()
    {
        return proxy.getHostname();
    }

    @Override
    public String getProperty(String key)
    {
        return proxy.getProperty(key);
    }

    @Override
    public long getCurrentTime()
    {
        return proxy.getCurrentTime();
    }

    @Override
    public int getTimezone(long when)
    {
        return proxy.getTimezone(when);
    }

    @Override
    public FileBasedConfig openUserConfig(Config parent, FS fs)
    {
        return new FileBasedConfig(parent, userGitConfig, fs);
    }

    // Return an empty system configuration, based on example in SystemReader.Default#openSystemConfig
    @Override
    public FileBasedConfig openSystemConfig(Config parent, FS fs)
    {
        return new FileBasedConfig(parent, null, fs)
        {
            @Override
            public void load()
            {
            }

            @Override
            public boolean isOutdated()
            {
                return false;
            }
        };
    }
}

我在初始化 git 存储库时最终使用了 SystemReader.getInstance().userConfig.clear()