wasmerio/wasmer · error
{} is world writable and not sticky ({m:?})
Error message
{} is world writable and not sticky ({m:?}) What it means
As part of `seccheck` for the `binfmt register` flow, wasmer refuses to register an interpreter whose path (or a parent) is world-writable and lacks the sticky bit, because a local attacker could replace the binary and gain execution via binfmt. `anyhow::ensure!` raises this error when `is_allowed(Other, Write, mode)` is true and `is_sticky(mode)` is false.
Source
Thrown at lib/cli/src/commands/binfmt.rs:55
#[clap(subcommand)]
action: Action,
}
// Quick safety check:
// This folder isn't world writable (or else its sticky bit is set), and neither are its parents.
//
// If somebody mounted /tmp wrong, this might result in a TOCTOU problem.
fn seccheck(path: &Path) -> Result<()> {
if let Some(parent) = path.parent() {
seccheck(parent)?;
}
let m = std::fs::metadata(path)
.with_context(|| format!("Can't check permissions of {}", path.to_string_lossy()))?;
use unix_mode::*;
anyhow::ensure!(
!is_allowed(Accessor::Other, Access::Write, m.mode()) || is_sticky(m.mode()),
"{} is world writable and not sticky ({m:?})",
path.to_string_lossy()
);
Ok(())
}
impl Binfmt {
/// The filename used to register the wasmer CLI as a binfmt interpreter.
pub const FILENAME: &'static str = "wasmer-binfmt-interpreter";
/// execute [Binfmt]
pub fn execute(&self) -> Result<()> {
if !self.binfmt_misc.exists() {
bail!("{} does not exist", self.binfmt_misc.to_string_lossy());
}
let temp_dir;
let specs = match self.action {
Register | Reregister => {
temp_dir = tempfile::Builder::new()
.permissions(Permissions::from_mode(0o1755))View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Tighten the offending path's permissions: `chmod o-w <path>` (e.g. make it 0755) for the binary and each parent directory.
- Alternatively set the sticky bit if the directory must remain group/other writable: `chmod +t <dir>`.
- Move/reinstall wasmer into a root-owned, non-world-writable location such as /usr/local/bin.
- Re-run `wasmer binfmt register` after the permission change.
Example fix
// before (fails) chmod 0777 /opt/wasmer/bin && wasmer binfmt register /opt/wasmer/bin/wasmer // after chmod 0755 /opt/wasmer/bin wasmer binfmt register /opt/wasmer/bin/wasmer
Defensive patterns
Strategy: validation
Validate before calling
use std::os::unix::fs::PermissionsExt;
fn is_world_writable_no_sticky(p: &Path) -> bool {
std::fs::metadata(p)
.map(|m| {
let mode = m.permissions().mode();
mode & 0o002 != 0 && mode & 0o1000 == 0
})
.unwrap_or(false)
}
if is_world_writable_no_sticky(Path::new("/opt/wasmer/bin/wasmer")) {
eprintln!("chmod o-w the binary and its parents before registering");
} Type guard
fn has_safe_mode(m: &std::fs::Metadata) -> bool {
let mode = m.permissions().mode();
mode & 0o002 == 0 || mode & 0o1000 != 0
} Try / catch
match binfmt_execute(path) {
Err(e) if e.to_string().contains("world writable and not sticky") => {
eprintln!("Run `chmod o-w <path>` (or `chmod +t <dir>`) and retry");
}
other => other?,
} Prevention
- Install wasmer with 0755 perms and root ownership.
- Avoid world-writable install directories; check `ls -ld` on every path component.
- Set a restrictive umask (022) before installing.
- On shared dirs that must be writable, ensure the sticky bit is set.
When it happens
Trigger: Running `wasmer binfmt register` where the wasmer binary or any of its parent directories has mode bits allowing 'other' write (e.g. 0777, 0775-with-other-write) without the sticky bit (no 01000 bit).
Common situations: wasmer installed under /home/user with a home directory of 0777; a shared/tmp-like install directory (e.g. /usr/local/share mounted 1777-without-sticky, or 0777); permissive umask misconfiguration; multi-user servers where admins hardened nothing.
Related errors
- Can't check permissions of {}
- cannot create debug directory: {}
- cannot create debug directory: {}
- state::get_inode_at_path for buffers
- state::get_inode_at_path unknown file type: not file, direct
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/a79ff7fb76759e3b.
Report an issue: GitHub.