Skip to content

ee/wcp: separate service account to run browser - #1380

Open
BeryJu wants to merge 38 commits into
mainfrom
ee/wcp/browser-privilege
Open

ee/wcp: separate service account to run browser#1380
BeryJu wants to merge 38 commits into
mainfrom
ee/wcp/browser-privilege

Conversation

@BeryJu

@BeryJu BeryJu commented Aug 16, 2026

Copy link
Copy Markdown
Member

No description provided.

BeryJu added 5 commits August 16, 2026 12:22
BROWSER_PRIVILEGE.md was deleted an hour after being written, in an
unrelated "cleanup" commit on ee/wcp/rs-cef-fresh. Restore it and record
what's settled for this branch: the dedicated-account option goes first,
integrated auth is out of scope so S4U needs no stored credential, and
the CEF sandbox option turns out to need a C++ shim cef-rs doesn't
provide on Windows -- left out of scope here.
ak_cef.exe launched as SYSTEM on fresh logon because
acquire_interactive_token fell back to duplicating winlogon.exe's own
token when no user token existed yet. Replace it with an S4U logon
(LsaLogonUser + MSV1_0_S4U_LOGON) for a dedicated local account, so
logon and unlock both mint a token for the same non-SYSTEM identity
and the winlogon-duplication fallback goes away entirely.

Also grants that account access to WinSta0\Winlogon (denied to any
non-SYSTEM token by default) and denies it interactive/network/RDP
logon rights, and rotates its installer-set password to a random,
discarded value the first time it runs -- nothing ever reads it back,
since S4U needs no credential.

The account itself is created by the installer; that and the design
tradeoffs are in BROWSER_PRIVILEGE.md.
WiX's util:User has no GeneratePassword attribute, so the placeholder
password/rotation approach differs from the first draft -- correct
that, and update the identity table and "rest of the work" list to
describe what credprovider now actually does instead of what was
planned.
Adds the local account ak_cef.exe now runs as (credprovider's
service_account_token/BROWSER_PRIVILEGE.md), created at install time
via util:User with a placeholder password credprovider rotates away
on first load, and grants it write access to wcp-cache. Verified with
a full local `dotnet build` of the MSI (placeholder binaries, ICE
validation included) -- only the wcp component's own binaries are
still missing from this tree.
Left over from the SYSTEM-token era this branch replaced: the spawned
browser now carries the service account's S4U token, not this
process's own SYSTEM one.
@BeryJu
BeryJu marked this pull request as ready for review August 16, 2026 11:24
@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 29.12281% with 404 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.53%. Comparing base (0da16e3) to head (f7f866c).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
ee/wcp/credprovider/src/syscalls.rs 12.36% 241 Missing ⚠️
ee/wcp/credprovider/src/ipc.rs 37.01% 125 Missing and 6 partials ⚠️
ee/wcp/cef-host/src/app.rs 30.76% 18 Missing ⚠️
ee/wcp/cef-host/src/handler.rs 68.00% 8 Missing ⚠️
ee/wcp/cef-host/src/main.rs 90.90% 3 Missing ⚠️
ee/wcp/cef-host/src/window.rs 0.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1380      +/-   ##
==========================================
- Coverage   47.58%   46.53%   -1.06%     
==========================================
  Files         195      195              
  Lines       18003    18346     +343     
  Branches    13138    13481     +343     
