Repository navigation
csp: allow data: and blob: images so Safari and Firefox can draw - #250
Closed
jseifeddine wants to merge 4 commits into
Closed
jseifeddine wants to merge 4 commits into
jseifeddine wants to merge 4 commits into
Conversation
The Content-Security-Policy had no img-src, so default-src 'self' governed images and refused the data: URIs the Guacamole client draws every tile from on browsers without WebCodecs ImageDecoder. Safari and Firefox rendered SSH and RDP sessions black with only rect fills and the cursor cell showing; Chrome decodes straight from the stream and never fetches a URL, which hid it. The same directive blocks the remote mouse cursor (cursor: url(data:...)) and blob: image URLs. Move the policy into a documented constant, add img-src 'self' data: blob:, and add a unit test that fails if img-src loses either source. Document the proxy-side header replacement for releases up to v1.10.5. Fixes sol1#249
This was referenced Oct 10, 2026
Windows RDP without GFX rounds the requested width down to a multiple of 16, so a 1710-wide window gets a 1696-wide desktop. The uniform fit in scaleDisplay() then keeps the scale at 1 (the height matches) and the missing 14px shows as a strip of bare page down the right edge. After the uniform fit, stretch the display element by the remaining fraction on each axis when it is at most 2.5%, and divide the same factors out of pointer coordinates before sendMouseState. A larger gap is a real aspect mismatch and keeps the letterbox. Multi-monitor pop-outs reset the fill. Fixes sol1#251
The 18px table with 20px cell padding and a separate cell each for edit, clone and delete overran the main column by ~300px on a 1710px MacBook display, cutting "delete" off the right edge. Put the three admin actions in one cell, and add a max-width: 1800px breakpoint on the connections page: 20px page padding, 240-280px sidebar, 16px cells with tighter padding, 14px headers, a 110px Connect button and a smaller folder title. The icon-only "open in new window" button keeps its compact size. Nothing is hidden; at 1710px the table fits with about 250px to spare. Fixes sol1#252
Three things kept the Connections page a stale picture of NetBox and Vault: a device moved between tenants kept its entry in both folders, a synced entry waited on a five-minute timer for its credentials, and the page never refreshed until it was reloaded. PUT .../entries/:entry?move=true deletes same-named entries from every other folder of the scope after the write, each audited, so an upsert keyed on a stable name follows its device when the folder changes. Folders get default credentials: a per-session-type username, password or private key at <folder>/.defaults, lent at connect time to entries with no secret of their own, subfolders inheriting per type. Listings report such entries as has_credentials with inherited_credentials, so they show Connect from the moment a webhook creates them. Admin API (GET/PUT/DELETE .../defaults, secrets write-only, audited) and a section in the folder dialog. GET /api/addressbook/version is a counter bumped by middleware after every successful change through the API; it costs no Vault read. The page polls it every three seconds and reloads folders, entries, the search index and the credential status only when it moves, plus an unconditional refresh every two minutes for changes made elsewhere. Nothing reloads while a dialog is open or the tab is hidden. Fixes sol1#253
Author
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.
Fixes #249, #251, #252 and #253.
What
Add
img-src 'self' data: blob:to the Content-Security-Policy thatsecurity_headersputs on every response, move the policy into a documented constant, and add a unit test that fails ifimg-srcever losesdata:orblob:again.Why
Safari and Firefox rendered SSH and RDP sessions black with only rect fills and the cursor cell visible. The Guacamole client draws each
imgstream by loading adata:image/...;base64,...URI into anImageon browsers without WebCodecsImageDecoder. With noimg-srcdirective,default-src 'self'applied and the browser refused every one of those loads.Display.draw()silently skips a failed image, the frame still flushes andsyncis still acked, so nothing showed up in rustguac or guacd logs. Chromium decodes straight from the stream bytes throughImageDecoderand never fetches a URL, which is why Chrome was fine on the same server.The same directive also blocks the remote mouse cursor (
cursor: url(data:...)fromoncursor) and theblob:image path inDisplay.drawBlob.Verification
main: 109 image loads, 109 errors,securitypolicyviolationevents witheffectiveDirective: "img-src", black framebuffer.cargo test --bin rustguac test_csppasses,cargo fmt --checkclean.Deployed versions
Until this ships, the reverse proxy can replace the header; the full policy is in #249 and in
docs/reverse-proxies.md.Also in this PR
#251: RDP strip on the right. Windows without GFX rounds the requested width down to a multiple of 16 (1710 asked, 1696 given), and the uniform fit in
scaleDisplay()left the 14px as bare page. After the uniform fit the display element is now stretched by the remaining fraction on each axis when that is at most 2.5%, and pointer coordinates are divided by the same factors beforesendMouseState. Larger gaps are real aspect mismatches and keep the letterbox. Checked against a realGuacamole.Displayin headless Chrome: 1710x960 over a 1696x960 framebuffer givesscale(1.00825, 1), an exact fit gives no transform, 1280x1024 in a 1710x960 window keeps the letterbox.#252: connections table at 1710px. Edit, clone and delete share one cell, and a
max-width: 1800pxbreakpoint tightens page padding, sidebar, cell size and the Connect button. Rendered at 1710x1112 before and after: the row that previously ran off the right edge now fits with ~250px spare and nothing is hidden.#253: live Connections page, folder default credentials, moving upserts.
PUT .../entries/:entry?move=truemakes the target folder the entry's only home in the scope (same-named entries elsewhere are deleted and audited), so a NetBox device that changes tenant follows instead of doubling. Folders can lend default credentials per session type (.defaults, admin API and a section in the folder dialog) to entries with none of their own, inherited by subfolders; such entries list ashas_credentials+inherited_credentialsand connect straight away.GET /api/addressbook/versionis a counter a middleware bumps after every successful change through the API, and the page polls it every 3 s, reloading only when it moves (plus a 2-minute unconditional refresh). Verified end to end against OpenBao dev: a move removed the old copy with an audit record, a connect through inherited defaults logged into an SSH target, and the page in Safari followed adds, defaults changes and deletes within one poll with no reload.