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
- Reinstall the plugin through Codewhale so the bundle is staged as plain single-link files
- Inspect the path: 'fsutil reparsepoint query <file>' and 'fsutil hardlink list <file>', then remove extra links or links entirely
- 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
- Install plugins only through Codewhale's own install path
- Treat the plugins directory as app-managed; no symlink or hard-link dedupe
- Exclude the plugins directory from cloud sync
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- refusing non-loopback app-server bind without explicit auth
- Codewhale-owned xAI OAuth path must not be a reparse point
- timed out waiting for runtime API bridge at {}/health
- refusing non-regular or reparse-point config lock at {}
- {} is a reparse point, not a workspace-owned file
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/7152f206f3980652.
Report an issue: GitHub.