==========================================
- Hits         8567     8537      -30     
- Misses       9199     9577     +378     
+ Partials      237      232       -5     
Flag Coverage Δ
rs-e2e-24.04 34.98% <0.00%> (+0.01%) ⬆️
rs-e2e-25.10 10.81% <0.00%> (ø)
rs-e2e-26.04 10.81% <0.00%> (ø)
rs-macos-26-ak-agent 32.45% <ø> (+2.21%) ⬆️
rs-macos-26-ak-agent-desktop 0.00% <ø> (ø)
rs-macos-26-ak-api-cli-gen 66.71% <ø> (ø)
rs-macos-26-ak-browser-support 23.93% <ø> (ø)
rs-macos-26-ak-cli 24.30% <ø> (ø)
rs-macos-26-ak-platform 0.27% <ø> (ø)
rs-macos-26-ak-platform-facts 83.44% <ø> (ø)
rs-macos-26-ak-sysd 34.02% <ø> (ø)
rs-ubuntu-24.04-ak-agent 32.45% <ø> (ø)
rs-ubuntu-24.04-ak-agent-desktop 0.00% <ø> (ø)
rs-ubuntu-24.04-ak-api-cli-gen 66.71% <ø> (ø)
rs-ubuntu-24.04-ak-browser-support 23.93% <ø> (ø)
rs-ubuntu-24.04-ak-cli 24.30% <ø> (ø)
rs-ubuntu-24.04-ak-nss 77.37% <ø> (ø)
rs-ubuntu-24.04-ak-pam 0.00% <ø> (ø)
rs-ubuntu-24.04-ak-platform 0.26% <ø> (ø)
rs-ubuntu-24.04-ak-platform-facts 82.64% <ø> (ø)
rs-ubuntu-24.04-ak-sysd 34.24% <ø> (ø)
rs-ubuntu-24.04-arm-ak-agent 32.45% <ø> (+2.21%) ⬆️
rs-ubuntu-24.04-arm-ak-agent-desktop 0.00% <ø> (ø)
rs-ubuntu-24.04-arm-ak-api-cli-gen 66.71% <ø> (ø)
rs-ubuntu-24.04-arm-ak-browser-support 23.93% <ø> (ø)
rs-ubuntu-24.04-arm-ak-cli 24.30% <ø> (ø)
rs-ubuntu-24.04-arm-ak-nss 77.37% <ø> (ø)
rs-ubuntu-24.04-arm-ak-pam 0.00% <ø> (ø)
rs-ubuntu-24.04-arm-ak-platform 0.26% <ø> (ø)
rs-ubuntu-24.04-arm-ak-platform-facts 82.64% <ø> (ø)
rs-ubuntu-24.04-arm-ak-sysd 34.24% <ø> (ø)
rs-windows-2025-ak-agent 30.24% <ø> (-2.22%) ⬇️
rs-windows-2025-ak-agent-desktop 0.00% <ø> (ø)
rs-windows-2025-ak-api-cli-gen 66.71% <ø> (ø)
rs-windows-2025-ak-browser-support 23.93% <ø> (ø)
rs-windows-2025-ak-cli 24.30% <ø> (ø)
rs-windows-2025-ak-platform 0.27% <ø> (ø)
rs-windows-2025-ak-platform-facts 78.89% <ø> (ø)
rs-windows-2025-ak-sysd 32.49% <ø> (ø)
rs-windows-2025-ee/wcp 52.30% <29.27%> (-5.43%) ⬇️
swift 3.37% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

BeryJu and others added 2 commits August 16, 2026 12:40
The two things CI cannot reach -- the WinSta0\Winlogon ACL grant holding and
the S4U service-account token working for logon as well as unlock -- now have
a real run behind them rather than an argument.

Keeps the ACL-narrowing and temp/fonts/crashpad items open. One VM not
failing is not the same as either being handled.

Also commits the checklist edits the run was done against: registering by
hand skips the MSI's util:User, so the service account has to exist first,
and step 5 no longer describes a token fallback that S4U replaced.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The branch's earlier rebase onto main replayed these commits onto
main's actual (simpler) syscalls.rs/credential.rs -- the one merged
via #1374/#1378 -- but syscalls.rs still carried PasswordStore,
KeyringPasswordStore, ak_platform_keyring and the richer
LocalAccountPassword trait from a different, unmerged branch
(ee/wcp/stored-pw) that this branch was never meant to depend on.
credential.rs never had that machinery to begin with here, so the
mismatch didn't compile (LocalAccountPasswordReset vs
LocalAccountPassword, missing ak_platform_keyring).

