Credential variables — address book entries reference $domain_username /
$domain_password instead of storing static credentials. Users fill in their
own values via My Credentials (gear menu), stored per-user in Vault KV.
All variables set → silent launch; missing → prompted. Hyphens allowed in
variable names. Docs section added.
Bug fixes:
- Rate limiting disabled by default; opt-in via rate_limit = true (#62)
- Docker: copy FreeRDP guac-common-svc plugins to runtime image (#64)
- Docker/install: add chromium-sandbox package for non-root web sessions (#61)
- Logo: skip redundant JS src= when server-side branding already set (#65)
- Sessions page: hide Open/Share buttons for non-active sessions (#63)
- Drive: expose drive_configured in /api/auth/status, warn in UI when
[drive] not configured
- install.sh: verify FreeRDP plugin installation
UI polish:
- Nav bar: border separator + spacing between header and nav on all pages
- Address book: password show/hide toggle on all password fields
- Drive diagnostic logging (session.rs, websocket.rs, client.html)
Closes#61, #62, #63, #64, #65
- Server-side HTML branding: site_title, h1, logo_url baked in at
startup so first paint shows configured branding (#59)
- Docker: pre-create certs/, drives/, scripts/ dirs and chown for
non-root user so startup loaders can write config/certs (#57)
Pre-create certs/, drives/, scripts/ dirs and chown them to the
rustguac user. Also chown the top-level /opt/rustguac dir (non-recursive)
so startup loaders can write config.toml and cert material without
needing root.
- Add optional `banner` field to address book entries (shown before session
starts, user must click Continue). No longer auto-populates from display_name.
- Restructure web entry form: username, password, login script, and autofill
collapsed under a collapsible "Automation" section.
- Filter login scripts dropdown to .js/.sh/.py files only (skip package.json etc.)
- Fix CDP/login scripts: change DeveloperToolsAvailability policy from 2 (disabled)
to 0. DevTools UI remains blocked by chrome://* URLBlocklist. Fixes login script
automation that was silently broken by the v0.6.0 security hardening.
- Update Dockerfile, debian/postinst, install.sh with corrected policy.
- Update docs/security.md and docs/web-sessions.md.
The loadLoginScripts() function called the non-existent authHeaders(),
causing a JS error that silently prevented web entry edit/clone modals
from opening.
Create a dedicated rustguac user instead of running as root. This
fixes the Chromium sandbox issue (SUID helper works as non-root)
and is better security practice for containers.
Chromium crashpad needs a real home directory, so the user gets
/home/rustguac. Data/recording dirs are chowned at build time.
Chromium refuses to start as root without --no-sandbox, causing a
silent black screen in Docker. Now detected via euid check — bare
metal installs with the SUID sandbox helper are unaffected.
Also adds a 500ms post-spawn liveness check: if Chromium exits
immediately (sandbox failure, missing libs, etc), stderr is captured
and logged, and the session fails with a clear error instead of
leaving Xvnc running with a black screen.
Clone opens the entry form in create mode pre-populated with the
source entry's settings and a "-copy" name suffix. Credentials are
not copied (security by design) — user re-enters or uses prompt.
Useful for duplicating similar entries (e.g. same config, different
host) and as a workaround for rename (clone + delete original).
Add GET /api/addressbook that returns all visible folders with entries
in a single response. Eliminates N+1 fetch pattern (list folders, then
entries per folder) that triggered 429 rate limiting on page load.
Address book UI now uses batch endpoint for initial load, falls back to
per-folder fetch after mutations (create/edit/delete).
Rate limits increased: API 20/s burst 100 (was 5/s burst 30), session
create 2/s burst 10 (was 1/s burst 5), WebSocket 5/s burst 50 (was
1/s burst 20).
- Rewrite Vault mTLS client to build rustls ClientConfig directly,
bypassing reqwest::Identity::from_pem() which fails with rustls
backend for PKCS#8 keys from OpenBao/Vault PKI
- Make cert_path/key_path optional in [tls] — guacd TLS now works
independently of server HTTPS (for reverse proxy setups)
- Add webpki-roots direct dependency for custom TLS config
- Add mTLS tests: PKCS#8 key, fullchain cert, tls_skip_verify
- Update docs: configuration.md, security.md
Closes#51, closes#49
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Allow dead_code on module (used via CLI subcommand, not direct calls)
- Simplify bool toggle: in_quote = !in_quote
- Use iterator instead of index loop in deduplicate_names
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New docs/web-sessions.md: comprehensive guide with autofill, domain
allowlisting, login scripts (Playwright + shell examples), clipboard
control, API reference, and troubleshooting
- Fix integrations.md: web sessions DO use credentials (for autofill
and login scripts)
- Add global Chromium policy warning to security.md and web-sessions.md
- Add web-sessions.md to in-app docs (build.rs)
- Condense overview.md web section to link to new dedicated doc
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New features:
- Native Chromium autofill: pre-populate Login Data SQLite before launch,
zero external deps (no Node.js/Playwright needed for simple login flows)
- Per-entry domain allowlisting: restrict which domains Chromium can reach
via --host-rules (separate from server-side web_allowed_networks CIDR)
- Per-entry clipboard control: disable-copy and disable-paste for all
session types (SSH, RDP, VNC, Web) via guacd native parameters
- Guacamole import: `rustguac import-guacamole` parses mysqldump SQL and
writes entries to Vault address book
Security hardening:
- Comprehensive Chromium managed policy deployed via install.sh, Dockerfile,
and debian/postinst (blocks DevTools, downloads, file dialogs, extensions,
dangerous URL schemes)
- Profile isolation: each web session gets a unique UUID-based profile dir
- Autofill credentials encrypted with Chromium's native os_crypt (AES-128-CBC)
Documentation:
- Updated README, docs/api.md, docs/security.md, docs/configuration.md,
docs/overview.md, docs/integrations.md with all new features
- Clarified two-layer domain restriction (web_allowed_networks vs allowed_domains)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add missing headline features to the README feature list and
architecture diagram. Update GitHub repo description to match.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolves PKCS7_verify signature/chain validation bypass and AES-CCM
timing side-channel vulnerabilities in aws-lc-sys.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Patches 003 (null guards) and 004 (config.h includes) both modified
disp.c and input.c, causing git apply to fail when applied sequentially
in the Docker build. Combined into a single 003-null-guard-and-config-h
patch that applies cleanly after 001 and 002.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bumps aws-lc-sys from 0.37.1 to 0.38.0 via aws-lc-rs 1.16.1,
resolving the security_update_not_possible failures in Dependabot.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
debian/control had Architecture: amd64 hardcoded, causing
dpkg-buildpackage to skip the package entirely on arm64 hosts
("no binary artifacts found").
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The := assignment was inside a recipe (tab-indented) where lines are
shell commands, not Make directives. Move to file scope with ?= so
dpkg-buildpackage can override, and Make expands it in recipe lines.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
debian/rules hardcoded x86_64-linux-gnu for the FreeRDP plugin directory,
causing empty packages on arm64 (aarch64-linux-gnu).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The default config.toml shipped in the .deb had db_path, static_path,
and other top-level keys placed after the [recording] header, causing
TOML to scope them under [recording] where serde silently ignored them.
The top-level db_path defaulted to ./rustguac.db which the rustguac
user cannot create in the root-owned /opt/rustguac directory.
Fixes: move all top-level keys above section headers in the template.
Adds a postinst migration that detects and repairs broken configs on
upgrade (backs up config first).
Closes#25
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Send actual browser window dimensions at session creation (addressbook,
sessions) instead of defaulting to 1920x1080
- Send initial sendSize() on WebSocket connect so guacd can resize the
remote display via Display Update channel
- Debounce window resize handler (250ms) to avoid overwhelming RDP server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>