Direct Answers
- Unified CA bundle without global side effects: Create a dedicated Java truststore (JKS or PKCS12) containing your corporate CA, then point only the Jenkins agent JVM at it via
-Djavax.net.ssl.trustStore=/path/custom.jks -Djavax.net.ssl.trustStorePassword=changeit. Configure command-line Git to use the same PEM bundle with git config --global http.sslCAInfo /path/corporate-ca.pem. This isolates the trust decision to the agent and avoids mutating the system cacerts or OS store. - Forcing submodule/LFS to match the parent checkout: The Git Client Plugin uses the same implementation for the initial checkout and for submodule/LFS operations if the implementation is explicitly selected. Set
-Dorg.jenkinsci.plugins.gitclient.Git.useJGit=true (or false) on the agent to lock the entire job to one stack. Without this flag, Jenkins defaults to command-line Git when available and falls back to JGit only when the binary is missing, which can cause a split within a single build. - Roadmap: No public roadmap exists for a unified SSL verification mode. The maintainers have not converged since JGit was introduced in 2016. Teams should standardize on one implementation (preferably command-line Git for parity with developer machines) and enforce it via the system property above.
Why the Divergence Occurs
Command-line Git reads the OS trust store (/etc/ssl/certs, Windows Cert Store, macOS Keychain) plus Git config http.sslCAInfo/http.sslCAPath. JGit ignores Git config entirely and uses the JVM truststore (cacerts or -Djavax.net.ssl.trustStore) and JSSE system properties. Hostname verification also differs: command-line Git honors http.sslVerify=false; JGit requires a custom HostnameVerifier or -Djdk.tls.allowUnsafeServerCertChange=true (JDK 11+). Corporate MITM proxies and self-signed internal servers therefore succeed on one stack and fail on the other.
Practical Alignment Steps
- Export your corporate CA as a PEM file (e.g.,
corporate-ca.pem). - Create a dedicated truststore:
keytool -importcert -alias corporate-ca -file corporate-ca.pem -keystore /var/lib/jenkins/custom-truststore.jks -storepass changeit -noprompt
- Add JVM options to the agent launch command:
-Djavax.net.ssl.trustStore=/var/lib/jenkins/custom-truststore.jks -Djavax.net.ssl.trustStorePassword=changeit
- Configure command-line Git globally on the agent:
git config --system http.sslCAInfo /etc/ssl/certs/corporate-ca.pem
- Force a single implementation (choose one):
# Use command-line Git everywhere
-Dorg.jenkinsci.plugins.gitclient.Git.useJGit=false
# Or use JGit everywhere
-Dorg.jenkinsci.plugins.gitclient.Git.useJGit=true
Verification
Run these on the agent to confirm both stacks see the same CA:
# Command-line Git
GIT_CURL_VERBOSE=1 git ls-remote https://your-internal-git.example.com/repo.git
# JGit (Groovy script console or pipeline step)
org.eclipse.jgit.api.LsRemoteCommand.newInstance()
.setRemote('https://your-internal-git.example.com/repo.git')
.setCredentialsProvider(new org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider('user','token'))
.call()
Check which implementation Jenkins actually uses: Manage Jenkins → System Information → git.client.GitClient shows CliGitAPIImpl (command-line) or JGitAPIImpl.
Assumptions & Uncertainty
- Assumes Jenkins agents run on Linux/Windows/macOS with a standard JVM. Containerized agents with minimal
cacerts may require the custom truststore even for command-line Git if the OS store is empty. - Assumes the corporate CA is a single PEM file. Chained intermediates must be concatenated in order.
- JGit 6.x (bundled in Git Plugin 4.x+) defaults to TLSv1.3; older agents may need
-Djdk.tls.client.protocols=TLSv1.2. - Credential helpers (Git Credential Manager) work only with command-line Git; JGit uses Jenkins' credential store. If you rely on GCM, standardize on command-line Git.
One Diagnostic Detail Needed
Does your environment use a MITM proxy that re-signs certificates with an internal CA, or are you connecting directly to a self-signed Git server? The proxy case requires the proxy CA in both stores; the self-signed case only needs the server's CA. This changes whether you must also update the OS store for non-Jenkins tooling.