Files
nexus/audits/20260729-1237-securityAudit.md

32 KiB

Security Audit Report

1. Executive Summary

This fix-mode audit reviewed the current Nexus desktop application, its local VS Code bridge process, browser-facing frontend, session and upload lifecycles, credential handling, network clients, encrypted storage and export, Leviathan file analysis, build/release configuration, dependencies, and earlier audit reports.

No Critical or High severity vulnerability was confirmed. Four evidence-backed findings were fixed in commit b5c7528:

  • Auto-reconnect credential prompts registered a permanent Wails listener on every prompt. Long-running processes with repeated reconnects accumulated callbacks and unnecessary event-dispatch work.
  • Interrupted streaming SFTP uploads could retain open remote writers and in-memory upload entries after their session closed. Concurrent unfinished uploads were not bounded.
  • The accepted Go toolchain range included versions affected by a reachable standard-library TLS privacy vulnerability.
  • Encrypted exports and Leviathan carve output did not consistently enforce private local file permissions. Short-lived plaintext and derived key byte slices were also retained until garbage collection.

The same commit fixed malformed IPv6 host/port construction in VNC, IRC SSH tunnels, and the connection tester, and repaired stale frontend regression assertions left behind when the VS Code extension tree and CGO build were removed.

All Go tests, focused race tests, Go vet, the complete frontend test suite, frontend production build, JavaScript and shell syntax checks, PHP syntax check, npm audit, and the reachable Go vulnerability scan pass. Live remote protocol testing and packaged desktop testing remain manual validation items.

2. Scope Reviewed

Reviewed:

  • Go packages under internal/, including sessions, SSH, SFTP, VNC, IRC, Telnet, RAW TCP, local shells, storage, vault/keychain integration, recording, updater, GitHub client, import/export, and Leviathan.
  • The localhost service bridge in cmd/vscode-bridge.
  • Frontend source, lifecycle handling, DOM construction, timers, Wails event subscriptions, build scripts, and regression harness under frontend/.
  • Network address construction, host-key verification, connection setup, and session shutdown paths.
  • Dependency manifests and lock files.
  • Build, release, update, and CI configuration.
  • Earlier reports under audits/, to distinguish regressions from already fixed findings.

Not live-tested:

  • Packaged Wails applications on every supported operating system.
  • Real SSH, SFTP, VNC, IRC, Telnet, RAW, GitHub, or update endpoints.
  • Malicious network peers under sustained load.
  • External Leviathan extractor tools. Their extraction path is not currently exposed by the active Wails document response.
  • A VS Code extension runtime, because the vscode/ source tree was intentionally removed in commit 4fc3b19.

3. Methodology

The review combined:

  • Repository and Git-history inspection.
  • Trust-boundary and attacker-starting-position mapping.
  • Static review of authentication, authorisation, secrets, cryptography, filesystem operations, command execution, parsers, network clients, event listeners, goroutines, timers, and cleanup paths.
  • Adversarial resource-exhaustion review, with particular attention to a process that has run for a long time while tabs and sessions are repeatedly opened, reconnected, and closed.
  • Frontend sink/source review for unsafe HTML, event-listener accumulation, timers, stale state, and privileged Wails calls.
  • Dependency and supply-chain scanning.
  • Focused regression tests followed by broad test, race, build, syntax, and static-analysis checks.

Principal validation commands:

  • go test ./... -count=1
  • go test -race ./internal/sessions ./internal/api ./internal/exportimport ./internal/vncclient ./cmd/vscode-bridge -count=1
  • go vet ./...
  • go run golang.org/x/vuln/cmd/govulncheck@latest -show verbose ./...
  • go run github.com/securego/gosec/v2/cmd/gosec@latest ./...
  • npm test in frontend/
  • npm run build in frontend/
  • npm audit --json in frontend/
  • node --check for changed JavaScript
  • bash -n build.sh build-all.sh release.sh scripts/build-common.sh
  • php -l updates/index.php
  • git diff --check

4. Risk Rating Method

