Skip to content

Security: ictechgy/Knot

SECURITY.md

Security scope

This is a development preview with source/build/synthetic checks, not a completed security audit or a claim of superiority to Chrome Remote Desktop.

Reporting a vulnerability

Use GitHub private vulnerability reporting for security-sensitive reports. Public bug reports should contain only source paths and a minimal synthetic reproduction. Do not include passwords, PINs, private keys, real files/desktops or raw service logs.

Trust boundaries

  • Direct user-selected private LAN/Tailscale IPv4 only. No relay/account/port-forwarding setup.
  • Automatic Bonjour/Mac-address suggestions exclude APIPA (169.254/16); manually entered link-local endpoints remain an advanced exception for a deliberately configured local link. Suggestions are capped at eight Mac addresses and never establish reachability or identity.
  • Bonjour and QR/link contents are untrusted address hints, not authentication. Discovery resolves DNS-SD metadata without host TCP probes or subnet scans, with bounded duration/services/results; only supported private IPv4/default Sunshine port candidates reach the UI. Choosing one runs the existing PIN/certificate path. QR import previews PC name/address and preserves both stored screen and SSH pins; active file/screen work rejects endpoint replacement in the model.
  • QR generation/decoding is offline. Version1 links carry a bounded name and1–8 canonical private IPv4 addresses; version2 also identifies the host platform. Unknown fields, credentials, fragments, ports, duplicate addresses and control/format characters are rejected. Platform hints select a compatible client workflow and never establish identity. QR does not import keys, reset trust or authorize files. Camera access is user-initiated video only, stops on dismissal and never stores/transmits images. QR image input is restricted to supported image types and bounded before full decode.
  • Sunshine identity established with upstream PIN challenge and verified certificate proof, then exact certificate pinning. Saved-pin failure never authorizes a replacement pin. Re-pairing requires the user to forget the saved host and approve PIN again.
  • Control/video/audio encryption and encrypted RTSP signalling are mandatory. Unsupported hosts fail closed; there is no plaintext toggle.
  • Authenticated host control counters are tracked across ENet channels in a fixed 65,536-counter replay window. Duplicate/expired envelopes do not advance reliable delivery state; only authenticated packets update the window. Fresh out-of-order counters within the window remain valid. A rejected new reliable envelope receives no ACK. Only exact previously accepted envelope fingerprints at duplicate transport labels permit retransmission ACKs; the fixed-capacity history uses constant-time eviction and stores no plaintext. This does not authenticate the outer ENet headers or prevent transport-level denial of service.
  • Encrypted RTSP replies must authenticate with AES-GCM, carry a strictly increasing independent host sequence within the RTSP instance, and have exactly one CSeq matching the actual request. Gaps are allowed; duplicates, older/wrapped counters and malformed/mismatched CSeq fail without committing receive state. This does not replace host pinning or authenticate the AES-CBC audio format.
  • Sunshine's audio wire format uses AES-CBC without a message authentication tag. Its sequence-derived IV repeats after the 16-bit packet sequence wraps within the same audio key; repeated plaintext prefixes can therefore reveal equality. Mandatory encryption does not give audio the integrity protection of authenticated control/video packets. Padding validation before queue admission detects some malformed payloads and is not authentication. LAN access control or Tailscale remains relevant against packet injection. Changing this format requires host protocol support.
  • Client identity is separate from Glimmer's installed identity, under Knot's Application Support directory. App-owned directories and credential/settings files are validated by descriptor for owner, private modes, ordinary type and extended ACLs before use. Credential reads are bounded and reject symlinks, hard links and special files. Unsafe existing material blocks connection instead of authorizing identity regeneration. No keychain or previous-app migration.
  • Configuration read failure blocks reconnection/storage, preserving existing trust state instead of treating it as a new host.
  • Settings writes enforce the same 128 KiB encoded-size limit as reads before replacing the previous file. Host display names are limited to 256 UTF-8 bytes and omit control/format characters; identity and certificate pins are not truncated.
  • Streaming disconnect uses disconnectOnly and never sends Sunshine /cancel.
  • SFTP uses a separate host pin and explicitly selected SSH key. Global SSH config, password auth, forwarding, proxy configuration and unrelated identity attempts are disabled.
  • Windows SFTP uses a dedicated standard local user, forced internal-sftp/chroot and NTFS ACLs. It does not add file I/O to privileged Sunshine.
  • The Windows public helper is a native x64 Win32 bootstrap. Before any CLR activation it restricts DLL search, holds image/ancestor paths against replacement, verifies the embedded managed helper's SHA256, creates an ACL-protected fresh stage and starts that exact helper with a fixed working directory. Elevated children receive an OS-derived environment allowlist; the normal UI receives a token-derived user environment with CLR/profiling hooks and module/temp/system overrides removed. Elevated stages use protected Program Files; ordinary UI stages use the current user's OS-known local temporary directory. TEMP/TMP for child applications use stable OS-derived temporary locations rather than the disposable stage. This narrows loader/path injection surfaces; actual Windows loader/ACL/UAC acceptance remains pending.
  • The primary UI requests elevation of the original native EXE with a bounded operation and validated public request data. The broker extracts its own hashed scripts into a protected administrator stage. It copies Sunshine's MSI there and rechecks embedded size/SHA256 before starting the fixed Windows installer. No caller-selected script or executable crosses this primary elevation boundary. A raw source folder is a separately warned manual-script workflow.
  • The Windows Sunshine downloader limits writes to the pinned byte count, validates HTTPS redirect hosts and enforces a 60-second idle and 10-minute total budget. Cancellation waits for its worker to close streams and remove an incomplete file before the UI permits another operation; final size/hash verification still precedes elevation.
  • Reuse/export validates the helper-owned firewall rule's direction, action, profile, ports, address set, application/service/interface/security filters and counts, rather than trusting its name or addresses alone. This does not inspect or override unrelated/GPO firewall rules.
  • Revoke/uninstall may return an already-inactive no-op only after successful fixed-resource inventories prove no default SSH config or dedicated firewall rule, a missing/disabled transfer account, a missing/stopped sshd service and no executing system OpenSSH server/session/auth workers. This path never changes resources, adopts/deletes metadata or opens shared data. Active/unknown conditions and any inventory error require strict managed preflight or refusal, including a present config/rule. It is independent of obsolete recovery-account/binary references only because it authorizes no mutations.
  • Remote desktop full control has greater authority than the SFTP share. A restricted file account does not restrict what a user can do through the desktop.
  • Uploads are new UUID job directories; downloads are exclusive local files. No user-confirmation overwrite shortcut. Downloads attach macOS quarantine metadata to the open partial-file descriptor before exclusive finalization; failure aborts and cleans the partial file. This labels remote content for OS assessment and does not establish that a file is safe.
  • No automatic clipboard sync or analytics. No full raw protocol/token/session-key diagnostic export UI.
  • SSH startup guidance inspects at most 4096 bytes with a signature-sized rolling byte window while draining stderr. Only fixed failure categories reach the UI; raw SSH diagnostic lines, usernames, paths and hostnames are not stored or displayed. Cancellation/deadline/protocol errors retain their own classification.

