A named-pipe handle or connection PID must not be treated as continuing application authentication; use AppContainer/package identity to restrict initial access, then require fresh operation-bound authorization from a component the authorized endpoint cannot delegate or misuse.
Documented boundary of the pipe experiment
The observed result is consistent with documented handle semantics:
- Pipe handles can be duplicated into another, unrelated process and used there. Non-inheritability prevents inheritance during process creation; it does not prevent deliberate
DuplicateHandleuse.^1^ -
DuplicateHandleproduces a handle valid in the target process, provided the requiredPROCESS_DUP_HANDLErights are available.^2^ -
GetNamedPipeClientProcessIdreports the client process identifier associated with the pipe instance; its contract does not say that it identifies the process performing every subsequent I/O operation.^3^ - A pipe DACL is checked when a client opens the pipe. A logon-SID ACE can exclude other logon sessions, but it does not cause a new access check on every write through an already granted or duplicated handle.^4^
Named-pipe impersonation similarly exposes the security context associated with the last message read; it authenticates a user/token context, not the executable currently holding a delegated handle. Failure must be checked before processing the request.^5^
Supported architecture for this threat model
Use two distinct controls rather than expecting one IPC primitive to supply both.
- Package and isolate both endpoints. Run each endpoint in AppContainer or Win32 app isolation. An AppContainer token contains a package SID plus capability SIDs; access is the intersection of user/group and AppContainer grants.^6^
- Restrict initial IPC acquisition. Put the current logon SID and the intended package/capability SID on the IPC object's DACL, grant only the required direction-specific rights, and reject remote connections. This excludes other users, sessions, and packages from opening the endpoint, but does not revoke authority after an authorized endpoint delegates it.
- Authorize each operation. Bind approval to:
- exact operation and parameters;
- both expected package identities;
- user/logon context;
- server-generated nonce;
- short expiry;
- one-time consumption.
- Keep approval authority outside the requesting endpoint. The signature or MAC must be issued by an isolated broker, trusted UI, service, or protected key holder that independently displays and approves the exact operation. If the authorized endpoint itself controls the credential, it can authenticate relayed requests; deliberate relay is then outside the guarantee.
A minimal request envelope is:
struct AuthorizedRequest {
GUID operationId;
std::vector<std::byte> canonicalParameters;
std::array<std::byte, 32> serverNonce;
uint64_t expiresAt;
std::wstring callerPackageFamily;
std::wstring calleePackageFamily;
std::vector<std::byte> approvalSignature;
};
// Server verifies identities, nonce, expiry, signature, and one-time use
// immediately before executing the read-only operation.
AppContainer is a recognized isolation boundary and prevents lower-integrity container processes from injecting into higher-integrity processes; capabilities and DACLs provide least-privilege resource access.^7^ This is the primary same-user isolation control. Process mitigations are defense in depth, not caller authentication.
App Services: what is documented and unresolved
An App Service provider receives an AppServiceConnection, and activation details expose CallerPackageFamilyName; the provider can also test whether the caller has a declared capability.^8^^9^
The public contracts supplied here do not establish:
- whether connection authority can be marshaled into another process;
- whether caller package identity is revalidated per message;
- whether identity is fixed at activation or connection creation;
- whether an authorized caller may relay arbitrary requests;
- whether App Services support the exact cross-package desktop/AppContainer topology required here.
The Agile marshaling attribute on AppServiceConnection should not be interpreted as a cross-process security or non-transferability guarantee.^10^
Open a Microsoft developer support case before selecting App Services as the security boundary. Request written confirmation for those five points, including the targeted Windows build, packaging model, and whether identity/capability checks occur per request.
Package and signing identity
A package identity includes its name and certificate-derived Publisher; the Package Family Name derives from name and publisher and is version-independent.^11^ The manifest Publisher must match the signing certificate subject.^12^
Maintain an allowlist containing the expected PFN and publisher policy. Define update behavior explicitly: accepting the same PFN normally spans package versions, while publisher changes require a planned identity transition—not an implicit trust decision.
Verification matrix
Require these pass/fail results before deployment:
| Test | Required result |
|---|---|
| Unapproved package opens endpoint | Access denied before a connection is established |
| Same user, different logon session | Access denied by logon-SID/session policy |
| Remote client | Rejected |
| Authorized handle deliberately duplicated | Transport may remain usable; request fails without fresh operation authorization |
| Captured request replayed | Rejected due to consumed nonce or expiry |
| Authorized endpoint proxies a request | Rejected only if approval comes from an independent trusted component; otherwise documented as allowed |
| Client/server restarts | Old nonces and authorization state rejected by design; transport-specific stale-handle behavior tested, not assumed |
| Package update with approved publisher/PFN | Accepted according to the explicit version policy |
| Publisher/PFN changed | Rejected unless an approved migration policy applies |
| Concurrent sessions | Only the approving logon session succeeds |
| Injection/dependency substitution attempt | Blocked by isolation/mitigations or detected; never accepted as proof of IPC identity |
References
- Anonymous Pipe Operations
- DuplicateHandle function (handleapi.h)
- GetNamedPipeClientProcessId function (winbase.h)
- Named Pipe Security and Access Rights
- ImpersonateNamedPipeClient function (namedpipeapi.h)
- Launch an AppContainer
- Application isolation
- AppServiceTriggerDetails Class-Definition
- AppServiceTriggerDetails.CheckCallerForCapabilityAsync(String) Method-Definition
- AppServiceConnection Class-Definition
- An overview of Package Identity in Windows apps
- Create a certificate for package signing