Severity reflects attacker position, prerequisites, exploit repeatability, trust-boundary impact, and confidentiality, integrity, and availability consequences.

  • Critical: practical unauthenticated remote compromise or broad secret disclosure.
  • High: practical code execution, credential theft, or privilege escalation.
  • Medium: meaningful local, renderer, connected-peer, or privacy impact with realistic prerequisites.
  • Low: bounded local exposure, defence-in-depth weakness, or correctness issue with a security consequence.
  • Informational: hardening or validation work without a confirmed exploit.

Confidence reflects the strength of source evidence, reproduction, scanner evidence, and regression coverage. Severity is not increased merely because a scanner reports a possible pattern.

5. Attack Surface Map

Entry points:

  • Wails-bound service methods invoked by the desktop renderer.
  • Runtime events crossing between frontend JavaScript and Go.
  • The token-authenticated localhost bridge endpoints.
  • User-selected SSH, SFTP, VNC, IRC, Telnet, RAW TCP, GitHub, and update endpoints.
  • Imported profiles, OpenSSH configuration, encrypted Nexus exports, recordings, and files selected for Leviathan analysis.
  • Local shell commands and SSH key generation.

Trust boundaries:

  • Renderer to privileged Go backend.
  • Local bridge client to localhost HTTP/RPC service.
  • OS keychain or encrypted vault to runtime session credentials.
  • Remote network data to protocol clients and frontend rendering.
  • User-selected or hostile files to parsers and external analysis tooling.
  • Release workflow and update manifest to installed application binaries.

Attacker starting positions considered:

  • A malicious or compromised remote service.
  • A hostile local file or imported configuration.
  • A local unprivileged process targeting the localhost bridge or filesystem artefacts.
  • A renderer injection or future renderer compromise invoking bound methods.
  • An observer of TLS traffic.
  • A legitimate local user accidentally creating unbounded resource state over a long-running process.

6. Findings Summary Table

ID Severity Confidence Title Component Status
SEC-20260729-1237-001 Medium High Reconnect credential prompts accumulated permanent runtime listeners internal/sessions Fixed in b5c7528
SEC-20260729-1237-002 Medium High Interrupted SFTP uploads retained resources without a concurrency bound internal/api Fixed in b5c7528
SEC-20260729-1237-003 Medium High Build accepted a Go toolchain with a reachable TLS privacy vulnerability go.mod, build scripts Fixed in b5c7528
SEC-20260729-1237-004 Low High Sensitive local artefacts did not consistently enforce private permissions Export/import and Leviathan Fixed in b5c7528

7. Detailed Findings

Finding ID: SEC-20260729-1237-001

Title

Reconnect credential prompts accumulated permanent runtime listeners

Severity

Medium

Confidence

High

Affected Files / Components

  • internal/sessions/manager.go:110
  • internal/sessions/manager.go:676
  • internal/sessions/manager.go:2577
  • internal/sessions/manager.go:2615
  • internal/sessions/manager.go:2654
  • internal/sessions/manager_test.go:383
  • cmd/vscode-bridge/main.go:187
  • internal/app/app.go:118

Description

Every credential request created during automatic reconnect registered another session:secret:response Wails listener. The listener was never unregistered, including after a response, timeout, cancelled reconnect, session close, or application shutdown.

The request ID check prevented one prompt from accepting another prompt's value, but all historical callbacks were still invoked for every future credential response. A process left open for a long time could therefore accumulate event callbacks in proportion to its reconnect history. A closed session could also leave a credential prompt waiting for its full timeout.

Evidence

Before the fix, buildInteractiveSecretCallback called wailsRuntime.EventsOn inside the callback created for each prompt and discarded the returned unsubscribe function.

The fix registers one manager-level response router from SetContext, stores the unsubscribe function, routes responses through a request-ID map, honours frontend cancellation, and selects on the reconnect context. Shutdown unregisters both host-key and credential listeners and releases all waiters. Application and bridge shutdown now call the complete service and manager shutdown methods.

Attack Scenario

A remote SSH or IRC service repeatedly drops connections after authentication, or a user repeatedly opens and reconnects profiles that require an interactive secret. Historical event listeners accumulate. Later secret responses fan out to all callbacks, increasing CPU work and retained memory even though old tabs are closed.