Windows-to-Mac desktop boundary

  • Reverse sharing is explicitly enabled in the Mac UI. Installed Sunshine must match the pinned bundle identifier, version and Developer ID team, with strict nested-code validation. DMG downloads are immutable official assets with size/SHA256 validation; no permission or OS security policy is silently disabled.
  • An app-owned private configuration supplies credentials/state/certificate/apps paths, mandatory LAN/WAN encryption, disabled UPnP and loopback-origin-only administrative web UI. Defaults are created only when missing; metadata-validated configuration and application-list edits inside this owned deployment survive restart. Sunshine validates their contents; the user must retain a Desktop entry for Knot's client. Sunshine still listens on IPv4 network interfaces; this is not a host firewall and cannot undo externally configured router forwarding. Do not expose the service publicly.
  • Only a new owned host process group is managed. A bundled native supervisor retains the exclusive read end of Knot's lifetime pipe; only Knot holds its write end. App exit or crash closes that pipe, and the supervisor kills its own group. The pinned Sunshine web Restart otherwise forks into another group, so the host executes under a fixed additional no-fork restriction before its first instruction. A same-PID helper checks denial before executing the host; missing wrapper, restriction or helper support fails closed without a direct-spawn fallback. This explicitly disables web Restart and custom application subprocesses: use Desktop and Knot sharing off → start. The stock macOS sandbox-exec/SBPL interface is deprecated and not a supported third-party sandbox API; its future availability and real capture/TCC interoperability are not assumed. It never loosens an inherited restriction or changes system security settings. Graceful stop has a bounded hard-stop fallback. The app observes the supervisor without reaping until group cleanup, so it never signals a reused group ID. No persisted PID, process-name kill, existing user settings or existing Sunshine instance is adopted. A process started is not evidence that screen permission, input permission or a media session works.
  • The single Windows EXE adds a native client role under the existing pre-CLR bootstrap. The unchanged Moonlight engine is downloaded directly from its pinned official ZIP only on request; archive size/hash, exact entry inventory, full file hashes, ordinary/private paths and held runtime files are required before execution. The source archive and third-party notices are linked. Decoder code is an exact pinned Apache-2.0 source subset compiled offline and loaded from an embedded SHA256-bound resource.
  • Streaming state is in a separate app-owned portable directory, per address, with exclusive profile use. Global Moonlight settings/credentials are not imported. QR and mDNS only produce private-address candidates; pairing and certificate persistence belong to the dedicated engine profile. Changing address may require pairing again.
  • Our supported Mac host enforces encrypted media; incompatible client negotiation must fail there. The unmodified Windows client does not inherit the Glimmer-specific encrypted-RTSP/replay/input hardening. No claim of identical client security, protocol audit or superiority to another product is made. The documented upstream AES-CBC audio integrity limit also remains.
  • Native client code generates only pair/stream Desktop commands, with no quit-after. The upstream engine can still offer an explicit confirmation to quit a different running application; users are told to cancel it. Local disconnect/cancel uses only the owned child Job, not a host quit request. System-key capture is off by default; users may explicitly enable it for fullscreen Mac Command input, with a local release/exit shortcut.
  • The Windows engine is created suspended, assigned to its kill-on-close Job, then resumed. Assignment/resume failure terminates the owned child before releasing its process handle. Verification of downloaded and extracted engine bytes runs off the UI thread with cancellation checks.
  • Optional rich presence, mDNS and connection-testing preferences are disabled in the dedicated portable INI. The unchanged engine still makes compatibility/controller/update-availability requests; there is no zero-external-traffic claim. Knot's signed application updater is separate and does not replace the engine's pairing profile.
  • This feature grants full control of the logged-in Mac account, not access limited to an SFTP folder. Reverse file transfer is unsupported, Remote Login/SSH and Full Disk Access are not automatically enabled, and clipboard synchronization is not added. User-initiated upstream clipboard paste is distinct from automatic sync.
  • Agent validation uses only source and fresh inert process/packet/image fixtures. No production capture process, real desktop, existing user preferences/keys/logs, clipboard or live remote endpoint is accessed. Real Windows ACL/Job/native engine and Mac TCC/input/video/audio/lock/sleep/display behavior remain device acceptance items.

