You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
OpenShell version tested: source-level review of main at 8cf2673c (local CLI on PATH is 0.0.72, but the finding is read from current main, not from a running sandbox)
Latest release checked: v0.0.86 (gh release list) — the code path below is unchanged on main as of this commit
Known fixes reviewed: searched main for every hard_requirement reference (16 hits); the only string comparison is the one below, and no validation exists in openshell-policy or openshell-server/src/grpc/validation.rs
Findings: LandlockDef.compatibility is deserialized as a bare String with no value validation. The proto→runtime conversion is a single equality check against "hard_requirement", with everything else falling through to BestEffort.
Remaining reason for filing: the failure direction is always toward less enforcement. A typo in a security-relevant field produces a sandbox that reads as strictly configured but runs permissively, with no error, warning, or log line.
Description
Actual behavior: Any value of landlock.compatibility other than the exact string hard_requirement is silently treated as best_effort. A policy containing compatibility: hard-requirement (hyphen), compatibility: strict, or compatibility: HARD_REQUIREMENT is accepted without complaint and runs in best_effort mode — meaning Landlock failures degrade to no filesystem restriction instead of aborting startup.
#[serde(deny_unknown_fields)] catches unknown keys, so landlock: { compatibilty: ... } is rejected. It does nothing for unknown values.
Expected behavior: An unrecognized compatibility value is rejected at policy parse/validation time with an error naming the field and the accepted values. Fail closed on a security control, or at minimum emit a warning — never silently downgrade enforcement.
On a host where Landlock is unavailable or a listed path cannot be opened, the sandbox starts anyway with reduced (or zero) filesystem restriction, rather than aborting as hard_requirement would.
Environment
OS: Linux 6.17 (x86_64)
Docker: n/a — source-level finding, reproducible on any driver
Parse into the existing LandlockCompatibility enum rather than a String, either via #[serde(rename_all = "snake_case")] on the enum or a TryFrom<&str> that errors on unrecognized input, and surface that error through gateway policy validation. Docs enumerate exactly two accepted values (docs/reference/policy-schema.mdx:92), so tightening the parser matches documented behavior rather than changing it.
Related
A second, separate gap found alongside this one: when both filesystem_policy.read_only and read_write are empty, prepare() returns Ok(None) and Landlock is a complete no-op even under hard_requirement (crates/openshell-supervisor-process/src/sandbox/linux/landlock.rs:145-147). Arguably hard_requirement with no paths should be a configuration error. Filing separately if maintainers agree it is distinct.
Agent Diagnostic
create-github-issuemainat8cf2673c(local CLI on PATH is 0.0.72, but the finding is read from currentmain, not from a running sandbox)gh release list) — the code path below is unchanged onmainas of this commitmainfor everyhard_requirementreference (16 hits); the only string comparison is the one below, and no validation exists inopenshell-policyoropenshell-server/src/grpc/validation.rslandlockand forcompatibility validation policy. Closest is supervisor: Landlock hard_requirement aborts with "incompatible directory-only access-rights: ReadDir" for real directories on RHEL 9.6 (kernel 5.14) ABI #2218 (Landlockhard_requirementaborting on RHEL 9.6 kernel 5.14 ABI), which is about ABI compatibility, not value parsing. No duplicate found.LandlockDef.compatibilityis deserialized as a bareStringwith no value validation. The proto→runtime conversion is a single equality check against"hard_requirement", with everything else falling through toBestEffort.Description
Actual behavior: Any value of
landlock.compatibilityother than the exact stringhard_requirementis silently treated asbest_effort. A policy containingcompatibility: hard-requirement(hyphen),compatibility: strict, orcompatibility: HARD_REQUIREMENTis accepted without complaint and runs inbest_effortmode — meaning Landlock failures degrade to no filesystem restriction instead of aborting startup.#[serde(deny_unknown_fields)]catches unknown keys, solandlock: { compatibilty: ... }is rejected. It does nothing for unknown values.Expected behavior: An unrecognized
compatibilityvalue is rejected at policy parse/validation time with an error naming the field and the accepted values. Fail closed on a security control, or at minimum emit a warning — never silently downgrade enforcement.Reproduction Steps
hard_requirementwould.Environment
main@8cf2673clandlockandcompatibility validation policy; supervisor: Landlock hard_requirement aborts with "incompatible directory-only access-rights: ReadDir" for real directories on RHEL 9.6 (kernel 5.14) ABI #2218 is related but distinct (ABI compatibility, not value parsing)Logs
Parsing accepts any string:
The only place the value is interpreted — everything that is not an exact match falls through to
BestEffort:Suggested Fix
Parse into the existing
LandlockCompatibilityenum rather than aString, either via#[serde(rename_all = "snake_case")]on the enum or aTryFrom<&str>that errors on unrecognized input, and surface that error through gateway policy validation. Docs enumerate exactly two accepted values (docs/reference/policy-schema.mdx:92), so tightening the parser matches documented behavior rather than changing it.Related
filesystem_policy.read_onlyandread_writeare empty,prepare()returnsOk(None)and Landlock is a complete no-op even underhard_requirement(crates/openshell-supervisor-process/src/sandbox/linux/landlock.rs:145-147). Arguablyhard_requirementwith no paths should be a configuration error. Filing separately if maintainers agree it is distinct.