* fix(keyboard): keep modifiers out of auto-release
Prevent per-key auto-release from dropping held modifiers during jitter while keeping explicit cleanup paths covered by E2E tests.
* fix(keyboard): keep modifiers out of auto-release
Prevent per-key auto-release from dropping held modifiers during jitter while keeping explicit cleanup paths covered by E2E tests.
* chore(keyboard): trim autorelease comments
Keep comments focused on keyboard behavior and remove branch-specific narrative from the tests.
* fix(keyboard): reset keepalive timing on key state changes
Reset session keepalive timing on every keyboard state change so stale gaps do not poison later holds under modifiers.
* fix: add custom broadcast IP option to Wake-on-LAN (#1238)
Add support for specifying a custom subnet broadcast IP when sending
WOL magic packets, enabling wake across different subnets.
Backend:
- Add broadcastIP optional parameter to rpcSendWOLMagicPacket
- Add OptionalParams support to RPCHandler for params with zero defaults
- Pass broadcastIP query param through HTTP handler
UI:
- Add broadcast address dropdown (Auto/Custom) to WOL dialog
- Show subnet broadcast IP input when Custom is selected
- Pass broadcastIP to RPC call when custom mode is active
* fix: move broadcast address field to add form only, default to Auto (#1238)
* fix(ui): simplify WoL broadcast dropdown and indent custom field
- Rename "Auto (global broadcast)" to "Auto" in the broadcast address
dropdown
- Wrap the custom subnet IP input in a nested indent with left border,
matching the settings page pattern (NestedSettingsGroup style)
* fix(i18n): use localization system for WoL broadcast address labels
Replace hardcoded English strings with m.xxx() calls in the broadcast
address UI and add the 4 new keys to all 14 locale files.
web.go had three hardcoded duration values scattered across
seven call sites:
- 31536000 (1 year) for immutable asset and robots.txt
Cache-Control headers, appearing on lines 123 and 140
- 300 (5 minutes) for cacheable static file headers, line 131
- 7*24*60*60 (1 week) for authToken cookie MaxAge, appearing
on lines 535, 706, 760, and 893
Extract these into named constants (cacheImmutableMaxAge,
cacheShortMaxAge, authTokenMaxAge) at the top of the file.
No behavioural change. The constants make the intent readable
at each call site and give maintainers a single place to
adjust these values.
Signed-off-by: Alex Howells <alex@howells.me>
Raw err.Error() strings in handleWebRTCSession, handleLocalWebRTCSignal,
handleLogin, handleSetup (web.go) and OIDC handlers (cloud.go) could expose
internal file paths, system details, or configuration to clients. Replace
with generic messages and log internal errors server-side via zerolog.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
Add X-Frame-Options, X-Content-Type-Options, and X-XSS-Protection headers
to all responses via a global middleware to prevent clickjacking, MIME
sniffing, and reflected XSS attacks.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The setup endpoint was publicly accessible without any rate limiting,
allowing an attacker on the network to probe or brute-force the endpoint
on unconfigured devices. Reuse the existing passwordRateLimiter (same
exponential backoff as login) to limit repeated failed attempts.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Go's bcrypt.GenerateFromPassword rejects passwords over 72 bytes with
an error. The code calls it without length checking in handleSetup,
handleCreatePassword, and handleUpdatePassword. The error surfaces as
"Failed to hash password" with no indication of the actual cause.
Users report being unable to set passwords during initial setup.
Add MaxPasswordLength = 72 alongside the existing MinPasswordLength = 8.
Check it in all three backend handlers before calling GenerateFromPassword,
returning a clear error message. Add matching MAX_PASSWORD_LENGTH
validation in the frontend (settings local-auth dialog and welcome
password flow) with localized error messages in all 13 languages.
Fixes#60
The diagnostics endpoint serializes the entire Config struct into
config.json inside the ZIP. This includes CloudToken (grants cloud API
access), LocalAuthToken (session credential), HashedPassword (bcrypt
hash, crackable offline), and GoogleIdentity. Users download this ZIP
for troubleshooting and may share it in GitHub issues or support
channels, exposing all credentials.
Copy the config struct and zero the sensitive fields before
serialization. The diagnostics ZIP retains all non-secret configuration
for debugging purposes.
handleLogin generates a new LocalAuthToken UUID on each login but does
not call SaveConfig to persist it. handleCreatePassword (line 686),
handleUpdatePassword (line 740), handleSetup (line 872), and
handleLogout (line 523) all persist the token — handleLogin is the only
auth path that does not.
If the device reboots after login but before any other config-saving
operation, the in-memory token is lost and the previous token from disk
is reloaded. The user's session cookie becomes invalid and the stale
on-disk token could be reused.
Add SaveConfig after token generation, matching the pattern used by
every other auth handler in the file.
* Set minimum chars and ratelimit on pw
* Implement onboarding flow for USB device tests by adding helper functions to handle welcome state and login. Enhance test setup to ensure device is ready before running tests.
* Refactor password handling by removing rate limiting checks from update and delete password functions. Update UI error handling to remove rate limit messages. Clean up related test cases for rate limiting.
* Refactor welcome flow and password handling in tests. Consolidate password setup functions and enhance local authentication mode checks. Update test cases to streamline onboarding and password management processes.
* Update log file paths in DEVELOPMENT.md
* Add password validation messages for multiple languages
- Added error message for passwords that are too short (minimum 8 characters).
- Included rate limiting error message for too many failed attempts.
- Updated localization files for Danish, German, Spanish, French, Italian, Japanese, Norwegian, Portuguese, Swedish, and both Simplified and Traditional Chinese.
* Update noder version in DEVELOPMENT.md
* Fix typo in log file path in DEVELOPMENT.md
* Refactor device onboarding and authentication flow in tests
- Renamed `ensureWelcomeState` to `resetDeviceToWelcome` for clarity.
- Consolidated password handling in welcome flow tests, replacing deprecated functions.
- Updated test setup to ensure device is in noPassword mode before running tests.
- Removed unused functions and cleaned up related test cases for better maintainability.
* Refactor mouse round-trip tests to streamline cursor movement verification
* Refactor crash log handling to improve large log handling.
- Introduced `readFileTail` function to read only the last specified bytes from log files, preventing memory issues with large files.
- Updated `checkFailsafeReason` and `rpcGetDiagnostics` functions to utilize `readFileTail` for reading crash logs and application logs, respectively.
- Adjusted log retrieval logic to handle different byte limits for recent and older crash logs.
* Remove the cause of the large logs. No need to log our mdn
* Move to HTTP for diagnostics
* Fix linter
* Prevent mDNS queries by ICE when mDNS is disabled in config (#1094)
* Pass full mDNS mode via SessionConfig, additionally set WebRTC NetworkTypes (#1094)
* feat: add web route for sending WOL package to given mac addr
```
adds a new route /device/send-wol/:mac-addr to send the magic WOL package
to the specified mac-addr.
Method is POST and is protected.
Useful for custom wake up scripts: example is sending HTTP request through iOS shortcut
Test plan:
calling the API with curl
```
$ curl -X POST http://<jetkvm-ip>/device/send-wol/xx:xx:xx:xx:xx:xx
WOL sent to xx:xx:xx:xx:xx:xx
```
and observing the magic packet on my laptop/PC:
```
$ ncat -u -l 9 -k | xxd
00000000: ffff ffff ffff d050 9978 a620 d050 9978 .......P.x. .P.x
00000010: a620 d050 9978 a620 d050 9978 a620 d050 . .P.x. .P.x. .P
00000020: 9978 a620 d050 9978 a620 d050 9978 a620 .x. .P.x. .P.x.
00000030: d050 9978 a620 d050 9978 a620 d050 9978 .P.x. .P.x. .P.x
00000040: a620 d050 9978 a620 d050 9978 a620 d050 . .P.x. .P.x. .P
00000050: 9978 a620 d050 9978 a620 d050 9978 a620 .x. .P.x. .P.x.
```
calling the api with invalid mac addr returns HTTP 400 error
```
$ curl -X POST -v http://<jetkvm-ip>/device/send-wol/abcd
...
* Request completely sent off
< HTTP/1.1 400 Bad Request
...
...
Invalid mac address provided
* Resolve golint complaint
---------
Co-authored-by: Marc Brooks <IDisposable@gmail.com>
Add SVG and ICO to cacheable files.
Emit robots.txt directly.
Recognize WOFF2 (font) files as assets (so the get the immutable treatment)
Pre-gzip the entire /static/ directory (not just /static/assets/) and include SVG, ICO, and HTML files
Ensure fonts.css is processed by vite/rollup so that the preload and css reference the same immutable files (which get long-cached with hashes)
Add CircularXXWeb-Black to the preload list as it is used in the hot-path.
Handle system-driven color-scheme changes from dark to light correctly.
* feat: add local web server loopback mode configuration
- Introduced a new configuration option `LocalWebServerLoopbackOnly` to restrict the web server to listen only on the loopback interface.
- Added RPC methods `rpcGetLocalWebServerLoopbackOnly` and `rpcSetLocalWebServerLoopbackOnly` for retrieving and updating this setting.
- Updated the web server startup logic to bind to the appropriate address based on the new configuration.
- Modified the `LocalDevice` struct to include the loopback setting in the response.
* remove extra logs
* chore: add VSCode extensions for improved development environment
* refactor: rename LocalWebServerLoopbackOnly to LocalLoopbackOnly
- Updated the configuration struct and related RPC methods to use the new name `LocalLoopbackOnly` for clarity.
- Adjusted the web server binding logic and device response structure to reflect this change.
* feat: add loopback-only mode functionality to UI
- Implemented a new setting for enabling loopback-only mode, restricting web interface access to localhost.
- Added a confirmation dialog to warn users before enabling this feature.
- Updated the ConfirmDialog component to accept React nodes for the description prop.
- Refactored imports and adjusted component structure for clarity.
* refactor: optimize device settings handlers for better performance
- Refactored the `handleDevChannelChange` and `handleLoopbackOnlyModeChange` functions to use `useCallback` for improved performance and to prevent unnecessary re-renders.
- Consolidated the logic for applying loopback-only mode into a separate `applyLoopbackOnlyMode` function, enhancing code clarity and maintainability.
- Updated the confirmation flow for enabling loopback-only mode to ensure user warnings are displayed appropriately.
* feat(cloud): Use Websocket signaling in cloud mode
* refactor: Enhance WebRTC signaling and connection handling
* refactor: Improve WebRTC connection management and logging in KvmIdRoute
* refactor: Update PeerConnectionDisconnectedOverlay to use Card component for better UI structure
* refactor: Standardize metric naming and improve websocket logging
* refactor: Rename WebRTC signaling functions and update deployment script for debug version
* fix: Handle error when writing new ICE candidate to WebRTC signaling channel
* refactor: Rename signaling handler function for clarity
* refactor: Remove old http local http endpoint
* refactor: Improve metric help text and standardize comparison operator in KvmIdRoute
* chore(websocket): use MetricVec instead of Metric to store metrics
* fix conflicts
* fix: use wss when the page is served over https
* feat: Add app version header and update WebRTC signaling endpoint
* fix: Handle error when writing device metadata to WebRTC signaling channel
---------
Co-authored-by: Siyuan Miao <i@xswan.net>
Enable more golangci-lint linters.
* `forbidigo` to stop use of non-logger console printing.
* `goimports` to make sure `import` blocks are formatted nicely.
* `misspell` to catch spelling mistakes.
* `whitespace` to catch whitespace issues.
Signed-off-by: SuperQ <superq@gmail.com>