Skip to content

Conversation

@doringeman
Copy link
Contributor

@doringeman doringeman commented Dec 12, 2025

Fixes #500.

Add support for corporate proxies that perform SSL interception allowing users to provide a CA certificate file.

The flag is available on install-runner, reinstall-runner, start-runner and restart-runner commands.

When provided, the certificate is:

  • Mounted into the container
  • Appended to the system CA bundle
  • Container is restarted to apply the new CA certificates

Test

  • Run the proxy:
docker run --rm -it --name mitmproxy -p 0.0.0.0:8080:8080 mitmproxy/mitmproxy mitmdump
  • Set HTTP_PROXY and HTTPS_PROXY:
    E.g.,
export HTTP_PROXY=http://172.0.0.1:8080
export HTTPS_PROXY=http://172.0.0.1:8080
  • Get the certificate:
docker cp mitmproxy:/home/mitmproxy/.mitmproxy/mitmproxy-ca-cert.pem ./mitmproxy-ca.crt
  • Install the new CLI of this PR:
make -C cmd/cli install
  • Uninstall DMR:
docker model uninstall-runner
  • Install DMR and provide the path to your proxy certificate:
docker model install-runner --proxy-cert $(pwd)/mitmproxy-ca.crt
Screenshot 2025-12-12 at 17 12 54

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @doringeman, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses the need for Docker Model Runner to operate seamlessly within corporate environments that utilize SSL inspection proxies. By introducing a --proxy-cert flag, users can now provide a custom CA certificate, which the CLI tool then integrates into the running container's trust store. This ensures that network communication originating from the container can be properly inspected and validated by the corporate proxy, resolving connectivity issues in such setups.

Highlights

  • New --proxy-cert flag: Introduced a new --proxy-cert flag to install-runner, reinstall-runner, start-runner, and restart-runner commands. This flag allows users to specify a CA certificate file for environments with SSL inspection.
  • SSL Inspection Support: The provided CA certificate is now mounted into the Docker container, appended to the system's CA bundle (/etc/ssl/certs/ca-certificates.crt), and the container is restarted to ensure the new certificate is applied, enabling support for corporate proxies performing SSL interception.
  • Container Execution as Root: Modified container execution logic to run commands as the root user, which is necessary for appending certificates to the system CA bundle.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Instead of appending the mounted proxy cert directly to /etc/ssl/certs/ca-certificates.crt, consider using the distro-native mechanism (e.g., keeping it in /usr/local/share/ca-certificates and invoking update-ca-certificates) to avoid brittle assumptions about the trust store path and format.
  • The execInContainer helper now always runs commands as root; if only the CA-bundle update needs elevated privileges, consider making the user configurable or adding a dedicated execAsRootInContainer to limit the blast radius of future uses.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Instead of appending the mounted proxy cert directly to `/etc/ssl/certs/ca-certificates.crt`, consider using the distro-native mechanism (e.g., keeping it in `/usr/local/share/ca-certificates` and invoking `update-ca-certificates`) to avoid brittle assumptions about the trust store path and format.
- The `execInContainer` helper now always runs commands as `root`; if only the CA-bundle update needs elevated privileges, consider making the user configurable or adding a dedicated `execAsRootInContainer` to limit the blast radius of future uses.

## Individual Comments

### Comment 1
<location> `cmd/cli/pkg/standalone/containers.go:95` </location>
<code_context>
 	execConfig := container.ExecOptions{
-		Cmd: []string{"sh", "-c", cmd},
+		Cmd:  []string{"sh", "-c", cmd},
+		User: "root",
 	}
 	execResp, err := dockerClient.ContainerExecCreate(ctx, containerID, execConfig)
</code_context>

<issue_to_address>
**🚨 issue (security):** Running all execs as root may be unnecessarily privileged and surprising for containers that define a non-root default user.

This change alters behavior for images that deliberately run as non-root and may violate security expectations by always elevating to root. Please consider limiting root usage to the specific privileged operations that need it (e.g., via an `asRoot` flag or a separate helper), and keep default execs running as the container’s configured user.
</issue_to_address>

### Comment 2
<location> `cmd/cli/pkg/standalone/containers.go:456-470` </location>
<code_context>
 		}
 	}
+
+	// Add proxy certificate to the system CA bundle
+	if created && proxyCert != "" {
+		printer.Printf("Adding proxy certificate to CA bundle...\n")
+		// Append the proxy cert to the system CA bundle
+		appendCmd := "cat " + proxyCertContainerPath + " >> /etc/ssl/certs/ca-certificates.crt"
+		if err := execInContainer(ctx, dockerClient, resp.ID, appendCmd); err != nil {
+			printer.Printf("Warning: failed to add proxy certificate to CA bundle: %v\n", err)
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Appending directly to ca-certificates.crt is brittle and bypasses the distro’s certificate management tooling.

The current `cat ... >> /etc/ssl/certs/ca-certificates.crt` approach:
- Assumes that specific bundle path/format, which can differ across images.
- Skips `update-ca-certificates` (or equivalent), so a future CA regeneration may discard this change.
Given the cert is already mounted under `/usr/local/share/ca-certificates`, consider calling the image’s CA update command (e.g., `update-ca-certificates`) instead of editing the bundle directly for better portability and durability.

```suggestion
	// Add proxy certificate to the system CA bundle
	if created && proxyCert != "" {
		printer.Printf("Updating CA certificates inside container...\n")
		// Ask the image's CA management tooling to pick up the mounted cert from /usr/local/share/ca-certificates
		updateCmd := "if command -v update-ca-certificates >/dev/null 2>&1; then " +
			"update-ca-certificates; " +
			"elif command -v update-ca-trust >/dev/null 2>&1; then " +
			"update-ca-trust extract; " +
			"else " +
			"echo 'No known CA update tool found (tried update-ca-certificates, update-ca-trust)' >&2; " +
			"exit 1; " +
			"fi"

		if err := execInContainer(ctx, dockerClient, resp.ID, updateCmd); err != nil {
			printer.Printf("Warning: failed to update CA certificates inside container: %v\n", err)
		} else {
			// Restart the container so the model-runner process picks up the refreshed CA bundle
			printer.Printf("Restarting container to apply CA certificate...\n")
			if err := dockerClient.ContainerRestart(ctx, resp.ID, container.StopOptions{}); err != nil {
				printer.Printf("Warning: failed to restart container after adding CA certificate: %v\n", err)
			}
		}
	}
```
</issue_to_address>

### Comment 3
<location> `cmd/cli/pkg/standalone/containers.go:325-331` </location>
<code_context>
 		hostConfig.Mounts = append(hostConfig.Mounts, ascendMounts...)
 	}

+	if proxyCert != "" {
+		hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{
+			Type:     mount.TypeBind,
+			Source:   proxyCert,
+			Target:   proxyCertContainerPath,
+			ReadOnly: true,
+		})
+	}
+
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Binding the proxy cert path without validation may produce a non-obvious Docker error if the file is missing or invalid.

