Skip to content

Releases: DtxdF/AppJail

v4.10.1

23 Mar 06:00

Choose a tag to compare

Changes between 4.10.0 and 4.10.1

  • Fixed: interaction between from and expose options
    • In appjail-quick(1), when the from and expose options are used together, and even if port rules are added, no rules are loaded. This is because, when from option is used, ports are only exposed if the expose suboption of the container option is used. This is unintended behavior. Now, if the user specifies a port to be forwarded using the expose option, the port is exposed correctly, just as in non-OCI deployments.

Full Changelog: v4.10.0...v4.10.1

v4.10.0

23 Mar 01:16

Choose a tag to compare

Changes between 4.9.1 and 4.10.0

  • Fixed: "umount: unmount of <JAILDIR>/<jail>/jail failed: Device busy":
    • The interaction between nullfs(4) and buildah-mount(1) appears to retain references to vnodes that prevent a clean umount(8). After some time, a clean umount(8) can be performed, but this is not feasible because, first, it would have to be done manually, and second, Director users expect these use cases to be handled automatically. A forced unmount is the only solution in this case and should not pose a problem due to the ephemeral nature of containers, plus we won’t be touching the volumes.
  • Honor exit code when executing a command in appjail-oci(1) exec.

Full Changelog: v4.9.1...v4.10.0

v4.9.1

08 Mar 17:33

Choose a tag to compare

Changes between 4.9.0 and 4.9.1

  • Minor grammar correction in appjail-makejail(1) (thanks to @jmpalacios).
  • Display only the description of ea_<iface>.

Full Changelog: v4.9.0...v4.9.1

v4.9.0

19 Feb 05:30

Choose a tag to compare

Changes between 4.8.0 and 4.9.0

  • Added: support for -j in appjail-{sysrc,service}(1):
    • Added: -j to appjail-sysrc(1).
    • Added: -j to appjail-service(1).
    • Now sysrc(1) and service(1) is executed (by default) from the host but using the -j parameter.
    • Added: -j to SERVICE in appjail-initscript(5).
    • Added: -j to SYSRC in appjail-initscript(5).
    • Added: --jail to SERVICE in appjail-makejail(5).
    • Added: --jexec to SYSRC in appjail-makejail(5).
  • Added: more stuff to bash completion script:
    • Added: x11 subcommand.
    • Added: -e parameter of appjail-cmd(1) jexec.
  • dyndns: Don't exit with a non-zero status when there isn't an IPv4:
    • Currently, it exits with a non-zero exit status when the interface doesn't have an IPv4 address, which may be desirable as a basic check, but the problem arises when the interface exists but has not yet been assigned an IPv4 address, as is the case with interfaces created by Tailscale, which means that the jail will not start.
  • Merged: jexec(8) from upstream:
    • Added: new parameters to appjail-cmd(1) jexec:
      • -w
      • -e
    • Added: new parameters to CMD instruction in appjail-makejail(5):
      • --workdir
      • --env
  • Improved: x11 support:
    • Added: X11 subsection in appjail(1).
    • Added: appjail-x11(1) command.
    • Added: appjail-x11(1) man page.
    • Added: new parameters to appjail.conf(5):
      • X11_XAUTHORITY
      • X11_XRANDR_REFRESH
      • X11_ASSIGN_ALGO
      • X11_FNFS
    • Added: new parameters to appjail-jail(1)'s get:
      • x11_display
      • xephyr_pid
    • Added: lib/x11 library.
  • Convert x11 option to String and add suboptions in appjail-quick(1):
    • The x11 option in appjail-quick(1) is now a string, allowing the user to pass a value. In this case, the purpose is to pass options such as ro or rw to specify whether the directory should be mounted as read-only or read-write, respectively.

Full Changelog: v4.8.0...v4.9.0

v4.8.0

26 Jan 17:40

Choose a tag to compare

Highlights

env, meta and labels

Before env and meta existed in jail(8), I have added appjail-label(1) to add metadata to jails so that they could be used by third-party tools as plugins. There are some tools such as appjail-network(1), Overlord, or AppJail hooks that use them to add more functionality to AppJail.

