Hmbown/CodeWhale · error · anyhow::Error

refusing unauthenticated app-server bind on non-loopback add

Error message

refusing unauthenticated app-server bind on non-loopback address

What it means

During plugin review on Windows, open_bundle_file opens bundle files with FILE_FLAG_OPEN_REPARSE_POINT and a deny-write share mode, then requires a regular file, no FILE_ATTRIBUTE_REPARSE_POINT, and exactly one link (windows_file_identity). A symlinked leaf, a hard-linked file, or a non-file is rejected with InvalidData; the sharing mode also blocks replacement while the file is hashed.

Source

Thrown at crates/app-server/src/lib.rs:694

        stdio_bridge: Arc::new(Mutex::new(None)),
        stdio_thread_hints: Arc::new(Mutex::new(HashMap::new())),
        pending_user_input: Arc::new(Mutex::new(std::collections::HashMap::new())),
        in_flight_turns: Arc::new(Mutex::new(HashMap::new())),
    })
}

fn resolve_auth_token(options: &AppServerOptions) -> Result<Option<String>> {
    let configured = options.auth_token.as_ref().map(|token| token.trim());
    if let Some(token) = configured
        && token.is_empty()
    {
        bail!("app-server auth token cannot be empty");
    }
    let has_explicit_token = configured.is_some();

    if options.insecure_no_auth {
        if !options.listen.ip().is_loopback() {
            bail!("refusing unauthenticated app-server bind on non-loopback address");
        }
        eprintln!("warning: app-server HTTP auth disabled by --insecure-no-auth");
        return Ok(None);
    }

    if !has_explicit_token && !options.listen.ip().is_loopback() {
        bail!(
            "refusing non-loopback app-server bind without explicit auth token; pass --auth-token or set CODEWHALE_APP_SERVER_TOKEN"
        );
    }

    let token = configured
        .map(str::to_string)
        .unwrap_or_else(|| format!("cwapp_{}", Uuid::new_v4().simple()));
    for line in app_server_auth_status_lines(has_explicit_token) {
        eprintln!("{line}");
    }
    Ok(Some(token))

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Reinstall the plugin through Codewhale so the bundle is staged as plain single-link files
  2. Inspect the path: 'fsutil reparsepoint query <file>' and 'fsutil hardlink list <file>', then remove extra links or links entirely
  3. Stop managing the plugins directory with symlink/hard-link dedupe tools
Defensive patterns

Strategy: validation

Validate before calling

const FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x400;

fn is_plain_single_link_file(path: &std::path::Path) -> bool {
    match std::fs::symlink_metadata(path) {
        Ok(md) => md.is_file() && md.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT == 0,
        Err(_) => false,
    }
    // plus: hard-link count == 1 via GetFileInformationByHandle / fsutil hardlink list
}

Try / catch

match open_bundle_file(&path) {
    Err(e) if e.to_string().contains("reparse point, hard link") => {
        // reinstall the plugin so the bundle is restaged as plain files
    }
    other => other?,
}

Prevention

When it happens

Trigger: Reviewing or staging a plugin whose component file is a symlink, has a second hard link (identity.links != 1), or names a directory/device - typically a hand-installed, deduped, or tampered plugin bundle.

Common situations: Users symlink plugin files to share one copy between installations; migration tools hard-link bundle files; partially synced cloud folders leave reparse placeholders in the plugins tree.

Understand the failure class

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/7152f206f3980652. Report an issue: GitHub.