The Linux host downloader also checks cancellation/deadlines during DNS, TCP and TLS setup. DNS runs in one isolated, bounded resolver child that is killed and reaped on cancellation; nonblocking TCP/TLS waits retain the original HTTPS hostname and certificate verification. This resolver does not enumerate LAN or Tailscale peers.

First-run enrollment and update continuity

  • Enrollment is explicitly started on Mac, bound to a selected private IPv4 interface and the selected Windows peer, and limited to one short-lived session. The separate enrollment link carries an ephemeral TLS certificate pin and random capability; it is an authorization secret for that session and must not be shared beyond the intended Windows PC. Ordinary discovery/address invitations carry no enrollment authority. Windows connects outbound; there is no new permanent Windows listener or broad firewall exception.
  • The exchange transfers bounded public setup data only. Windows still requires local approval and the original-user privileged provisioning broker; Mac still requires SSH fingerprint confirmation. Cancellation, expiry, changed selections and request mismatches cannot install a returned host key. A successful provisioning operation can outlive a cancelled UI; cancellation must not claim it revoked an already approved Windows configuration.
  • Native updates use exact pinned Sparkle/WinSparkle archives with full inventories and license notices. Missing publisher configuration disables updater networking. Published update artifacts require Ed25519 authentication; configured Mac builds also require Developer ID signing, and Windows execution requires Authenticode verification against the configured publisher certificate. Sparkle authenticates the signed feed; WinSparkle does not authenticate feed presentation metadata. Do not treat a Windows update prompt or release-note text as authenticated publisher content. See update publication and platform limits.
  • Updates wait for active desktop, file, enrollment and sharing work, and new work is gated once installation is pending. The Windows installer waits for the exact previous process to exit before replacing its locked executable. Overinstall retains app identity, PIN trust, SSH keys, account metadata and engine profiles; uninstall is not an update step.
  • A Mac update reconnect receipt contains only the previous build number, target identity, certificate digest and a maximum ten-minute deadline. It is stored separately in private app storage and consumed before decoding or validation. Only a strictly newer build with the same saved endpoint, host ID and certificate digest may run the normal pinned PC-verification path. No automatic PIN pairing, changed-certificate acceptance, file transfer resume or automatic stream launch is authorized.

Windows signing boundary

The native helper's Authenticode signature, when explicitly applied, covers its embedded exact-source managed payload and scripts. The inner SHA256 checks detect payload replacement relative to that build; an unsigned helper does not establish publisher identity. Build signing changes only the outer helper and installer, records the final hashes and leaves tracked scripts unchanged. Embedded PowerShell scripts are unsigned. An organization enforcing AllSigned needs separately signed scripts and an approved manual distribution; EXE signing does not satisfy that script policy. No execution-policy bypass is provided.