With this change, the meta and env of jail(8) parameters can also be used, so third-party tools can use them to add more functionality.

For example, Serpico, a security scanner for FreeBSD, uses the meta parameter to select which jails to scan:

# appjail quick scanme start overwrite=force ephemeral virtualnet=":<random> default" nat meta="serpico:1" pkg=python
...
# serpico --category package --scan-jails
...
===> Starting Serpico ( category:package, jail:scanme ) at 2026-01-26 13:28 -04
##!> pkg-audit(8) ( jail:scanme ): [scanme.appjail] Fetching vuln.xml.xz: .......... done
##!> pkg-audit(8) ( jail:scanme ): python311-3.11.14 is vulnerable:
##!> pkg-audit(8) ( jail:scanme ):   python -- several vulnerabilities
##!> pkg-audit(8) ( jail:scanme ):   CVE: CVE-2025-13836
##!> pkg-audit(8) ( jail:scanme ):   CVE: CVE-2025-12084
##!> pkg-audit(8) ( jail:scanme ):   WWW: https://vuxml.FreeBSD.org/freebsd/613d0f9e-d477-11f0-9e85-03ddfea11990.html
##!> pkg-audit(8) ( jail:scanme ):
##!> pkg-audit(8) ( jail:scanme ): 1 problem(s) in 1 package(s) found.
##!> Found 2 vulnerabilities in 'python311' ( 3.11.14 )
{"serpico.package.name": "python311", "serpico.package.version": "3.11.14", "serpico.package.architecture": "amd64", "serpico.package.category": "package", "serpico.vulnerability.title": "CVE-2025-13836 affects python311", "serpico.vulnerability.assigner": "cna@python.org", "serpico.vulnerability.cve": "CVE-2025-13836", "serpico.vulnerability.url": "https://nvd.nist.gov/vuln/detail/CVE-2025-13836", "serpico.vulnerability.published_at": "2025-12-01T18:16:04.200", "serpico.vulnerability.status": "Modified", "serpico.vulnerability.updated": "2026-01-26T15:16:06.210", "serpico.vulnerability.description": "When reading an HTTP response from a server, if no read amount is specified, the default behavior will be to use Content-Length. This allows a malicious server to cause the client to read large amounts of data into memory, potentially causing OOM or other DoS.", "serpico.vulnerability.severity": "MEDIUM", "serpico.vulnerability.score": 6.3, "serpico.package.generated_cpe": ["cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", "cpe:2.3:a:python:python:3.14.0:-:*:*:*:*:*:*", "cpe:2.3:a:python:python:3.15.0:alpha1:*:*:*:*:*:*", "cpe:2.3:a:python:python:3.15.0:alpha2:*:*:*:*:*:*"], "serpico.vulnerability.cve_version": "4.0", "serpico.vulnerability.references": ["https://github.com/python/cpython/commit/14b1fdb0a94b96f86fc7b86671ea9582b8676628", "https://github.com/python/cpython/commit/289f29b0fe38baf2d7cb5854f4bb573cc34a6a15", "https://github.com/python/cpython/commit/4ce27904b597c77d74dd93f2c912676021a99155", "https://github.com/python/cpython/commit/5a4c4a033a4a54481be6870aa1896fad732555b5", "https://github.com/python/cpython/commit/5dc101675fd22918facbbe0fecdc821502beaaf0", "https://github.com/python/cpython/commit/afc40bdd3dd71f343fd9016f6d8eebbacbd6587c", "https://github.com/python/cpython/issues/119451", "https://github.com/python/cpython/pull/119454", "https://mail.python.org/archives/list/security-announce@python.org/thread/OQ6G7MKRQIS3OAREC3HNG3D2DPOU34XO/"], "serpico.vulnerability.cwe_references": ["CWE-125", "CWE-400"], "serpico.vulnerability.cvss.cvss3.base_score": 9.1, "serpico.vulnerability.cvss.cvss3.exploitability_score": 3.9, "serpico.vulnerability.cvss.cvss3.impact_score": 5.2, "serpico.vulnerability.cvss.cvss3.vector.attack_vector": "NETWORK", "serpico.vulnerability.cvss.cvss3.vector.availability": "HIGH", "serpico.vulnerability.cvss.cvss3.vector.confidentiality_impact": "HIGH", "serpico.vulnerability.cvss.cvss3.vector.integrity_impact": "NONE", "serpico.vulnerability.cvss.cvss3.vector.privileges_required": "NONE", "serpico.vulnerability.cvss.cvss3.vector.scope": "UNCHANGED", "serpico.vulnerability.cvss.cvss3.vector.user_interaction": "NONE", "serpico.jail": "scanme", "serpico.package.condition": ["< 3.11.14_1"]}
{"serpico.package.name": "python311", "serpico.package.version": "3.11.14", "serpico.package.architecture": "amd64", "serpico.package.category": "package", "serpico.vulnerability.title": "CVE-2025-12084 affects python311", "serpico.vulnerability.assigner": "cna@python.org", "serpico.vulnerability.cve": "CVE-2025-12084", "serpico.vulnerability.url": "https://nvd.nist.gov/vuln/detail/CVE-2025-12084", "serpico.vulnerability.published_at": "2025-12-03T19:15:55.050", "serpico.vulnerability.status": "Modified", "serpico.vulnerability.updated": "2026-01-26T15:16:05.950", "serpico.vulnerability.description": "When building nested elements using xml.dom.minidom methods such as appendChild() that have a dependency on _clear_id_cache() the algorithm is quadratic. Availability can be impacted when building excessively nested documents.", "serpico.vulnerability.severity": "MEDIUM", "serpico.vulnerability.score": 6.3, "serpico.package.generated_cpe": ["cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", "cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", "cpe:2.3:a:python:python:3.15.0:alpha1:*:*:*:*:*:*", "cpe:2.3:a:python:python:3.15.0:alpha2:*:*:*:*:*:*"], "serpico.vulnerability.cve_version": "4.0", "serpico.vulnerability.references": ["https://github.com/python/cpython/commit/027f21e417b26eed4505ac2db101a4352b7c51a0", "https://github.com/python/cpython/commit/08d8e18ad81cd45bc4a27d6da478b51ea49486e4", "https://github.com/python/cpython/commit/27648a1818749ef44c420afe6173af6868715437", "https://github.com/python/cpython/commit/41f468786762348960486c166833a218a0a436af", "https://github.com/python/cpython/commit/57937a8e5e293f0dcba5115f7b7a11b1e0c9a273", "https://github.com/python/cpython/commit/8d2d7bb2e754f8649a68ce4116271a4932f76907", "https://github.com/python/cpython/commit/9c9dda6625a2a90d2a06c657eee021d6be19842d", "https://github.com/python/cpython/commit/a46c10ec9d4050ab67b8a932e0859a2ea60c3cb8", "https://github.com/python/cpython/commit/a696ba8b4d42fd632afc9bc88ad830a2e4cceed8", "https://github.com/python/cpython/commit/c97e87593063d84a2bd9fe7068b30eb44de23dc0", "https://github.com/python/cpython/commit/ddcd2acd85d891a53e281c773b3093f9db953964", "https://github.com/python/cpython/commit/e91c11449cad34bac3ea55ee09ca557691d92b53", "https://github.com/python/cpython/issues/142145", "https://github.com/python/cpython/pull/142146"], "serpico.vulnerability.cwe_references": ["CWE-407"], "serpico.vulnerability.cvss.cvss3.base_score": 5.3, "serpico.vulnerability.cvss.cvss3.exploitability_score": 3.9, "serpico.vulnerability.cvss.cvss3.impact_score": 1.4, "serpico.vulnerability.cvss.cvss3.vector.attack_vector": "NETWORK", "serpico.vulnerability.cvss.cvss3.vector.availability": "LOW", "serpico.vulnerability.cvss.cvss3.vector.confidentiality_impact": "NONE", "serpico.vulnerability.cvss.cvss3.vector.integrity_impact": "NONE", "serpico.vulnerability.cvss.cvss3.vector.privileges_required": "NONE", "serpico.vulnerability.cvss.cvss3.vector.scope": "UNCHANGED", "serpico.vulnerability.cvss.cvss3.vector.user_interaction": "NONE", "serpico.jail": "scanme", "serpico.package.condition": ["< 3.11.14_1"]}
##!> Serpico done: found 2 vulnerabilities in 16.5799 seconds

