{"record":{"id":"0183b8c51286185b","repo":"astrid-runtime/astrid","slug":"named-pipe-peer-pid-did-not-identify-the-opened-pr","errorCode":null,"errorMessage":"named-pipe peer PID did not identify the opened process","messagePattern":"named-pipe peer PID did not identify the opened process","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/local_transport/windows.rs","lineNumber":437,"sourceCode":"        if peer_process_id(stream)? != self.process_id {\n            return Err(io::Error::new(\n                io::ErrorKind::PermissionDenied,\n                \"named-pipe peer process changed during authentication\",\n            ));\n        }\n        Ok(())\n    }\n}\n\nfn peer_process_identity(stream: &LocalStream) -> io::Result<VerifiedPeerProcess> {\n    let process_id = peer_process_id(stream)?;\n    let process = unsafe { OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, process_id) };\n    if process.is_null() {\n        return Err(last_error(\"failed to open named-pipe peer process\"));\n    }\n    let process = OwnedHandle(process);\n    if unsafe { GetProcessId(process.0) } != process_id {\n        return Err(io::Error::new(\n            io::ErrorKind::PermissionDenied,\n            \"named-pipe peer PID did not identify the opened process\",\n        ));\n    }\n\n    let mut token = ptr::null_mut();\n    let opened = unsafe { OpenProcessToken(process.0, TOKEN_QUERY, &raw mut token) };\n    if opened == 0 || token.is_null() {\n        return Err(last_error(\"failed to open named-pipe peer process token\"));\n    }\n    let user_sid = token_user_sid(&OwnedHandle(token))?;\n    Ok(VerifiedPeerProcess {\n        process_id,\n        user_sid,\n        _process: process,\n    })\n}\n","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/local_transport/windows.rs#L419-L455","documentation":"peer_process_identity opens the peer PID with OpenProcess and then calls GetProcessId on the returned handle to confirm the handle really refers to that PID. If the handle resolves to a different PID (handle recycling / PID reuse or an API inconsistency), identity cannot be trusted and the library fails closed with PermissionDenied.","triggerScenarios":"Calling connect/accept (via peer_is_current_user or require_current_user_process_peer) when the PID captured from the pipe was recycled by the OS between capture and OpenProcess, or OpenProcess returned a mismatched handle.","commonSituations":"Long-lived servers re-verifying peers whose PIDs were reused after process churn; heavily loaded systems with rapid process creation/destruction.","solutions":["Treat the peer as unverified: re-authenticate the connection (new handshake, new PID capture).","Retry the connection promptly — PID reuse windows are usually transient.","If this recurs, verify the client is not dying mid-handshake and that only one process is connecting per pipe instance."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"did not identify the opened process\") => {\n        // transient PID/handle inconsistency: re-authenticate with backoff\n        retry_with_backoff(authenticate, 3)\n    }\n    other => other,\n}","preventionTips":["Re-verify peer identity promptly after capturing the PID to shrink the reuse window.","Keep client lifetimes stable during handshake; avoid heavy process churn during IPC setup.","Fall back to full re-authentication rather than trusting a cached VerifiedPeerProcess."],"tags":["windows","named-pipes","security","process"],"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"}