Local credential scope

Generated SSH keys and the upstream streaming identity are owner-only local files. They are not protected against a process already running as the same macOS user, root, or an unlocked compromised session. Passphrase-protected explicit SSH identities can use an already-unlocked local agent. The app is not App Sandbox-isolated.

Generated SSH keys are created only after validating the app-owned base and a fresh private generation directory. A folder with inherited ACL entries is refused before key generation; the app does not remove ACLs from an existing directory to make it usable. Private streaming PEM files are limited to 64 KiB each and client IDs to 4 KiB. An initialized streaming identity requires all three persisted components, even if every file later disappears; it is never silently replaced. An uninitialized legacy PEM pair may complete migration with a generated client ID. Keep existing credentials when investigating a storage refusal; verify the app folder's owner, permissions and sharing settings before retrying.

If identity material is missing or corrupt, restore the complete matching identity from an original private backup. This preview has no client-identity reset or assisted repair implementation; deleting files or reinstalling the app does not clear its initialized state. Without a usable original backup, revoke this client's pairing on the host and seek project recovery guidance rather than deleting more state. Do not share private keys or settings in a bug report. See installation and recovery guidance.

Validation still required

Real Windows11 Home Sunshine encrypted signalling/media; revocation during an active stream; Windows OpenSSH chroot/ACL/fresh-install/rollback; focus/IME behavior; monitor input/EDID; audio output changes; cancellation across actual network loss; reproducible public release signing and notarization. No agent attempts a protected local service or accesses existing user content to test these.

Please avoid public reports containing private keys, PINs, host certificates paired with identifiers, raw service logs, file contents or desktop screenshots. Use a minimal synthetic reproduction and source paths.

The extracted Windows managed EXE, QR DLL and PowerShell scripts are individually unsigned in this preview. An outer Authenticode signature authenticates embedded bytes; it does not establish their acceptance under Smart App Control, WDAC or ConstrainedLanguage. Do not disable these policies. Public signed releases need inner-artifact signing before hashing/embedding and acceptance on an application-control-enabled Windows device.

Mac 공유는 Knot가 직접 시작한 자식 프로세스를 사용하므로 macOS TCC의 책임 앱이 Knot일 수 있습니다. 화면·시스템 오디오·선택한 오디오 입력의 목적 문자열을 부모 앱에도 포함하며, 권한은 실제 macOS 요청에 표시된 Knot 또는 Sunshine에 사용자가 직접 승인합니다. 개인 SPI로 책임을 숨기거나 자동 승인하지 않습니다. 실제 권한 귀속·입력·오디오 승인과 앱 교체 후 유지 여부는 대상 기기 검증 항목입니다.

Optional Windows virtual display boundary

Automatic installation is currently blocked by an explicit default-deny policy while the candidate third-party driver control interface is reviewed. The UI cannot bypass the same check in the privileged backend. Removal remains independently available for an owned deployment. A pinned archive and valid Windows signature establish provenance, not driver safety.

The implemented installer uses an exact-source elevated stage, bounded pinned ZIP/member parsing, pinned catalog signer, protected fixed settings and an exact planned random device ID journaled before creation. It uses device-targeted SetupAPI, refuses existing or later-added foreign present/phantom devices and altered files/registry, and retains shared driver-store packages. Only administrators/SYSTEM can write persistent state; the UMDF LocalService account has read access. No driver test-signing, certificate-store changes, topology mutation or physical-screen disable is performed. Manual Sunshine output selection does not require reading existing credentials/configuration/logs.

Inert tests and read-only artifact-signature checks do not establish stock Windows/Secure Boot, device installation, headless capture or performance acceptance. See headless validation boundary.

Managed Sunshine account on Windows

Current Windows builds create a fresh web account with 32 random password bytes and journal it before account creation. Existing accounts are saved only after pinned local authentication. Credentials and incomplete-setup state use machine DPAPI plus an explicit protected SYSTEM/Administrators-only file under the verified installation. The store rejects changed public certificates, malformed records, unsafe ACLs and linked files. Administrator compromise remains outside this boundary; machine DPAPI alone does not isolate local users. PINs are not retained. Setup/update never resets pairing or adopts a new certificate automatically.

The manual update installer closes only exact installed Knot images and verified same-session descendants using retained handles and graceful window messages. Privileged windows must explicitly support the idle-only safe-close protocol; older or busy privileged work is refused. No process-name kill or Sunshine/OpenSSH service stop is used for updates.

There aren't any published security advisories