{"record":{"id":"0c1a16823d17a588","repo":"astrid-runtime/astrid","slug":"named-pipe-client-s-effective-token-belongs-to-a-d","errorCode":null,"errorMessage":"named-pipe client's effective token belongs to a different operating-system user","messagePattern":"named-pipe client's effective token belongs to a different operating-system user","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/local_transport/windows.rs","lineNumber":473,"sourceCode":"\nfn require_current_user_process_peer(stream: &LocalStream) -> io::Result<VerifiedPeerProcess> {\n    let peer = peer_process_identity(stream)?;\n    if peer.user_sid.equals(&current_user_sid()?) {\n        Ok(peer)\n    } else {\n        Err(io::Error::new(\n            io::ErrorKind::PermissionDenied,\n            \"named-pipe peer process belongs to a different operating-system user\",\n        ))\n    }\n}\n\nfn require_current_user_effective_client(stream: &LocalStream) -> io::Result<()> {\n    let client_sid = effective_client_user_sid(stream)?;\n    if client_sid.equals(&current_user_sid()?) {\n        Ok(())\n    } else {\n        Err(io::Error::new(\n            io::ErrorKind::PermissionDenied,\n            \"named-pipe client's effective token belongs to a different operating-system user\",\n        ))\n    }\n}\n\nfn effective_client_user_sid(stream: &LocalStream) -> io::Result<OwnedSid> {\n    let server = match &stream.inner {\n        StreamInner::Server(server) => server,\n        StreamInner::Client(_) => {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"client effective-token validation requires the server pipe end\",\n            ));\n        },\n    };\n    let impersonated = unsafe { ImpersonateNamedPipeClient(server.as_raw_handle().cast()) };\n    if impersonated == 0 {","sourceCodeStart":455,"sourceCodeEnd":491,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/local_transport/windows.rs#L455-L491","documentation":"During accept, the server impersonates the named-pipe client (ImpersonateNamedPipeClient) and reads the effective token's user SID; if it differs from the server's own user SID the client is rejected. This checks the identity the client is actually exercising on the pipe, complementing the process-owner check.","triggerScenarios":"accept() called on a server pipe whose connected client's effective security token belongs to a different OS user — e.g. the client connected using a token of another account, or its impersonation token differs from its process owner.","commonSituations":"Client running under a service account while the server runs as the logged-in user; client started via scheduled task under a different identity; duplicated/impersonated tokens on the client side.","solutions":["Start the client under the same user account that owns the server pipe.","Check the client isn't impersonating another user before ConnectNamedPipe/CreateFile on the pipe.","Inspect both accounts with `whoami /user` on each side to confirm the SIDs match."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// on the client: ensure the process token owner matches the server account\n// e.g. verify with GetTokenInformation(TokenOwner) before opening the pipe","typeGuard":"fn token_owner_matches(client_sid: &Sid, server_sid: &Sid) -> bool {\n    client_sid.equals(server_sid)\n}","tryCatchPattern":"match listener.accept() {\n    Err(e) if e.kind() == io::ErrorKind::PermissionDenied\n        && e.to_string().contains(\"effective token\") => {\n        eprintln!(\"client token owner mismatch; dropping connection\");\n    }\n    other => other?,\n}","preventionTips":["Don't run clients under scheduled-task or service accounts that differ from the server user.","Avoid impersonation on the client before connecting.","Log both SIDs on rejection to diagnose account mismatches quickly."],"tags":["windows","named-pipes","security","authentication","token"],"backgroundTag":"permission-denied","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}