Rebuilds the service-account additions directly on main's actual
LocalAccountPasswordReset/reset-only API instead. No behavior change
to any of this branch's own logic -- ensure_service_account_password_rotated
still calls the same single reset, just through the trait that
actually exists here.
@authentik-automation

Copy link
Copy Markdown
Contributor

🚀 Deployed on https://pr-1380--authentik-pkg.netlify.app

@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 16, 2026 12:23 Inactive
BeryJu added 2 commits August 16, 2026 17:16
# Conflicts:
#	ee/wcp/credprovider/src/syscalls.rs
#	ee/wcp/e2e/README.md
LocalAccountPasswordReset was this branch's stand-in for the trait
name before #1379 (properly reusing a stored password for the
interactive user's account) landed on main; merging main back in
restored its real name, LocalAccountPassword.
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 16, 2026 16:44 Inactive
BeryJu added 3 commits August 16, 2026 18:04
$ is the WiX preprocessor's variable-substitution leader (\$(var.X),
\$(env.X)) and this file is preprocessed before the XML is parsed --
plausible cause of the "invalid password" failure at install, since
the literal value NetUserAdd ends up receiving may not be what the
source says. Also lengthened it as a hedge against a stricter than
default minimum-length policy on the install target. No functional
change either way: the account is denied all interactive/network/RDP
logon and credprovider rotates this away on first load, so the exact
value has never mattered past satisfying account creation.
Several ran two paragraphs restating things BROWSER_PRIVILEGE.md
already covers, or spelling out both a function's rationale and its
caller's in one place. Same information, less of it per comment.
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 16, 2026 17:34 Inactive
`net accounts` on the install target shows minimum password length 0
and no maximum, ruling out length as the cause of "invalid password" --
so the previous two fixes (dropping "$", lengthening it) were treating
the wrong symptom. NetUserAdd folds LSA password-filter rejections
(complexity, banned-word/dictionary lists) into the same
NERR_PasswordTooShort a real length failure produces, and the old
placeholder contained a real word ("Placeholder"). Replaced it with a
random string with no recognizable words at all.
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 16, 2026 18:26 Inactive
BeryJu and others added 3 commits August 17, 2026 20:45
# Conflicts:
#	ee/wcp/credprovider/src/ipc.rs
#	ee/wcp/credprovider/src/syscalls.rs
#	ee/wcp/e2e/README.md
- ipc.rs lost its ForegroundControl import in conflict resolution:
  RealSyscalls.foreground_pid() didn't compile without the trait in
  scope.
- e2e/README.md's manual checklist kept both sides' "confirm a fresh
  logon" step -- the old one referencing syscalls::acquire_interactive_token,
  which this branch deleted. Dropped the stale duplicate.
# Conflicts:
#	vpkg/windows/Package.wxs
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 17, 2026 21:53 Inactive
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 17, 2026 22:47 Inactive
…need

Both LsaRegisterLogonProcess and CreateProcessAsUserW check the
privileges they need (SE_TCB_NAME, and SE_ASSIGNPRIMARYTOKEN_NAME/
SE_INCREASE_QUOTA_NAME respectively) as enabled, not merely present --
SYSTEM's token holds all three but disabled by default, same as any
privilege that isn't SE_PRIVILEGE_ENABLED_BY_DEFAULT. Generalizes the
one-off TCB-enabling helper into enable_privilege(name) and calls it
for all three, fixing STATUS_PORT_CONNECTION_REFUSED from the LSA
connect and ERROR_NOT_ALL_ASSIGNED from CreateProcessAsUserW seen on
a real test build. Corrects the CreateProcessAsUserW retry comment,
which had assumed this was unreachable on the real logon scenarios.
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 18, 2026 00:12 Inactive
PsExec -s confirms SeTcbPrivilege is Enabled for SYSTEM on the test
box, contradicting a real ERROR_NOT_ALL_ASSIGNED failure inside
service_account_token -- the deployed process's token evidently isn't
the plain SYSTEM token that gives you, and the previous error message
gave no way to tell a genuinely-missing privilege from an unexpected
identity. enable_privilege now takes a display name and logs it, plus
the account current_token_identity() resolves via
GetTokenInformation(TokenUser)/LookupAccountSidW, on the
ERROR_NOT_ALL_ASSIGNED path.
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 18, 2026 16:30 Inactive
BeryJu added 2 commits August 18, 2026 21:09
S4U (LsaLogonUser/MSV1_0_S4U_LOGON) needed SE_TCB_NAME, and a real
install proved LogonUI's own token does not hold it -- not disabled,
absent, confirmed by dumping the token's account identity in the same
failure. That's expected once you look at why the credential provider
model has hosted providers in the separate, more sandboxed LogonUI.exe
since Vista: third-party code loaded there was never meant to have
TCB-level trust. Calling LsaRegisterLogonProcess directly from inside
one was never going to be supported.