Impact

Progressive memory and CPU consumption in a long-running process, sluggish credential prompts, delayed shutdown, and eventual application availability loss. The request-ID routing means no cross-session secret disclosure was confirmed.

Recommendation

Use one application-lifetime event listener per event type, route responses by opaque request ID, bind every waiter to a cancellation context, and explicitly unsubscribe and release waiters during shutdown.

Safer Example

Implemented in outline:

cancel := wailsRuntime.EventsOn(ctx, "session:secret:response", m.handleSecretResponse)
m.secretListenerCancel = cancel

select {
case response := <-ch:
    return response.value, cancellationError(response)
case <-ctx.Done():
    return "", ctx.Err()
}

Suggested Tests

Added tests verify request-ID routing, reconnect-context cancellation, frontend cancellation, pending-map cleanup, and shutdown waiter release. The focused race suite passes.

References

  • CWE-400: Uncontrolled Resource Consumption
  • CWE-772: Missing Release of Resource after Effective Lifetime

Assumptions / Limitations

No packaged Wails runtime stress test was run. The defect and fix are directly visible in source, and the routing/cancellation logic is covered at Go level.

Finding ID: SEC-20260729-1237-002

Title

Interrupted SFTP uploads retained resources without a concurrency bound

Severity

Medium

Confidence

High

Affected Files / Components

  • internal/api/api.go:52
  • internal/api/api.go:117
  • internal/api/api.go:469
  • internal/api/api.go:475
  • internal/api/api.go:515
  • internal/api/api.go:1569
  • internal/api/api.go:2189
  • internal/api/api.go:2202
  • internal/api/api_test.go:145

Description

Streaming SFTP upload state held an open remote writer in the service upload map. Finish and explicit cancel removed it, but disconnecting, reconnecting, or closing the owning session did not. Application shutdown also did not drain unfinished uploads. There was no limit on the number of simultaneously open streaming uploads.

Evidence

The earlier lifecycle paths called the session manager directly without visiting the upload map. SFTPUploadStart inserted every new writer without a capacity check.

The fix:

  • Caps active streaming uploads at 16.
  • Checks capacity before opening a remote writer and atomically rechecks before insertion.
  • Removes and closes uploads belonging to a session before disconnect or reconnect.
  • Drains every upload during close-all and service shutdown.
  • Best-effort removes the partial remote file.
  • Releases secret-prompt waiters and the service's Wails listener during shutdown as part of the same lifecycle hardening.

Attack Scenario

A compromised renderer, automation loop, or repeated user action starts uploads and closes the associated tabs or sessions without finishing them. Each iteration can retain a local map entry, SFTP request state, remote file handle, and partially written file. Repetition eventually exhausts descriptors, memory, or server-side resources.

Impact

Local and remote resource exhaustion, failed subsequent uploads, leaked partial files, and degraded session availability.

Recommendation

Make resource ownership explicit: uploads must be owned by a session and cancelled when that session ends. Bound concurrent work and keep a race-safe second capacity check after expensive setup.

Safer Example

Implemented:

func (s *Service) DisconnectSession(sessionID string) error {
    s.cancelSFTPUploads(sessionID)
    return s.sessions.Disconnect(sessionID)
}

Suggested Tests

Added tests verify session-scoped cancellation, unrelated-upload preservation, the active-upload limit, writer closure, and shutdown cleanup. Full and race tests pass.

References

  • CWE-400: Uncontrolled Resource Consumption
  • CWE-404: Improper Resource Shutdown or Release
  • CWE-772: Missing Release of Resource after Effective Lifetime

Assumptions / Limitations

No real SFTP server was used to verify partial-file deletion after a transport failure. Removal is best-effort because the session may already be unavailable; local writer and map cleanup do not depend on remote deletion succeeding.

Finding ID: SEC-20260729-1237-003

Title

Build accepted a Go toolchain with a reachable TLS privacy vulnerability

Severity

Medium

Confidence

High

Affected Files / Components

  • go.mod:3
  • go.mod:5
  • build.sh:21
  • build-all.sh:20

Description

