Hi @Pål Bernhardsen ,
Thank you for your patience while I reviewed the available Microsoft documentation. I went through your questions separately, as some aspects are documented by the public Win32 APIs, while others do not currently have the same level of class-specific detail.
1. Process and token access requirements
For OpenProcessToken, the documentation states that the process handle must have PROCESS_QUERY_LIMITED_INFORMATION. The requested token access is then evaluated against the token's DACL. The documentation also notes additional security-context considerations, such as SE_DEBUG_NAME when checking a process started by a different account.
For GetTokenInformation, TOKEN_QUERY is required for all TOKEN_INFORMATION_CLASS values except TokenSource, which requires TOKEN_QUERY_SOURCE.
Therefore, PROCESS_QUERY_LIMITED_INFORMATION and TOKEN_QUERY are the documented access requirements for these respective operations, subject to the applicable DACL and security context.
2. Querying while the primary thread is suspended
The documentation states that a thread created with CREATE_SUSPENDED does not begin execution until ResumeThread is called. This allows work to be performed before the suspended thread begins executing.
However, while these documents establish the suspended-thread behavior, I could not find an explicit public documentation statement covering GetTokenInformation(TokenIsLessPrivilegedAppContainer) on the child process's primary token specifically before the first ResumeThread.
3. TokenIsLessPrivilegedAppContainer output contract
The Win32 TOKEN_INFORMATION_CLASS documentation states that GetTokenInformation uses values from this enumeration and includes TokenIsLessPrivilegedAppContainer. However, while TokenIsAppContainer explicitly states that the buffer receives a DWORD whose nonzero value indicates an AppContainer token, the Win32 entry for TokenIsLessPrivilegedAppContainer describes LPAC but does not define the corresponding output buffer type, size, alignment, or value interpretation.
The WDK version provides additional information: it states that TokenIsLessPrivilegedAppContainer returns a DWORD value that is nonzero when the token is for an LPAC. However, that documentation introduces TOKEN_INFORMATION_CLASS in the context of SeQueryInformationToken and ZwQueryInformationToken.
I could not find a public Microsoft document that explicitly establishes this WDK class-specific DWORD description as the documented Win32 GetTokenInformation contract. Therefore, for a security-sensitive implementation, I would avoid treating that correspondence as an explicit Win32 API guarantee.
The general GetTokenInformation contract does document the buffer mechanics: TokenInformationLength specifies the supplied buffer size, ReturnLength receives the required number of bytes, and the function returns zero on failure, with GetLastError providing extended error information.
What the public Win32 documentation does not currently define for this specific information class is the exact output layout, alignment, valid values, successful ReturnLength semantics, or class-specific error mapping.
4. LPAC process creation
Microsoft does document how to launch an LPAC. The Launch an AppContainer documentation shows an LPAC being configured through STARTUPINFOEX, PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, and the additional PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY attribute with PROCESS_CREATION_ALL_APPLICATION_PACKAGES_OPT_OUT. It then uses that startup information when creating the process.
This provides a documented LPAC creation path. However, I did not find documentation presenting successful creation through these attributes as an independent post-creation verification of the resulting primary token, which is the additional guarantee your fail-closed design requires.
5. Areas not clearly established by the public documentation
For the remaining parts of your scenario, I could not find sufficiently explicit information in the currently published Microsoft documentation to confirm:
- the complete class-specific Win32 output contract for TokenIsLessPrivilegedAppContainer;
- whether the WDK DWORD description is explicitly the contract for Win32 GetTokenInformation;
- class-specific alignment and successful ReturnLength semantics;
- class-specific error mapping that would distinguish an unsupported information class from the other relevant failure conditions;
- a build-specific guarantee for Windows 11 Home 26H2, build 26300.9818, x64;
- or another documented user-mode API providing equivalent independent LPAC verification before the first ResumeThread.
Given that this verification forms part of a security-sensitive, fail-closed design, I would be cautious about relying on undocumented buffer assumptions or behavior observed only on a particular Windows build.
For authoritative confirmation of the class-specific API contract and build-specific guarantees that are not explicitly covered by the public documentation, I recommend contacting Microsoft Developer Support. The Windows SDK technical support channel would be better positioned to provide or route an authoritative clarification for this scenario.
If you found this helpful, you can refer to this guidance to confirm it and help others with similar questions.
Thank you.