OCI containers, brandelf and environment

Currently, to define a new environment variable or modify an existing one, we need to use env(1), which may or may not be available inside the jail, especially in OCI containers created with the scratch layer (i.e., those containers that are only a single static binary, plus configuration files and related stuff). With this option, we can specify environment variables of arbitrary length for the specified process running inside the jail. This has also been added to upstream: https://reviews.freebsd.org/D54660

Another improvement related to OCI is the addition of the brandelf and brandelf_abi options to appjail-quick(1).

Some OCI containers are just a single, static binary, so FreeBSD may misdetect the ABI of that binary, preventing it from running until we run brandelf(1). To automate this step, I have added the aforementioned options to appjail-quick(1).

# appjail oci run -o start -o overwrite=force -o alias -o ip4_disable -o ip6_disable -o template=/usr/local/share/examples/appjail/templates/minimal.conf -o linuxfs -o device='include $devfsrules_hide_all' -o device='include $devfsrules_unhide_basic' -o device='include $devfsrules_unhide_login' -o device='path shm unhide' -o device="path 'shm/*' unhide" -o container="args:--platform=linux/amd64" -o ephemeral -o brandelf="/hello" docker.io/hello-world:linux hello-world
...
[00:00:10] [ debug ] [hello-world] Executing:  /usr/local/libexec/appjail/jexec/jexec -l -w "/" -e "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"  -- "hello-world"  "/hello"

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Changes betwe...