The build accepted Go 1.25.0 and the local build used Go 1.26.4. govulncheck identified GO-2026-5856 / CVE-2026-42505 in a reachable crypto/tls path. Affected clients could expose TLS PSK identities in a plaintext ClientHello while Encrypted Client Hello was in use, allowing a passive observer to undermine ECH privacy.

Evidence

The pre-fix scan reported the standard-library vulnerability as reachable. The official Go vulnerability record states that Go 1.25 is fixed in 1.25.12 and Go 1.26 is fixed in 1.26.5.

The fix raises the module minimum to Go 1.25.12, requests toolchain Go 1.26.5, and aligns both Unix build scripts with the new minimum. The post-fix verbose scan used the Go 1.26.5 standard library and reported zero symbol or package vulnerabilities affecting Nexus.

Attack Scenario

Where ECH and PSK resumption are used, a passive network observer records the client's plaintext ClientHello and correlates an exposed PSK identity with the protected destination.

Impact

Conditional network privacy disclosure. No private key or application credential extraction was demonstrated. Nexus does not explicitly configure ECH, so actual exposure depends on TLS configuration and runtime behaviour.

Recommendation

Enforce fixed toolchain floors in go.mod, local build scripts, and CI. Keep govulncheck in release validation so standard-library vulnerabilities cannot be missed by module-only scanners.

Safer Example

Implemented:

go 1.25.12
toolchain go1.26.5

Suggested Tests

Run go version and verbose govulncheck in release CI, and fail if a reachable symbol-level vulnerability is reported.

References

  • GO-2026-5856
  • CVE-2026-42505
  • CWE-200: Exposure of Sensitive Information

Assumptions / Limitations

The scanner established a reachable TLS symbol path, not that Nexus actively negotiated ECH with a vulnerable server during this audit. Severity therefore reflects conditional exploitability.

Finding ID: SEC-20260729-1237-004

Title

Sensitive local artefacts did not consistently enforce private permissions

Severity

Low

Confidence

High

Affected Files / Components

  • internal/exportimport/exportimport.go:68
  • internal/exportimport/exportimport.go:111
  • internal/exportimport/exportimport.go:116
  • internal/exportimport/exportimport.go:170
  • internal/exportimport/exportimport_test.go:108
  • internal/leviathan/binsnoop/binsnoop.go:137
  • internal/leviathan/binsnoop/binsnoop.go:141
  • internal/leviathan/binsnoop/extract.go:17
  • internal/leviathan/binsnoop/extract.go:20
  • internal/leviathan/binsnoop/common_test.go:25

Description

Encrypted profile exports were created through os.Create, which normally uses mode 0666 filtered by the process umask. Overwriting an existing file also preserved its existing mode. Leviathan carved binary data and extraction directories used 0644 and 0755. Carved content can include credentials, private keys, firmware configuration, or other forensic secrets.

Export encryption keys, password byte slices, and decrypted plaintext byte slices also remained live until garbage collection after use.

Evidence

The fix opens exports with mode 0600 and explicitly applies Chmod(0600) so an existing permissive destination is tightened. Leviathan-owned carve files now use 0600, and directories use 0700. Export/import makes a best-effort clear of transient password, derived-key, and plaintext byte slices.

Attack Scenario

On a multi-user host, another local account reads a carved private key or configuration from a world-readable output file. For an export destination that already had permissive permissions, another account can copy the encrypted profile bundle for offline password guessing.

Impact

Local confidentiality exposure. The export remains protected by Argon2id and AES-GCM, which significantly reduces its immediate sensitivity; raw carve output has no equivalent encryption.

Recommendation

Create sensitive artefacts and parent directories with private modes, tighten existing destinations explicitly, and minimise the lifetime of mutable plaintext and key buffers. Document that Go strings and internal copies cannot be guaranteed to be erased.

Safer Example

Implemented:

f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
if err == nil {
    err = f.Chmod(0600)
}

Suggested Tests

POSIX-only regression tests verify 0600 export and carve files and a 0700 carve directory, including overwriting a pre-existing 0644 export.

References

  • CWE-276: Incorrect Default Permissions
  • CWE-316: Cleartext Storage of Sensitive Information in Memory