If `--proxy-cert` points to a missing or unreadable file, the container will fail to start due to the bind mount, but the CLI will only show a generic startup error. Consider validating the path (existence/readability) before adding the mount so you can return a clearer, targeted error when the certificate path is invalid.

Suggested implementation:

```golang
import (
	"os"

```

```golang
	if proxyCert != "" {
		info, err := os.Stat(proxyCert)
		if err != nil {
			// Fail fast with a clear, targeted error instead of a generic Docker bind error
			return nil, nil, fmt.Errorf("proxy certificate path %q is not accessible: %w", proxyCert, err)
		}
		if !info.Mode().IsRegular() {
			return nil, nil, fmt.Errorf("proxy certificate path %q is not a regular file", proxyCert)
		}

		hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{
			Type:     mount.TypeBind,
			Source:   proxyCert,
			Target:   proxyCertContainerPath,
			ReadOnly: true,
		})
	}

```

Because I cannot see the full function, you will need to:

1. Adjust the `return nil, nil, fmt.Errorf(...)` lines to match the actual return types of the function where this `proxyCert` logic lives.  
   - For example, if the function returns `(config *container.Config, hostConfig *container.HostConfig, err error)`, the `nil, nil, err` form is correct; otherwise, replace the `nil` placeholders appropriately.
2. Ensure `fmt` is imported in this file (if it is not already):
   - Add `fmt` to the import block: `import ("fmt" ... )`.
3. If `os` is already imported, remove the duplicate `os` line from the suggested import change.
4. Keep error messages consistent with the rest of the CLI (e.g. wrapping with your own error type or prefixing with command context if that is the existing pattern).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

execConfig := container.ExecOptions{
Cmd: []string{"sh", "-c", cmd},
Cmd: []string{"sh", "-c", cmd},
User: "root",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): Running all execs as root may be unnecessarily privileged and surprising for containers that define a non-root default user.

This change alters behavior for images that deliberately run as non-root and may violate security expectations by always elevating to root. Please consider limiting root usage to the specific privileged operations that need it (e.g., via an asRoot flag or a separate helper), and keep default execs running as the container’s configured user.

Comment on lines +325 to +331
if proxyCert != "" {
hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{
Type: mount.TypeBind,
Source: proxyCert,
Target: proxyCertContainerPath,
ReadOnly: true,
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Binding the proxy cert path without validation may produce a non-obvious Docker error if the file is missing or invalid.

If --proxy-cert points to a missing or unreadable file, the container will fail to start due to the bind mount, but the CLI will only show a generic startup error. Consider validating the path (existence/readability) before adding the mount so you can return a clearer, targeted error when the certificate path is invalid.

Suggested implementation:

import (
	"os"
	if proxyCert != "" {
		info, err := os.Stat(proxyCert)
		if err != nil {
			// Fail fast with a clear, targeted error instead of a generic Docker bind error
			return nil, nil, fmt.Errorf("proxy certificate path %q is not accessible: %w", proxyCert, err)
		}
		if !info.Mode().IsRegular() {
			return nil, nil, fmt.Errorf("proxy certificate path %q is not a regular file", proxyCert)
		}

		hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{
			Type:     mount.TypeBind,
			Source:   proxyCert,
			Target:   proxyCertContainerPath,
			ReadOnly: true,
		})
	}

Because I cannot see the full function, you will need to:

  1. Adjust the return nil, nil, fmt.Errorf(...) lines to match the actual return types of the function where this proxyCert logic lives.
    • For example, if the function returns (config *container.Config, hostConfig *container.HostConfig, err error), the nil, nil, err form is correct; otherwise, replace the nil placeholders appropriately.
  2. Ensure fmt is imported in this file (if it is not already):
    • Add fmt to the import block: import ("fmt" ... ).
  3. If os is already imported, remove the duplicate os line from the suggested import change.
  4. Keep error messages consistent with the rest of the CLI (e.g. wrapping with your own error type or prefixing with command context if that is the existing pattern).

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a --proxy-cert flag to support SSL inspection by corporate proxies. The changes are well-integrated into the install-runner, reinstall-runner, start-runner, and restart-runner commands. The implementation correctly mounts the user-provided certificate into the container and triggers a restart. My review includes one suggestion to improve the robustness of how the system's CA certificate bundle is updated inside the container, to ensure broader compatibility with different applications.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to use 'docker model pull'

1 participant