GHSA-6jcq-6546-qrrw: PraisonAI SandlockSandbox falls back to unrestricted subprocess execution when Landlock is unavailable
Summary`praisonai.sandbox.SandlockSandbox` is documented and implemented as the kernel-enforced sandbox backend for untrusted code. Its `SandboxConfig.native()` path lets callers configure allowed filesystem paths and `network=False`.On systems where the optional `sandlock` module imports but reports that Landlock is unavailable, `SandlockSandbox.execute()` and `run_command()` do not fail closed. They silently fall back to `SubprocessSandbox(self.config)`.That fallback keeps the same high-level native policy object but does not enforce the native filesystem or network boundary during code execution. A sandboxed payload can read files outside the configured allowed path and open network connections despite `network=False`.Technical Details`SandboxConfig.native()` creates a restricted native policy and records caller-provided writable paths plus the requested network posture:`SandlockSandbox` builds the intended kernel policy with Landlock-backed filesystem allowlisting and network denial:However, both execution paths fail open when Sandlock is unavailable:`SubprocessSandbox.execute()` writes the code to a temp file and runs `python` with a minimal environment and POSIX rlimits. It does not install a filesystem sandbox, network namespace, syscall filter, chroot, Landlock policy, or path allowlist for the code execution path. The `safe_sandbox_path()` checks only protect the `read_file()`, `write_file()`, and `list_files()` helper methods.Why This Is Not Intended BehaviorThe report is not based only on a trust-model disagreement. The code and docs define a concrete boundary:PraisonAI's Sandlock README says the backend provides kernel-level filesystem allowlisting, network isolation, seccomp filtering, and blocks `/etc/passwd`, SSH keys, AWS credentials, and unauthorized connections.The security demo creates `SandboxConfig.native(writable_paths=["./safe_workspace"], network=False)` and labels file and network access as blocked operations.The upstream `sandlock` package requires Linux with a compatible Landlock ABI and documents a fail-closed default for missing required protections unless the caller explicitly opts into degraded protection.PraisonAI's own current security page recommends sandboxed execution and says path traversal protection is enabled by default for local sandbox backends.The bug is the silent fallback from an unavailable kernel-enforced boundary to plain subprocess execution without preserving the configured native policy.PoVRun from a PraisonAI source checkout:The PoV:injects a fake `sandlock` module that imports successfully but reports no usable Landlock support;configures `SandboxConfig.native(writable_paths=[tenant_a], network=False)`;creates `tenant-b-secret.txt` outside the configured path;starts a localhost TCP listener;executes code through `SandlockSandbox.execute()`.Observed result on `v4.6.58`:This proves both policy boundaries are crossed:the file read target is not under the configured allowed path;the localhost network connection succeeds even though the native policy was created with `network=False`.Full PoV script:PoCThe PoV section above contains the local reproduction command, input, and decisive output.ImpactIf a PraisonAI user or service relies on `SandlockSandbox` / native sandboxing for untrusted code isolation on a host without the required Landlock support, code submitted to the sandbox can execute with the host user's normal filesystem and network access.Concrete impact includes:reading files outside the configured tenant/workspace path;reading project files, credentials, `.env` files, SSH material, or cloud config reachable by the PraisonAI process user;connecting to loopback or internal services despite `network=False`;moving from sandboxed code execution to unsandboxed host-user code execution in deployments that treat Sandlock as the isolation boundary.The local PoV does not read real sensitive files or contact external systems. It uses temporary tenant directories and a localhost TCP listener.Suggested FixFail closed when the requested native sandbox boundary cannot be enforced.Recommended changes:In `SandlockSandbox.execute()` and `run_command()`, return a failed `SandboxResult` or raise a clear runtime error when `self.is_available` is false.If fallback behavior is kept for developer convenience, require an explicit opt-in such as `allow_degraded=True` or `fallback="subprocess"` and surface that degraded state in the result metadata.Do not preserve `sandbox_type == "sandlock"` in status metadata when the actual execution backend is subprocess.Add regression tests proving that unavailable Landlock does not execute code unless degraded fallback was explicitly requested.Add tests that a native policy with `network=False` and a restricted path cannot read outside-path canaries or connect to a localhost listener.Document the required kernel/ABI versions and the exact degraded-mode semantics.Affected Package/VersionsRepository: `MervinPraison/PraisonAI`Package: `praisonai`Component: `src/praisonai/praisonai/sandbox/sandlock.py`Related config component: `src/praisonai-agents/praisonaiagents/sandbox/config.py`Latest verified release/current head: `v4.6.58`, `1ad58ca02975ff1398efeda694ea2ab78f20cf3e`Confirmed affected:Negative control:Suggested affected range: `>= 4.5.110, <= 4.6.58`.No fixed version is known at submission time.Version SweepGitHub history for `sandlock.py` shows the backend was introduced in `4ee7d298c89f` on 2026-04-01 with "graceful fallback to SubprocessSandbox", then updated in `7ae6c6d19c31` on 2026-04-02 to use the current Landlock ABI check.Advisory HistoryNearby advisories are distinct:`GHSA-r4f2-3m54-pp7q` / `CVE-2026-34955`: `SubprocessSandbox` shell command escape through `4.5.96`.`GHSA-4mr5-g6f9-cfrh`, `GHSA-qf73-2hrx-xprp`, `GHSA-6vh2-h83c-9294`: `execute_code()` Python sandbox escapes.`GHSA-ch89-h4r2-c8f8`: agent tools workspace escape via symlinks.`GHSA-gcq3-mfvh-3x25`: PraisonAI Code agent tool workspace fail-open.This report covers a different root cause: `SandlockSandbox` / native sandbox policy downgrade when Landlock is unavailable. It reproduces on the latest release `v4.6.58`, while the older `SubprocessSandbox` shell escape advisory was fixed at `4.5.97`.
CVSS v3.1: 8.8