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

  1. Tighten the offending path's permissions: `chmod o-w <path>` (e.g. make it 0755) for the binary and each parent directory.
  2. Alternatively set the sticky bit if the directory must remain group/other writable: `chmod +t <dir>`.
  3. Move/reinstall wasmer into a root-owned, non-world-writable location such as /usr/local/bin.
  4. 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

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


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/a79ff7fb76759e3b. Report an issue: GitHub.