Read more

v4.7.1

23 Dec 21:39

Choose a tag to compare

Changes between 4.7.0 and 4.7.1

  • Fixed: jail: <jail>: negative jid:
    • When the -j flag is not specified in appjail-makejail(1), a random name is generated for the jail. This random name may be a number that causes problems with jail(8). This is similar to a problem in Director that generates the error the name cannot be numeric (unless it is the jid), but in this case, the error is jail: <jail>: negative jid. The solution is simply to check whether the generated name is numeric and, if so, generate it again until it contains at least one letter (since it is actually a hexadecimal number).

Full Changelog: v4.7.0...v4.7.1

v4.7.0

22 Dec 05:36

Choose a tag to compare

Changes between 4.6.0 and 4.7.0

  • Added: dyndns hook:
    • My intention with this hook is to create an alternative to SkyDNS implemented in Overlord, but in a much simpler way and avoiding deploying an etcd cluster. Unlike tools such as dns/dynip (or a combination of cron(8) and fetch(1)) that periodically update A/AAAA records, this hook is only implemented to update A records at deployment, not periodically, so it is assumed that the IP address does not change frequently or even at all (in my case, tailscale).

Full Changelog: v4.6.0...v4.7.0

v4.6.0

13 Nov 22:19

Choose a tag to compare

Changes between 4.5.0 and 4.6.0

  • Use -n flag in route(8) when EXT_IF isn't set:
    • Don't resolve host and network names symbolically when reporting actions (such as the default gateway), which is time consuming, and may require correct operation of the network.

Full Changelog: v4.5.0...v4.6.0

v4.5.0

06 Nov 16:55

Choose a tag to compare

Changes between 4.4.0 and 4.5.0

  • Added: examples for hooks:
    • Added: history hook.
  • Added: security-group hook.
  • Added: security-table hook.

Full Changelog: v4.4.0...v4.5.0

v4.4.0

16 Oct 20:00

Choose a tag to compare

Changes between 4.3.1 and 4.4.0

  • Added: import suboption to container option in appjail-quick(1).

Full Changelog: v4.3.1...v4.4.0