Skip to content

v2.0.0 — Security release: jail-escape fix

Latest

Choose a tag to compare

@chofstede chofstede released this 10 Jun 08:49
· 1 commit to main since this release
v2.0.0
d0d9127

⚠️ Security release. All versions prior to 2.0.0 contain a jail-escape vulnerability in file transfers. Upgrading is strongly recommended. See the advisory.

Security fix

put_file previously resolved the destination to a host-side path (<jail_root>/<dest>) and ran mkdir -p / mv there as root. Those commands follow symlinks, so a compromised jail could plant a symlink to redirect a privileged write onto an arbitrary host file — escaping the jail. Transfers now run inside the jail via jexec, confining all path resolution to the jail's chroot.

Other fixes

  • Default jail name is the inventory hostname, not the connection address. Previously web ansible_host=192.0.2.10 … ran jexec "192.0.2.10" and failed with jail not found.
  • ansible_jail_user now uses jexec -U (the jail's password database) instead of -u (the host's).
  • fetch_file uses privilege escalation, so root-only files inside the jail are fetchable; staged with umask 077.
  • Internal commands pass sudoable=False, avoiding become-prompt hangs and needless pty allocation.

Changed / deprecated

  • Transfers run as ansible_jail_user inside the jail (use become for root-owned paths).
  • Host-side privilege now only needs a single jexec doas/sudo rule; the jls/mkdir/mv/rm rules can be removed.
  • The jls jail-root probe is gone. ansible_jail_root is deprecated and ignored (warns when set).

Upgrading

For the common ansible_jail_user=root setup, no inventory changes are needed beyond trimming doas/sudoers to the single jexec rule. See the "Upgrading from 1.x" section in the README.

Verification

88 unit tests at 100% coverage; black/isort/flake8/bandit clean across Python 3.9–3.12 × ansible-core 2.14–2.17, plus an integration smoke test that round-trips a file through copy/slurp/fetch against a real FreeBSD 15.0 jail.

Full details in the CHANGELOG.