CVE-2022-39206 (Java, published 2022-09-13T19:15Z)
Description: value: Onedev is an open source, self-hosted Git Server with CI/CD and Kanban. When using Docker-based job executors, the Docker socket (e.g. /var/run/docker.sock on Linux) is mounted into each Docker step. Users that can define and trigger CI/CD jobs on a project could use this to control the Docker daemon on the host machine. This is a known dangerous pattern, as it can be used to break out of Docker containers and, in most cases, gain root privileges on the host system. This issue allows regular (non-admin) users to potentially take over the build infrastructure of a OneDev instance. Attackers need to have an account (or be able to register one) and need permission to create a project. Since code.onedev.io has the right preconditions for this to be exploited by remote attackers, it could have been used to hijack builds of OneDev itself, e.g. by injecting malware into the docker images that are built and pushed to Docker Hub. The impact is increased by this as described before. Users are advised to upgrade to 7.3.0 or higher. There are no known workarounds for this issue.
Severity: nan (CVSS v3 base score: 9.9)
Weakness: CWE-610 \u2014 Externally Controlled Reference to a Resource in Another Sphere
The product uses an externally controlled name or reference that resolves to a resource that is outside of the intended control sphere.
Repository: https://github.com/theonedev/onedev
Files changed:
pom.xml
server-core/src/main/java/io/onedev/server/migration/DataMigrator.java
server-plugin/server-plugin-executor-kubernetes/src/main/java/io/onedev/server/plugin/executor/kubernetes/KubernetesExecutor.java
server-plugin/server-plugin-executor-remotedocker/src/main/java/io/onedev/server/plugin/executor/remotedocker/RemoteDockerExecutor.java
server-plugin/server-plugin-executor-serverdocker/src/main/java/io/onedev/server/plugin/executor/serverdocker/ServerDockerExecutor.java
server-product/system/incompatibilities/incompatibilities.md
Commit message: Fix the docker sock mount security vulnerability

Vulnerable code:
		<agent.version>1.3.7</agent.version>
				commonVolumeMounts.add(dockerSockMount);
				commonVolumeMounts.add(containerdSockMount);
				volumes.add(CollectionUtils.newLinkedHashMap(
						"name", "docker-sock", 
						"hostPath", CollectionUtils.newLinkedHashMap(
								"path", dockerSock)));
				volumes.add(CollectionUtils.newLinkedHashMap(
						"name", "containerd-sock", 
						"hostPath", CollectionUtils.newLinkedHashMap(
								"path", containerdSock)));
						jobContext.getActions(), jobContext.getRetried(), services, registryLogins, 
						trustCertContent, getRunOptions());
										if (SystemUtils.IS_OS_WINDOWS) 
											docker.addArgs("-v", "//./pipe/docker_engine://./pipe/docker_engine");
										else
											docker.addArgs("-v", "/var/run/docker.sock:/var/run/docker.sock");

Fixed code:
		<agent.version>1.3.8</agent.version>
	private void migrate87(File dataDir, Stack<Integer> versions) {
		for (File file: dataDir.listFiles()) {
			if (file.getName().startsWith("Settings.xml")) {
				VersionedXmlDoc dom = VersionedXmlDoc.fromFile(file);
				for (Element element: dom.getRootElement().elements()) {
					String key = element.elementTextTrim("key");
					if (key.equals("JOB_EXECUTORS")) {
						Element valueElement = element.element("value");
						if (valueElement != null) {
							for (Element executorElement: valueElement.elements()) {
								if (executorElement.getName().contains("DockerExecutor")) 
									executorElement.addElement("mountDockerSock").setText("false");
								else if (executorElement.getName().contains("KubernetesExecutor")) 
									executorElement.addElement("mountContainerSock").setText("false");
							}
						}						
					}
				}
				dom.writeToFile(file, false);
			}
		}
	}
	
	private boolean mountContainerSock;
	
	
	@Editable(order=300, description="Whether or not to mount docker/containerd sock into job "
			+ "container to support container operations in job commands, for instance to build "
			+ "container image.<br>"
			+ "<b class='text-danger'>WARNING</b>: Malicious jobs can take control of k8s node "
			+ "running the job by operating the mounted container sock. You should configure job "
			+ "requirement option below to make sure the executor can only be used by trusted "
			+ "jobs if this option is enabled")
	public boolean isMountContainerSock() {
		return mountContainerSock;
	}

	public void setMountContainerSock(boolean mountContainerSock) {
		this.mountContainerSock = mountContainerSock;
	}
				
				if (isMountContainerSock()) {
					commonVolumeMounts.add(dockerSockMount);
					commonVolumeMounts.add(containerdSockMount);
				}
				
				if (isMountContainerSock()) {
					volumes.add(CollectionUtils.newLinkedHashMap(
							"name", "docker-sock", 
							"hostPath", CollectionUtils.newLinkedHashMap(
									"path", dockerSock)));
					volumes.add(CollectionUtils.newLinkedHashMap(
							"name", "containerd-sock", 
							"hostPath", CollectionUtils.newLinkedHashMap(
									"path", containerdSock)));
				}
	private boolean mountDockerSock;
	
	@Editable(order=400, description="Whether or not to mount docker sock into job container to "
			+ "support docker operations in job commands, for instance to build docker image.<br>"
			+ "<b class='text-danger'>WARNING</b>: Malicious jobs can take control of the agent "
			+ "running the job by operating the mounted docker sock. You should configure job "
			+ "requirement option below to make sure the executor can only be used by trusted "
			+ "jobs if this option is enabled")
	public boolean isMountDockerSock() {
		return mountDockerSock;
	}

	public void setMountDockerSock(boolean mountDockerSock) {
		this.mountDockerSock = mountDockerSock;
	}
	
						jobContext.getActions(), jobContext.getRetried(), services, registryLogins,
						mountDockerSock, trustCertContent, getRunOptions());
	private boolean mountDockerSock;
	
	@Editable(order=500, description="Whether or not to mount docker sock into job container to "
			+ "support docker operations in job commands, for instance to build docker image.<br>"
			+ "<b class='text-danger'>WARNING</b>: Malicious jobs can take control of whole OneDev "
			+ "by operating the mounted docker sock. You should configure job requirement "
			+ "option below to make sure the executor can only be used by trusted jobs if this "
			+ "option is enabled")
	public boolean isMountDockerSock() {
		return mountDockerSock;
	}

	public void setMountDockerSock(boolean mountDockerSock) {
		this.mountDockerSock = mountDockerSock;
	}

										if (isMountDockerSock()) {
											if (SystemUtils.IS_OS_WINDOWS) 
												docker.addArgs("-v", "//./pipe/docker_engine://./pipe/docker_engine");
											else
												docker.addArgs("-v", "/var/run/docker.sock:/var/run/docker.sock");
										}
# 7.3.0
1. [CI/CD] Docker sock is mounted by default for server docker executor, remote docker executor and Kubernetes 
executor for security reasons. If your CI job performs docker operation, the build may fail. You may enable 
the mount docker sock option in related executors, but make sure to configure job requirement of the executor 
to only allow trusted jobs to use the executors