WebLink is a Windows-only native host for a WebView2-based bridge between C++ code and browser-side JavaScript.
At a high level, WebLink splits responsibility across three components:
WebLinkthe native Win32 client / implant processWebLinkLibthe native bridge layer that owns WebView2 and native/browser message passingWebLinkSrvthe Bun-based page server that provides the browser-side runtime and HTTP control plane
The project is built around one core idea: native code owns lifecycle and scheduling, while browser-side JavaScript owns browser-originated web activity.
- provide a reusable native-to-browser bridge using WebView2
- let native code drive a hidden embedded browser over COM
- keep JavaScript-side HTTP activity in browser space instead of a custom native HTTP client
- avoid an extra localhost TCP bridge between native and browser logic
- support process relocation under a chosen parent for lineage shaping
Per WebLink.exe instance, the app creates:
- one hidden native host window
- one WebView2 environment/controller pair
- one embedded page runtime
The runtime flow is:
WebLink.exestarts, optionally relocates under a chosen parent, initializes COM, and creates a hidden host window.WebLinkLibcreates the WebView2 environment and controller, installs handlers, and navigates to the configured page.- The page sends an initial
page_readybootstrap message to native throughwindow.chrome.webview.postMessage(createPageReadyMessage()). - After that one-time push, the steady-state loop is native-driven:
WebLinkLibrepeatedly callswindow.hostBridge.pollOnce()throughICoreWebView2::ExecuteScript(...). - Browser-side JavaScript talks HTTP to the server and exchanges structured messages with native through WebView2 messaging.
One embedded WebView still produces multiple msedgewebview2.exe processes because WebView2 uses Chromium's multi-process runtime model.
- platform: Windows
- default parent process:
explorer.exe - default start URL:
http://127.0.0.1:9001/index.html - default direct profile directory:
wv2_profileunder the executable directory - default log file:
debug.logbeside the executable - poll interval:
5000 ms - reconnect interval:
2000 ms
Examples:
msbuild WebLink.vcxproj /t:Build /m /p:Configuration=Debug /p:Platform=x64
msbuild WebLink.vcxproj /t:Build /m /p:Configuration=Debug /p:Platform=ARM64Start the Bun server first so the page is available at http://127.0.0.1:9001/index.html, then launch WebLink.exe.
Run the server from WebLinkSrv/server.ts:
cd .\WebLinkSrv
bun run .\server.tsExpected startup output:
[2026-03-23T20:11:49.068Z] Server listening on http://127.0.0.1:9001
[2026-03-23T20:11:49.071Z] Commands: catalog, ask <uuid>, list, answers, clear, help, exit
Predefined questions:
11111111-1111-1111-1111-111111111111 Do1
22222222-2222-2222-2222-222222222222 Do2
33333333-3333-3333-3333-333333333333 Do3
The Bun server includes a small interactive console for enqueueing predefined questions:
> help
catalog show valid question UUIDs
ask <uuid> enqueue a predefined question by UUID
list show queued/dequeued/answered question state
answers show recorded answers
clear clear queue and answers
exit quit
Example:
> ask 11111111-1111-1111-1111-111111111111
> answers
Basic launch:
.\x64\Debug\WebLink.exeLaunch and relocate under a selected parent process:
.\x64\Debug\WebLink.exe -p M365Copilot.exeThat launch asks WebLink.exe to respawn under M365Copilot.exe instead of the default parent. This is useful when testing parent-lineage shaping against a process that already has a normal relationship with msedgewebview2.exe.
Launcher flags:
-p <process.exe>request relocation under the named parent process-rinternal marker used by the relocated child after handoff
The important detail is that -p triggers relocation. After relocation, the running child process continues with -r -p <process.exe> in its command line.
- This is a Windows-only TTP and implementation. It depends on WebView2, COM, and Windows process creation behavior.
msedgewebview2.exeis a Microsoft-signed runtime component, but that should not be confused with invisibility or guaranteed trust.- The host window is message-only and hidden. There is no visible UI requirement for normal operation.
- When the WebView is hidden, WebView2 background throttling rules can still apply. WebLink mitigates that by keeping scheduling on the native side.
- WebLink.cpp app bootstrap, relocation bootstrap, COM setup, hidden host window, message loop
- WebViewBridgeHost.cpp WebView2 creation, navigation, timers, page message handling
- HostProtocolBridge.cpp typed dispatch from raw page messages into native callbacks
- ClientConfig.cpp startup policy, profile policy, logging defaults
- WebLinkSrv/server.ts Bun server for the bridge page and local HTTP tasking flow
For the longer architectural rationale and operational discussion, see the blog and architecture notes under docs/.