Assumptions / Limitations

POSIX mode bits are not equivalent on Windows, so permission tests skip there. clear is best-effort in Go and cannot erase immutable password strings, copies held by libraries, or compiler-created copies. External extraction tools may choose their own modes for files they create beneath the private directory.

8. Blackhat-Style Abuse Paths

Path 1: Reconnect churn to process exhaustion

Prerequisite: a profile needs an interactive credential during automatic reconnect. A hostile endpoint repeatedly drops the connection. Before the fix, each prompt left another Wails listener behind. Defensive breakpoint: application-level listener routing, context cancellation, and shutdown unsubscribe.

Path 2: Renderer-driven SFTP handle exhaustion

Prerequisite: renderer access to bound service methods. Start streaming uploads without finishing them, then close or reconnect sessions repeatedly. Before the fix, writers and upload entries survived. Defensive breakpoint: the 16-upload cap and session-owned cancellation.

Path 3: Passive observation of vulnerable TLS ECH

Prerequisite: affected Go runtime, ECH/PSK behaviour, and network visibility. Observe plaintext ClientHello state and correlate exposed PSK identity. Defensive breakpoint: Go 1.25.12 or 1.26.5 and later.

Path 4: Local recovery of carved secrets

Prerequisite: another local account can traverse the selected output location. Read a 0644 carved file containing a private key or configuration secret. Defensive breakpoint: 0700 directories and 0600 files.

No practical chain to unauthenticated remote code execution was identified.

9. Denial-of-Service Review

Fixed in this audit:

  • Reconnect secret listeners no longer grow with historical prompt count.
  • Cancelled reconnect prompts stop immediately instead of waiting up to 60 seconds.
  • Session close/reconnect and application shutdown drain streaming uploads.
  • Concurrent streaming uploads are capped at 16.
  • Runtime listeners and prompt waiters are released at shutdown.
  • IPv6 literals are joined with ports correctly, preventing connection failure and misleading repeated retry behaviour.

Previously hardened and rechecked:

  • SFTP inline/chunk/total upload size caps.
  • VNC WebSocket frame limits.
  • GitHub archive and update-response size limits.
  • SSH configuration and public-key input caps.
  • Recording and Leviathan file-size limits in exposed paths.
  • Session timers, latency pings, frontend intervals, and closed-tab lifecycle cleanup covered by the current regression tests.

Residual considerations:

  • Network protocols ultimately depend on remote peer responsiveness.
  • External Leviathan tools lack a shared timeout/output-budget wrapper, but that path is not currently exposed by the active UI API.
  • Hostile binary parsers deserve continued fuzzing even where current bounds checks reject malformed offsets.

10. Dependency and Supply-Chain Review

npm audit --json reported zero vulnerabilities across 33 frontend dependencies.

Post-fix govulncheck -show verbose reported:

  • Zero vulnerabilities in symbols Nexus calls.
  • Zero vulnerabilities in imported package call paths.
  • Four advisories in required module versions that Nexus does not appear to call:
    • GO-2026-5970 in golang.org/x/text@v0.37.0.
    • GO-2026-5942 in golang.org/x/net@v0.55.0.
    • GO-2026-5932 for the unmaintained x/crypto/openpgp package.
    • GO-2026-5841 in github.com/klauspost/compress/s2@v1.17.11.

Those versions should be refreshed through normal dependency maintenance, but they were not forcibly upgraded in this fix because the scanner found no Nexus call path and broad transitive churn would require separate compatibility testing.

The release workflow uses common GitHub Actions by major version and a write-capable release job. Pinning actions to immutable commit SHAs would further reduce supply-chain drift. Release permissions should remain scoped to the release job and tag/manual triggers.

11. Secrets and Sensitive Data Review

No hard-coded production credential, private key, token, or certificate was found. Test secrets were confined to test fixtures.

Reviewed controls:

  • OS keychain integration.
  • Argon2id-derived AES-GCM vault and export encryption.
  • SSH host-key verification and known-host handling.
  • Bridge bearer token generation and comparison.
  • Secret prompt routing and cancellation.
  • Sensitive file permissions.
  • Logging and frontend error paths for obvious secret disclosure.

