41 Commits

Author SHA1 Message Date
Adam Shiervani df5dbea431 fix(keyboard): keep modifiers out of auto-release (#1438)
* 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.
2026-05-01 14:48:25 +02:00
Adam Shiervani 72d27ac85e feat: add custom broadcast IP option to Wake-on-LAN (#1238) (#1345)
* 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.
2026-03-28 12:54:57 +01:00
Alex Howells 7e8f881627 refactor(web): extract magic cache and cookie TTL constants (#1304)
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>
2026-03-17 09:35:20 +01:00
Ercan Ermiş edb8162bc3 fix(security): sanitize error messages returned to clients (#1270)
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>
2026-03-16 11:52:27 +01:00
Ercan Ermiş cde4d74c64 fix(security): add missing HTTP security headers (#1267)
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>
2026-03-16 11:50:37 +01:00
Ercan Ermiş d303b0ea93 fix(security): rate limit /device/setup endpoint (#1271)
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>
2026-03-16 11:50:07 +01:00
Alex Howells 5b6bf0b98b fix(security): enforce bcrypt 72-byte password length limit (#1290)
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
2026-03-16 11:11:03 +01:00
Alex Howells 0a522c9d12 fix(security): redact secrets from diagnostics ZIP export (#1291)
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.
2026-03-16 11:07:25 +01:00
Alex Howells 8f73daa05f fix(security): persist session token to disk on login (#1293)
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.
2026-03-16 11:07:03 +01:00
Adam Shiervani 13c5e55962 Rate limit login access (#1185)
* 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
2026-02-08 10:19:28 +01:00
Adam Shiervani 4cf6b08964 Improve failsafe handling (#1135)
* 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
2026-01-07 01:18:09 +01:00
DigitalDJ be0bb36490 Prevent mDNS queries by ICE when mDNS is disabled in config (#1094) (#1095)
* Prevent mDNS queries by ICE when mDNS is disabled in config (#1094)

* Pass full mDNS mode via SessionConfig, additionally set WebRTC NetworkTypes (#1094)
2025-12-29 13:27:40 +01:00
DigitalDJ 34d877756e Fix TLS server to obey LocalLoopbackOnly setting (#1090) (#1091) 2025-12-29 13:25:22 +01:00
Marc Brooks 6e1b84f39b chore: clean up logger messaging 2025-11-07 13:21:38 +01:00
tadic-luka 36f06a064a feat: add web route for sending WOL package to given mac addr (#945)
* 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>
2025-11-06 21:39:22 +01:00
Aveline c775979ccb feat: refactoring network stack (#878)
Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
2025-10-15 18:32:58 +02:00
Aveline 72e3013337 feat: send all paste keystrokes to backend (#789)
* feat: send all paste keystrokes to backend

* feat: cancel paste mode

* wip: send macro using hidRPC channel

* add delay

* feat: allow paste progress to be cancelled

* allow user to override delay

* chore: clear keysDownState

* fix: use currentSession.reportHidRPCKeyboardMacroState

* fix: jsonrpc.go:1142:21: Error return value is not checked (errcheck)

* fix: performance issue of Uint8Array concat

* chore: hide delay option when debugMode isn't enabled

* feat: use clientSide macro if backend doesn't support macros

* fix: update keysDownState handling

* minor issues

* refactor

* fix: send duplicated keyDownState

* chore: add max length for paste text

---------

Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
2025-09-18 13:00:57 +02:00
Marc Brooks 80a8b9e9e3 feat: Adds IPv6 disabling feature (#803)
* Allow disabling IPv6

Simply ignores any IPv6 addresses in the lease and doesn't offer them to the RPC
Also fixed display issue for IPv6 link local address.
Fixes https://github.com/orgs/jetkvm/projects/7/views/1?pane=issue&itemId=122761546&issue=jetkvm%7Ckvm%7C685

* Don't listen on disabled addresses in mDNS or web server.

* We have to set the IPv4 and IPv6 modes on the server.
2025-09-16 12:44:56 +02:00
Marc Brooks ca8b06f4cf chore: enhance the gzip and cacheable handling of static files
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.
2025-09-12 08:41:41 +02:00
Aveline 6202e3cafa chore: serve pre-compressed static files (#793) 2025-09-11 19:17:15 +02:00
Aveline 584768bacf chore: remove /device/ui-config.js endpoint (#678) 2025-07-10 12:04:47 +02:00
Alex Goodkind 718b343713 feat: add local web server loopback mode configuration (#511)
* 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.
2025-05-27 17:28:51 +02:00
Aveline 189b84380b network enhanecment / refactor (#361)
* chore(network): improve connectivity check

* refactor(network): rewrite network and timesync component

* feat(display): show cloud connection status

* chore: change logging verbosity

* chore(websecure): update log message

* fix(ota): validate root certificate when downloading update

* feat(ui): add network settings tab

* fix(display): cloud connecting animation

* fix: golintci issues

* feat: add network settings tab

* feat(timesync): query servers in parallel

* refactor(network): move to internal/network package

* feat(timesync): add metrics

* refactor(log): move log to internal/logging package

* refactor(mdms): move mdns to internal/mdns package

* feat(developer): add pprof endpoint

* feat(logging): add a simple logging streaming endpoint

* fix(mdns): do not start mdns until network is up

* feat(network): allow users to update network settings from ui

* fix(network): handle errors when net.IPAddr is nil

* fix(mdns): scopedLogger SIGSEGV

* fix(dhcp): watch directory instead of file to catch fsnotify.Create event

* refactor(nbd): move platform-specific code to different files

* refactor(native): move platform-specific code to different files

* chore: fix linter issues

* chore(dev_deploy): allow to override PION_LOG_TRACE
2025-04-16 01:39:23 +02:00
Siyuan Miao 94e83249ef chore(cloud): use request id from the cloud 2025-04-11 16:03:46 +02:00
Siyuan Miao 0ba7902f82 chore: update logging 2025-04-11 12:55:36 +02:00
Siyuan Miao e08ff425c3 chore(log): add webRtcLogger 2025-04-11 08:05:04 +02:00
Siyuan Miao 4c37f7e079 refactor: use structured logging 2025-04-11 00:43:46 +02:00
Aveline dc1ce03697 chore(websocket): logging and metrics improvement (#347)
* chore(websocket): only show warning if websocket is closed abnormally

* chore(websocket): add counter for ping requests received
2025-04-11 00:43:46 +02:00
Aveline 66a3352e5d feat(websocket): handle ping messages sent from react and add logging (#346) 2025-04-11 00:43:46 +02:00
Adam Shiervani 98af805089 refactor: remove unnecessary whitespace in setupRouter function 2025-04-11 00:43:45 +02:00
Adam Shiervani 84b35d5deb re-add old signaling for when upgrading 2025-04-11 00:43:45 +02:00
Adam Shiervani 1a30977085 Feat/Trickle ice (#336)
* 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>
2025-04-09 00:10:38 +02:00
SuperQ aed453cc8c chore: Enable more linters
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>
2025-03-26 18:41:09 +01:00
Siyuan Miao 8b59a3e387 chore(prometheus): move prometheus to a new file 2025-03-10 13:49:20 +01:00
Adam Shiervani e4bb4f288c feat(cloud): Add support for custom cloud app URL configuration (#207)
* feat(cloud): Add support for custom cloud app URL configuration

- Extend CloudState and Config to include CloudAppURL
- Update RPC methods to handle both API and app URLs
- Modify cloud adoption and settings routes to support custom app URLs
- Remove hardcoded cloud app URL environment file
- Simplify cloud URL configuration in UI

* fix(cloud): Improve cloud URL configuration and adoption flow

- Update error handling in cloud URL configuration RPC method
- Modify cloud adoption route to support dynamic cloud URLs
- Remove hardcoded default cloud URLs in device access settings
- Refactor cloud adoption click handler to be more flexible

* refactor(cloud): Simplify cloud URL configuration RPC method

- Update rpcSetCloudUrl to return only an error
- Remove unnecessary boolean return value
- Improve error handling consistency

* refactor(ui): Simplify cloud provider configuration and URL handling
2025-02-28 13:48:52 +01:00
SuperQ e1ea783fc7 Feature: Add a metrics endpoint
Add a basic Prometheus Monitoring metrics endpoint.
* Include a `jetkvm_build_info` metric.
* `go mod tidy`

Signed-off-by: SuperQ <superq@gmail.com>
2025-02-23 15:18:46 +01:00
Aveline 69461140e3 chore(config): merge userConfig with defaultConfig and add a lock (#164)
* chore(config): merge userConfig with defaultConfig and add a lock

* chore(config): remove lock for LoadConfig
2025-02-17 20:12:34 +01:00
Aveline f3b4dbce49 feat: use the api url from device config (#161) 2025-02-17 11:34:38 +01:00
Aveline 0d7efe5c0e feat: add ICE servers and local IP address returned by the API to fix connectivity issues behind NAT (#146)
Add ICE servers and local IP address returned by the API to fix connectivity issues behind NAT
2025-02-11 15:45:14 +01:00
Adam Shiervani e445039cb8 Don't allow empty tokens (#13) 2025-01-02 21:44:26 +01:00
Adam Shiervani 20780b65db Release 202412292127 2024-12-29 21:27:42 +01:00