⚠️ 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 …ranjexec "192.0.2.10"and failed withjail not found. ansible_jail_usernow usesjexec -U(the jail's password database) instead of-u(the host's).fetch_fileuses privilege escalation, so root-only files inside the jail are fetchable; staged withumask 077.- Internal commands pass
sudoable=False, avoiding become-prompt hangs and needless pty allocation.
Changed / deprecated
- Transfers run as
ansible_jail_userinside the jail (usebecomefor root-owned paths). - Host-side privilege now only needs a single
jexecdoas/sudo rule; thejls/mkdir/mv/rmrules can be removed. - The
jlsjail-root probe is gone.ansible_jail_rootis 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.