Chromium's own credential provider (GCPW) hits the identical wall for
the identical reason and has never used S4U: CreateLogonToken in
chrome/credential_provider/gaiacp/gcp_utils.cc calls LogonUserW with a
real password, then strips every privilege from the result via
CreateRestrictedToken(DISABLE_MAX_PRIVILEGE) before using it.
service_account_token now does the same. LogonUserW needs no special
privilege for a non-admin account -- confirmed independently, since
RealSyscalls::validate already called it successfully with no
privilege-enabling for the interactive user's password check.

This means the service account needs a real, stored password after
all -- service_account_password is the same establish-once/validate/
reuse/change state machine as credential.rs::account_password
(LOCAL_PASSWORD.md), backed by the same KeyringPasswordStore, keyed by
this account's own SID. The installer grants LogonAsService... no,
LogonAsBatchJob="yes" for the SeBatchLogonRight LOGON32_LOGON_BATCH
needs, matching GCPW's own choice for its non-interactive case.

BROWSER_PRIVILEGE.md updated throughout; the Kerberos/SPNEGO scoping
question S4U used to raise no longer applies, since LogonUserW tokens
carry real credentials.
deny_interactive_and_network_logon's doc still said Service (the old
S4U SECURITY_LOGON_TYPE) instead of Batch (LOGON32_LOGON_BATCH, what
service_account_token actually uses now).
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 18, 2026 20:45 Inactive
CreateProcessAsUserW needs SE_ASSIGNPRIMARYTOKEN_NAME/SE_INCREASE_QUOTA_NAME,
which turn out to be absent from LogonUI's token, not just disabled -
confirmed on a real install (ERROR_PRIVILEGE_NOT_HELD). CreateProcessWithTokenW
is brokered through the Secondary Logon service instead and needs only
SE_IMPERSONATE_NAME, which is present. It has no handle-inheritance mechanism
though, so the result/cancel pipe pair between credprovider and ak_cef.exe is
now a named pair (SDDL-scoped to SYSTEM + the service account's SID) instead
of anonymous-and-inherited.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 18, 2026 22:28 Inactive
The pipe DACL hardcoded "SY" (SYSTEM) as the fallback identity when no
connecting SID is given, but CPUS_CREDUI's child inherits the caller's own
token (spawn_in_current_session passes none), which is not necessarily
SYSTEM - the debug/e2e path runs as whatever user launched the test. Fixed
by dropping the explicit DACL entirely in that case and letting
CreateNamedPipeW apply the default one derived from the creating token,
which always grants that same identity full control.

connect_duplex_pipes also used to block the full timeout even after the
child had already exited (e.g. CEF's own ProcessSingleton/ContentMainRun
failing before ak_cef.exe ever reaches the code that opens these pipes) -
it now polls in short slices and bails out as soon as WaitForSingleObject
shows the process gone, logging the exit code instead of just timing out
silently 15 seconds later.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 19, 2026 11:08 Inactive
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 19, 2026 11:49 Inactive
CefInitialize was failing on real installs with Chromium's own
ProcessSingleton error ("Failed to create a ProcessSingleton for your
profile directory ... Aborting now to avoid profile corruption").
root_cache_path doubles as Chromium's user-data directory, which is what
ProcessSingleton locks against, and every launch shared one fixed path -
a second sign-in attempt starting before the first one's process had fully
torn down (or any leftover instance) made every subsequent launch fail
outright.

Fixed by giving each launch its own unique subdirectory
(browser_state_dir) instead of the shared one, removed again once that
run is done (wipe_browser_state, best-effort - a launch the credential
provider had to kill for never responding just leaves its directory
behind).

Supersedes the "try without root cache path" experiment.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 19, 2026 14:32 Inactive
CreateProcessWithTokenW was called with lpEnvironment: None, which reuses
this process's own (SYSTEM/LogonUI) environment for the child rather than
the token's. LOGON_WITH_PROFILE only loads the account's registry hive; it
does not touch the environment block, which is a separate thing the caller
builds. So %TEMP%/%LOCALAPPDATA%/etc. in the child still pointed at
system32\config\systemprofile, which the restricted service-account token
cannot write to - and Chromium touches those paths during startup
independent of root_cache_path, which is why giving each launch a unique
cache directory alone didn't fix the ProcessSingleton failure reported
against a real install (confirmed by the directory being empty afterwards,
and rebuilding/reinstalling/rebooting not changing the symptom).

Fixed with CreateEnvironmentBlock(token) in ipc.rs::spawn_with_token,
falling back to the caller's environment only if that call itself fails
(possible on the account's very first launch, before its profile directory
exists on disk).

Also: log the cache path browser_state_dir creates, and leave a failed
run's directory in place instead of wiping it, so a CefInitialize failure
is inspectable afterwards rather than erasing its own evidence.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 19, 2026 18:28 Inactive
BeryJu and others added 5 commits August 19, 2026 20:22
…in window

CefInitialize kept failing with Chromium's ProcessSingleton error even
after a unique per-launch cache directory and a proper per-token
environment block - neither was the cause. Comparing our token
acquisition, desktop, and spawn API against Google Credential Provider
for Windows's equivalent (chrome/credential_provider/gaiacp/) turned up
no difference in any of those - because GCPW's sign-in UI helper is not
a Chromium browser process at all. It launches rundll32.exe reloading its
own DLL through an entrypoint, never touching chrome_main_delegate.cc or
ProcessSingleton in the first place.

CEF 151 supports both a Chrome style runtime (the full Chrome UI/browser
layer - extensions, profile manager, ProcessSingleton) and a lighter
Alloy style runtime meant for embedding, and windowed browsers default to
Chrome style. Neither this credential provider's sign-in window nor its
BrowserView need any Chrome UI, so both now return RuntimeStyle::ALLOY -
a Chrome style Window can only host one Chrome style BrowserView, so both
had to move together.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
So a real-install log can be matched against the exact commit that
produced the binary, rather than assumed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
S4U was replaced by LogonUserW+CreateRestrictedToken several commits ago;
a few comments and e2e/README.md still described the old design (one
outright wrong - e2e/README.md called the current logon an "S4U logon",
which it isn't). Also trimmed several doc comments in ipc.rs/main.rs that
had grown long through iterative edits, including one in window.rs that
overclaimed the Alloy runtime style change fixes ProcessSingleton - later
research showed CEF's Chrome bootstrap runs unconditionally regardless of
window style, so that comment was actively misleading, not just long.

BROWSER_PRIVILEGE.md's own S4U section is left alone - it's the historical
record of why S4U was tried and abandoned, not leftover code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ProcMon showed ak_cef.exe getting ACCESS DENIED on every attempt to open
C:\ProgramData\Authentik Security Inc\logs\ak_cef_chromium.log (and its
fallback, System32\debug.log) - the logs folder was created by the
installer with no permission grant for ak-wcp-browser, unlike wcp-cache.

This means ak_cef_chromium.log has likely been frozen at whatever content
an earlier, differently-privileged run left it at, for every attempt since
the service-account redesign landed - the "still failing the exact same
way" log excerpts examined over the last several rounds of debugging may
never have reflected the current build's actual behavior at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… makes

handle.exe confirmed no stale Local\ChromeProcessSingletonStartup! mutex
exists between attempts, ruling out a wrong-DACL'd leftover object - but
that only tells us nothing PERSISTS, not why a fresh CreateMutex might
fail. Chromium's own diagnostic for this specific failure is DPLOG(FATAL),
which compiles to nothing in a release build, and Process Monitor doesn't
capture mutex operations at all. Ask the same question ourselves, through
ak_platform::log (Windows Event Log), which is confirmed working, instead
of continuing to reason about internals we can't directly observe.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 19, 2026 22:03 Inactive
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 19, 2026 23:35 Inactive
BeryJu and others added 2 commits August 20, 2026 00:44
…ntity

Confirmed against a real install: CreateMutex(Local\ChromeProcessSingletonStartup!)
fails with ERROR_ACCESS_DENIED on a fresh create (handle.exe found nothing
pre-existing, ruling out a stale wrong-owner object). Three follow-up
CreateMutex calls narrow down why: a random name under Local\ tells apart
"this token can't create named mutexes in the session namespace at all"
from "this specific, publicly-documented string is blocked" (endpoint
security software is the leading suspect for the latter); a Global\ name
checks whether it's specific to the per-session namespace; a Chrome-ish
but not-exact name checks whether the block matches the literal string or
the product name more loosely.

Also logs the token's mandatory integrity level, session id, and whether
Windows considers it IsTokenRestricted, to rule in or out the double
access-check restricted tokens get (service_account_token only passes
DISABLE_MAX_PRIVILEGE, no SIDs to disable/restrict, so this is expected to
read false - confirming that removes one more hypothesis either way).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@authentik-automation
authentik-automation Bot temporarily deployed to pull request August 20, 2026 00:26 Inactive
BeryJu and others added 3 commits August 20, 2026 01:45
Diagnostics confirmed the root cause: a LOGON32_LOGON_BATCH token cannot
create any named synchronization object (mutex/event/semaphore) in the
session namespace at all. CreateMutex(Local\ChromeProcessSingletonStartup!)
failed with ERROR_ACCESS_DENIED, and so did CreateMutex with random UUID
names under both Local\ and Global\ - ruling out a stale wrong-owner
object (handle.exe found nothing) and a name-specific block (endpoint
security software was the leading suspect until random names failed
identically). The same token creates named pipes, files, and registry
keys fine; only synchronization objects are affected.

Batch logons carry the NT AUTHORITY\BATCH well-known SID rather than
INTERACTIVE, and it's a documented Windows hardening pattern (CIS/STIG
baselines) to scope BaseNamedObjects creation rights to interactive/
service identities specifically, excluding batch - plausible on a
baselined Windows Server test box.

Switches to LOGON32_LOGON_SERVICE (SeServiceLogonRight/LogonAsService,
not SeBatchLogonRight/LogonAsBatchJob). Unverified whether this alone
fixes it or whether BaseNamedObjects also needs an explicit ACL grant for
the account, the same way ensure_desktop_access already does for
WinSta0\Winlogon.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
LOGON32_LOGON_SERVICE alone was not enough: the service account's token
still couldn't create named synchronization objects (CreateMutex etc.) in
the session's BaseNamedObjects directory, which is fatal to Chromium's
ProcessSingleton. GCPW hits the identical requirement for its own logon SID
and answers it the same way (AllowLogonSIDOnLocalBasedNamedObjects), via
NtOpenDirectoryObject since no Win32 wrapper exists for opening an arbitrary
Object Manager directory.
… state

The CreateMutex/token diagnostics in cef-host's main() served their purpose
(root-causing the BaseNamedObjects failure) and don't belong in the shipped
feature. Rewrites BROWSER_PRIVILEGE.md from a chronological debugging
journal into a concise doc describing the final design, condensing the
"roads not taken" investigation into short factual paragraphs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant