Repository navigation
1.5.0
Run containers as a dedicated user, safely: securityContext for dc-docker.yml, a hardened agent file system, strict config parsing, and every open dependency CVE closed.
Upgrade notes (read before rolling out)
- Unknown or duplicate keys in
dc-docker.ymlare now errors (#75). A typo such asreadOnly:orreadOnlyRootFilesysem:used to be ignored silently, which turned a protection off. After upgrading, runDOCKER_CHECKfor every service: each stray key is listed with its path and the closest known name. nameindc-docker.ymlmust be a docker container name ([a-zA-Z0-9][a-zA-Z0-9_.-]*). Any other name already faileddocker run --name=.TEMP_DIRmust be on a path only root can change. A sticky/tmpis fine. The agent refuses an unsafeTEMP_DIRbefore extracting anything.- New agent parameter
CONTAINER_RUNTIME(podmanby default, ordocker). It only matters forsecurityContext.passwdEntry. Setdockeron hosts with real Docker before using it; the agent refuses a mismatch withdocker --version. save-artifact: thex-dc-agent-file-extensionheader must be a plain extension (e.g.tar.gz). A missing or blank header still falls back to the configuredextension.
Containers as a user (securityContext)
runAsUser/runAsGroup→--user U:GreadOnlyRootFilesystem→--read-onlyallowPrivilegeEscalation: false→--security-opt no-new-privilegesdirectoryOrCreatevolumes getowner(runAsor{user, group}) andmode. These are applied behind a write-path preflight that checks every path the root agent writes, for CHECK and PUSH alike (#74).passwdEntrygives a UID that is not in the image a passwd entry, the way imagekit'sruntime.passwd_entrydoes, so Java gets a realuser.nameand a writableuser.home. Podman receives its own--passwd-entry; with docker the agent mounts a small generatedcontainer-passwdread-only over/etc/passwd. The host's/etc/passwdis never used.tmpfs→--tmpfs <path>[:<options>], e.g. a writable/tmpunder--read-only.
Security fixes
- Local privilege escalation via a predictable work dir: tasks were extracted into
/tmp/docker-<name>-<ms>, created non-exclusively, so a local user could pre-create it and swapdc-docker.ymlor steer root's writes. The work dir is now created exclusively with mode0700and a random suffix, under aTEMP_DIRwhose whole path is checked first. - Deleting trees no longer follows symbolic links (#76). On Linux the deletion goes through
SecureDirectoryStream, relative to open directory descriptors. save-artifact: the api-key is now checked before anything touches the disk; before, a request without a key made the root agent create arbitrary directories. The stored file must stay insidedir, and the header extension is validated.- Operator: HTML auto-escaping in the FreeMarker templates (reflected/stored XSS).
dc-docker.ymlnamecan no longer place the service directory outsideSERVICES_DEFINITION_DIR.
Dependencies
- FreeMarker 2.3.35 (CVE-2026-84939), Jetty 12.1.13 (CVE-2026-19203, CVE-2026-19204), logback 1.6.4 (CVE-2026-19880), plus slf4j, jgit, guava, handlebars and snakeyaml-engine updates.
- Docs site on pnpm 10 with
minimumReleaseAge; all website dependency alerts closed. - Build: Maven 3.9.16 through a script-only wrapper with a checksum; surefire pinned. CI: CodeQL Action v4.
Full docs: https://evsinev.github.io/dc-agent/