Fixed:

  • Best-effort clearing of mutable export/import plaintext, password bytes, and derived keys.
  • Private export and carve modes.
  • Prompt waiters and listeners released during shutdown.

Residual:

  • Go strings and library copies cannot be reliably zeroed.
  • Users may explicitly choose plaintext Telnet, RAW TCP, or non-TLS VNC.
  • A user can explicitly select insecure SSH host-key behaviour; that choice remains a visible compatibility option and should not be the default.

12. Authentication and Authorisation Review

Nexus is a single-user desktop client rather than a multi-tenant server. Its primary authorisation boundary is the logged-in OS account plus the Wails renderer/backend boundary.

Checked:

  • Local bridge endpoints retain bearer-token authentication.
  • SSH host-key callbacks are required in the reviewed direct and tunnel paths.
  • GitHub and remote-session credentials are retrieved from configured secret stores or interactive prompts.
  • Sensitive service methods validate session identifiers through the manager and validate paths, sizes, or option allow-lists where applicable.

No new authentication bypass or cross-user authorisation defect was confirmed. A future renderer compromise would still have substantial privileges because Wails-bound methods are designed for the trusted desktop UI; maintaining output encoding and a narrow method surface therefore remains important.

13. Input Validation and Output Encoding Review

Reviewed:

  • Profile fields, ports, hostnames, paths, filenames, import strategies, archive/update URLs, SSH key options, recording files, binary offsets, and base64 upload chunks.
  • HTML construction and text insertion in frontend modules.
  • Local subprocess arguments for shell, ssh-keygen, and Leviathan extraction.

Fixed:

  • net.JoinHostPort now constructs IPv4, hostname, and IPv6 endpoints in VNC, IRC SSH tunnels, and the connection tester.
  • Existing SFTP validation is now combined with a concurrency limit and lifecycle cleanup.

Scanner findings for MD5/SHA-1 in Leviathan are intentional forensic hash identifiers, not password or signature protection. Representative integer conversion and slice warnings in hostile-file parsers were manually traced to existing bounds checks; no concrete out-of-bounds path was confirmed. Parser fuzzing remains preferable to broad speculative casting changes.

14. Frontend HTML/JavaScript Robustness Review

The frontend contains numerous event listeners because each tab and modal owns interactive DOM. Reviewed tab/session paths attach handlers to ephemeral nodes that become collectable when their owning DOM is removed, while application listeners and intervals have explicit one-time or cleanup behaviour.

Current regression coverage verifies session cleanup, active latency timer behaviour, closed-tab release, safe DOM patterns, upload constraints, build hardening, and other earlier fixes.

The aggregate test harness still referenced VS Code files deleted in 4fc3b19 and a CGO flag removed by the same pure-Go migration. This caused npm test to fail before reaching its current assertions. The stale VS Code checks were removed, and the obsolete -O2 -g0 assertion was replaced with a check that the current build retains CGO_ENABLED=0. Both frontend suites now pass.

No confirmed exploitable current DOM injection was found. Some innerHTML usage remains and relies on escaping helpers or trusted static markup; future changes should prefer textContent and DOM construction for dynamic data.

15. Infrastructure and Deployment Review

Reviewed:

  • Shell, PowerShell, Makefile, and shared build helpers.
  • GitHub Actions release configuration.
  • Updater endpoint and PHP manifest delivery.
  • Cross-platform build flags and Go toolchain selection.

Fixed:

  • Unix build scripts now reject Go versions older than 1.25.12.
  • go.mod requests Go 1.26.5 while keeping 1.25.12 as the minimum supported language/toolchain floor.
  • Stale regression coverage now reflects the pure-Go build.

The updater remains a high-value trust boundary. Production release validation should verify HTTPS, hashes/signatures where supported, expected artefact names, and least-privilege release credentials. No new command-injection or manifest-escaping defect was confirmed.

16. Logging, Monitoring, and Error Handling Review

The new cleanup paths do not log credentials or secret responses. Upload cleanup treats remote partial-file deletion as best-effort because the underlying session may already be broken.

