Spike: live UltraVNC (Windows) and Apple Screen Sharing (macOS) on hosted runners - #335
Closed
sibson wants to merge 4 commits into
Closed
Spike: live UltraVNC (Windows) and Apple Screen Sharing (macOS) on hosted runners#335sibson wants to merge 4 commits into
sibson wants to merge 4 commits into
Conversation
Round 1: test whether windows-latest can host UltraVNC (no-auth, loopback-only) and macos-latest can host Screen Sharing / Remote Management via kickstart, both driven by vncdotool over the real network stack. Windows tries an unauthenticated loopback config first; macOS creates a dedicated local user and tries ARD/DH auth with a legacy-VNC-password fallback. Jobs are independent so one OS failing does not cancel the other, and both upload screenshots plus diagnostic logs regardless of outcome. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STWkReabCK9sJW2qQ45brM
Round 1 results: - macOS: ARD/Diffie-Hellman auth via a dedicated local user worked end to end (connect, handshake, auth, type, capture) but the captured framebuffer was fully black. The legacy VNC password path is confirmed non-functional - kickstart accepts the command but the server still demands ARD/DH auth with a username. - Windows: a full recursive scan for winvnc.exe over C:\Program Files took over 5 minutes on the loaded windows-latest toolcache, and launching winvnc.exe directly (-run) opened an interactive "Settings" window rather than truly headless-serving, so the RFB connection failed silently under default (non-verbose) logging. This round hardcodes the known choco install path, switches Windows to service mode (UltraVNC's normal unattended-deployment path), and runs vncdo at -v -v with explicit exit-code checks so a real failure is visible instead of silently falling through. The macOS job drops the non-functional legacy attempt from its pass/fail gate and adds diagnostics aimed at explaining the black framebuffer (caffeinate to rule out display sleep, console/session/display state dumps); a black-but-connected result still counts as a working screenshot per the spike's success criteria and no longer fails the job. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STWkReabCK9sJW2qQ45brM
Round 2 result: with service mode fixed, vncdo successfully connected and typed, but capture failed with a definitive server-side error: "This server does not have a valid password enabled. Until a password is set, incoming connections cannot be accepted." This holds regardless of AuthRequired, so a real password is mandatory rather than optional for UltraVNC. This round computes the UltraVNC ini's DES-encrypted passwd field using the exact same RFB DES-variant key transform vncdotool itself implements in rfb.py's _vnc_des(): the password's bits are reversed per byte to form a DES key, which then encrypts 8 zero bytes; the result is hex-encoded with a trailing 00 update-flag byte. Verified locally that this key derivation is byte-for-byte identical to _vnc_des() and that the DES encryption round-trips correctly; whether UltraVNC's ini format accepts this exact encoding is what this run will confirm empirically. macOS is unchanged from round 2, where it passed: ARD/Diffie-Hellman auth via a dedicated local user connects, authenticates, types, and captures successfully end to end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STWkReabCK9sJW2qQ45brM
Round 3 result: with a passwd= field set, UltraVNC dropped the
"no password enabled" rejection and offered VNC_AUTHENTICATION - but
the server rejected the auth challenge response for "vncspike1",
meaning the password it decoded from our ini hex was wrong. That
hex was computed by using the password itself (bit-reversed) as a
DES key to encrypt 8 zero bytes - the same transform vncdotool's
rfb.py _vnc_des() uses for the RFB challenge *response*, but that's
the wrong primitive for password *storage*.
This round switches to the actual classic VNC password-file
algorithm shared by the whole VNC family (originating in AT&T's
vncauth.c, and still what TightVNC/TigerVNC/x11vnc/UltraVNC all
build on): a DES key derived from a fixed constant
{23,82,107,6,35,78,88,7} (via the same bit-reversal transform)
encrypts the null-padded password bytes as plaintext. That's the
inverse pairing of round 3 (fixed key encrypts the password, rather
than the password deriving a key that encrypts zeros).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01STWkReabCK9sJW2qQ45brM
sibson
commented
Aug 13, 2026
| # artifact uploads and diagnostics. | ||
| # | ||
| # Round-1 findings baked into this version: | ||
| # - Recursively scanning C:\Program Files for winvnc.exe took 5+ minutes on the |
Owner
Author
There was a problem hiding this comment.
too much omment here. narrative should be in docs and linked here not inline
Owner
Author
|
🤖 Claude Code: Superseded — Tier 2 graduation work already merged to main: setup/diagnostic scripts under tests/servers/ultravnc/ and tests/servers/screen-sharing/, tests/functional/test_os_servers.py, and docs/server-compatibility-plan.md updated with this spike's findings. This raw spike workflow is no longer needed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
Viability spike for Tier 2 of the server compatibility plan: can GitHub-hosted
windows-latest/macos-latestrunners host live OS-bound VNC servers for vncdotool to test against? Verdict: viable on both, with one macOS caveat. Final spike-os-servers run is green on both jobs after four evidence-driven rounds. Single file added:.github/workflows/spike-os-servers.yml.Windows / UltraVNC — works end-to-end
choco install ultravnc;winvnc.exeis at the fixed pathC:\Program Files\uvnc bvba\UltraVNC\winvnc.exe(do not searchProgram Filesrecursively — minutes-slow on runner images)AuthRequired— no no-auth shortcut exists (server literally replies "Until a password is set, incoming connections cannot be accepted")ultravnc.inipasswd=hex uses the classic VNC password-file obfuscation (DES with the fixedvncauth.ckey, bit-reversed) — computed in a few lines of Python on the runner; note this is not the challenge-response transformwinvnc.exe -install+Start-Service);winvnc.exe -runopens an interactive settings dialog instead of servingvncdo type+capturesucceed with genuine, non-black desktop content → Windows supports real visual assertionsmacOS / Screen Sharing — works at the protocol level
sysadminctl -addUser), enable Remote Management viakickstart; Screen Sharing is socket-activated on :5900 out of the box-setvnclegacy/-setvncpwsilently but the server still demands ARD authrfb.pyfalls into an interactiveinput("username:")prompt and dies withEOFErroron a TTY-less runner — filed under the plan's Phase 1 fail-loudly itemsSpike status
Spike-quality proof, triggered only on pushes to this branch + manual dispatch. Graduation (per
docs/server-compatibility-plan.md): both jobs move under the change-triggered/path-filtered policy — Windows as a full type+capture check, macOS with pixel assertions explicitly excluded — with passwords moved to repository secrets and the dedicated-user/service-mode setup retained.Generated by Claude Code