Useful future operational signals:

  • Active and rejected streaming-upload counts.
  • Reconnect attempt count and pending credential prompts.
  • Active runtime listener and session counts in a diagnostics view.
  • Resource snapshots during long-running open/close soak tests.

These should expose counts and identifiers only, never passwords, tokens, private keys, terminal contents, or bridge bearer tokens.

17. Test Coverage and Security Regression Gaps

Added:

  • Credential response routing by request ID.
  • Reconnect cancellation releases its secret prompt immediately.
  • Frontend cancellation is honoured.
  • SFTP cleanup is scoped to the owning session.
  • Active streaming uploads are bounded.
  • Service shutdown releases uploads and prompt waiters.
  • Existing permissive export files are tightened to 0600.
  • Leviathan carve directories/files use 0700/0600.

Passing:

  • Full Go test suite.
  • Focused Go race suite.
  • Go vet.
  • Complete frontend lifecycle and regression suite.
  • Frontend production build.
  • JavaScript, shell, and PHP syntax checks.
  • npm audit.
  • Reachable Go vulnerability scan.

Remaining gaps:

  • No packaged Wails UI smoke or long-duration tab/reconnect soak test.
  • No real SFTP server test proves partial-file deletion after a broken transport.
  • No live IPv6 protocol endpoint was used.
  • Hostile-file parser coverage is uneven; fuzzing should be expanded.
  • Windows ACL behaviour is not verified by POSIX permission tests.
  • External Leviathan extractors lack integration tests for time and output limits.

18. Prioritised Remediation Plan

Immediate:

  • Soak-test a packaged app while repeatedly opening, reconnecting, and closing local and remote tabs. Monitor process CPU, memory, goroutines, file descriptors, and listener/upload counts.
  • Exercise interrupted SFTP uploads against a real server and verify local handle cleanup plus remote partial-file behaviour.

Short-term:

  • Add a packaged Wails lifecycle smoke test.
  • Add fuzz targets for the highest-complexity Leviathan parsers.
  • Refresh the four module versions with unreachable advisories and run protocol compatibility tests.
  • Add metrics or a diagnostics screen for active sessions, reconnects, uploads, prompts, and event subscriptions.

Medium-term:

  • Wrap every external Leviathan extractor with context timeout, process-group termination, and output-size/file-count budgets before exposing extraction through the UI.
  • Replace remaining dynamic innerHTML paths with text nodes or narrowly reviewed rendering helpers.
  • Add real IPv6 SSH/VNC/IRC tunnel integration coverage.

Long-term:

  • Add release CI gates for full tests, race-focused tests, govulncheck, frontend audit/build, packaged smoke checks, and signed artefact validation.
  • Pin third-party GitHub Actions to reviewed immutable revisions.

19. False Positives / Needs Manual Verification

  • Gosec MD5 and SHA-1 reports in Leviathan are forensic digest features, not security authentication or password hashing.
  • Gosec subprocess reports include user-selected local shells, allow-listed SSH key generation options, and an external extraction path not exposed by the current document API. The extraction path still needs limits before future exposure.
  • File-parser integer-conversion and slice warnings were reviewed representatively; existing range checks rejected the paths inspected. Fuzzing is required for stronger assurance.
  • The four remaining Go module advisories are present in required versions, but govulncheck found no called symbol or imported vulnerable package path.
  • The fixed TLS issue had a reachable standard-library path, but actual ECH exposure was not reproduced.
  • Sensitive-buffer clearing is best-effort and must not be described as guaranteed memory erasure in Go.

20. Final Notes

The confirmed issues and their regression tests are committed in b5c7528. The most important improvement for the reported long-running-process behaviour is that credential event listeners, prompt waiters, and unfinished upload writers now have explicit owners and terminal cleanup paths.

Closing a session now cancels its reconnect work and SFTP uploads; closing all sessions drains all uploads; application or bridge shutdown also unregisters runtime listeners and releases pending prompts. This materially improves cleanup, but live soak testing is still required before claiming that every OS, third-party library, and remote-peer resource remains flat indefinitely.