This fork is alive. We love mRemoteNG and we're committed to keeping it moving forward. This Community Edition ships regular releases with security patches, bug fixes, and long-requested features — backed by proper CI, automated tests, and builds for x64, x86, and ARM64.
Full transparency: this project is built by humans and AI working together, and it only works together with you. Fixes are developed and verified by an automated pipeline — 6,600+ automated tests, adversarial cross-review between independent AI models — and we test too: we run mRemoteNG every day on the latest build, as our daily driver. What we cannot do is reproduce your setup — your network, your servers, your locale, the specific state that triggers your bug. That gap is the honest limit of our testing, and it is exactly where you come in. When a fix for your issue lands in a nightly, your test is what actually verifies it. Sometimes a fix is right on the first try; sometimes it takes rounds, and your logs, traces, and even small suggestions are what get it there. We provide the engineering, the infrastructure, and continuously updated models; you provide the ground truth we cannot generate ourselves. How it works in detail: #167.
— Robert & contributors (human + AI)
Two live releases, always:
| Release | Version | Description |
|---|---|---|
| Stable | v1.82.0 | Latest tagged release — all platforms. Recommended. |
| Nightly | rolling | Rebuilt and overwritten on every push to main. Latest changes, fully tested. |
| Legacy | v1.76.20 | Last .NET Framework 4.x release. |
| Variant | x64 | x86 | ARM64 |
|---|---|---|---|
| Framework-dependent (~21 MB) | Download | Download | Download |
| Self-contained (~108-150 MB) | Download | Download | Download |
Nightly builds (ZIP + MSI, x64) live on the nightly release, refreshed every push.
Framework-dependent requires .NET Desktop Runtime 10.0. Self-contained includes the .NET runtime — no prerequisites. MSI installs to Program Files with desktop & Start Menu shortcuts.
mRemoteNG ships entirely from GitHub Releases with a deliberately small, predictable model: one rolling nightly (everything on main, overwritten on each push) and immutable vX.Y.Z stable tags — the newest of which is exactly what the app's built-in Check for updates reports (releases/latest). We chose this over the old multi-channel, self-hosted update-feed setup because it is simpler and fully GitHub-native: no update server to run, no per-channel text files to keep in sync, and a single obvious source of truth for both users and the app. Fewer moving parts, less to break, easier to trust.
16 protocols supported: RDP, VNC, SSH, Telnet, HTTP/HTTPS, rlogin, Raw Socket, PowerShell Remoting, AnyDesk, VMRC (VMware), MSRA (Remote Assistance), OpenSSH (native Windows), Winbox (MikroTik), WSL, Terminal, Serial (COM port).
Security: PBKDF2 600K iterations, HTTPS-only vaults, SSH key wipe, AnyDesk command injection prevention, LDAP sanitization, owner-only ACL on the PuTTY credential pipe, master-password re-authentication on password copy/reveal, 4 CodeQL alerts fixed.
Enterprise: Self-contained builds (zero prerequisites), ADMX/ADML Group Policy templates, connection audit logging, JSON export, protocol/tag filtering.
Performance: Startup optimized to under 1 second with 200 connections (down from 10-30s). WMI queries, plugin loading, and IE emulation deferred to background threads. XML deserialization uses O(1) dictionary lookups instead of O(n) attribute scans.
Recent additions (nightly, ported from upstream and adapted): Clear Cached RDP Credentials action (drop the stale TERMSRV/<host> entry that overrides your configured credentials), Use Redirection Server Name RDP property for load-balance redirects (GNOME Remote Desktop --system), Explorer-style slow-click rename in the connection tree (opt-in), RD Gateway access-token inheritance from parent folders.
Quality: 6,666 automated tests (0 failures), 0 analyzer warnings, 5-level code quality pipeline (Roslynator + Meziantou + SonarCloud + CodeQL + Qodo AI Review), x64/x86/ARM64. 853 upstream issues triaged (712 released, March 2026 snapshot); 89 reports from this fork's own users, 83 closed. SonarCloud Quality Gate green: reliability, security and maintainability all A, 81.6% coverage on new code, 0.6% duplication, 100% of security hotspots reviewed.
For detailed usage, refer to the Documentation.
mRemoteNG uses Windows APIs (SendInput, DPAPI, COM Interop for RDP) that can trigger antivirus heuristic false positives. We worked directly with AV vendors to resolve all detections:
| Date | VirusTotal Score | Action |
|---|---|---|
| 2026-03-03 | 8/66 flagged | Submitted false positive reports to all flagging vendors |
| 2026-03-05 | Xcitium confirmed fix | Comodo/Xcitium whitelisted mRemoteNG |
| 2026-03-06 | 0/75 — clean | BitDefender fixed IL:Trojan.MSILZilla → cascaded to 7 OEM vendors |
Current scan: VirusTotal — 0 detections across 75 engines.
If your antivirus flags mRemoteNG, please see Antivirus False Positive Guide.
This project uses an AI orchestrator (Python, ~6,900 LOC) coordinating multiple AI agents against a backlog of 800+ upstream issues. It did not start that way, and the road here was not smooth — the history is worth keeping, because most of what the harness does today exists because an earlier version failed at it.
How the harness evolved — five generations, and what broke in each
Gen 1 — one model, hand-driven (Feb 2026). A single model, prompted manually, one issue at a time. It worked, and it did not scale: every fix needed a human to open the issue, paste context, read the diff, run the build. Throughput was bounded by the human, not the model. This is the baseline the project's measurements still compare against.
Gen 2 — three models, poorly coordinated. Adding models did not simply add throughput. Agents overwrote each other's work, re-fixed what was already fixed, and disagreed with no mechanism to resolve the disagreement. Failures were silent: an agent would report success while its edit never reached disk, or reach disk and never build. The lesson that shaped everything after: parallel agents without a protocol are slower than one agent, not faster.
Gen 3 — the orchestrator. A Python controller took ownership of the loop: issue sync, triage, agent dispatch, and — critically — build/test gating between every step, so no agent could declare victory unverified. Roles were separated by strength rather than availability (fast triage vs. deep multi-file work vs. bulk transforms). Silent failures became loud.
Gen 4 — supervision and self-healing. Long runs died in ways a single loop could not survive:
hung agents, buffered logs that made a live process look dead, orphaned build processes, sessions
that mass-committed dirty trees. Gen 4 added a supervisor, an internal auto-flushed log (stdout
redirection on Windows buffers and lies), timeouts, and hard scope rules about what an agent may
touch. Most of .project-roadmap/LESSONS.md is the scar tissue from this phase.
Gen 5 — adversarial review and human-facing discipline (current). Verification moved from "tests pass" to "an independent model family tried to break this and failed". Added on top: a hard attempt budget (two failed premise-based fixes → the next build must ship instrumentation, not a third guess), a blocking security tripwire, and honest reporter communication. This generation came directly out of a public failure — four consecutive fixes on one issue missed, and a reporter said so bluntly. The rules exist so the cost of a miss lands on the pipeline, not on the person who reported the bug.
The agent stack is maintained continuously — every agent runs on its family's current flagship model at maximum reasoning effort, and pinned versions are treated as drift to be fixed, not as stability. Model releases are picked up as they ship. Five agents are in the loop today, and the roster grows as capable models appear:
| Agent | Role in the loop |
|---|---|
| Claude (Anthropic) | Main thread: root-cause analysis, multi-file fixes, WinForms / COM interop, and final review of every other agent's output |
| Codex (OpenAI) | Fast triage, single-file patches, and independent adversarial review via the codex-rescue contract |
| Gemini (Google) | Long-context analysis, bulk transforms, and independent adversarial review via the gemini-rescue contract |
| Grok (xAI) | Adversarial counter-opinion from a fourth model family — tasked with refuting a proposed fix, not confirming it |
| Qodo | AI review on pull requests, complementing SonarCloud + CodeQL |
Why several families rather than one strong model: correlated blind spots. A single model — however capable — repeats its own mistakes under review. Independent families disagree, and the disagreements are where wrong fixes get caught. Two recent examples from this repo: a proposed focus fix was killed in review because it would have broken Quick Connect, and a follow-up implementation was caught with a stale-state hole before it shipped. Both were found by an agent whose explicit job was to break the fix, not to approve it.
Human direction sits on top: the maintainer directs the work, reviews what ships, and takes over directly when automated rounds fail (hard rule: after two missed fixes the pipeline ships instrumentation instead of a third guess, and after three failed rounds a human takes the issue). What the pipeline cannot do is reproduce your environment — which is why reporter testing is treated as the most valuable contribution this project receives, and why every fix announcement says plainly that it is an automated fix awaiting your verification.
A pipeline that turns issue text — written by anyone on the internet — into code has one serious risk, and it is worth naming publicly. It is not crude "ignore your instructions" injection. It is a plausible bug report whose obvious fix happens to be a vulnerability: "connections only work if I disable certificate validation", "encrypted files won't open on my other PC, use a fixed key", "SSH fails unless host-key checking is off". Each reads like a genuine bug. Each fix would pass all 6,400 tests, because weakening a security property breaks nothing functional.
So the rules are mechanical, not aspirational:
- Reporter input is data, never instructions. A report describes a symptom; it does not get to name the fix. A stated cause, file, or patch is a hypothesis to verify against the source.
- A security tripwire blocks delivery, not just review.
scripts/security-tripwire.shruns as a pre-commit hook and refuses any change touching cryptography, key derivation, credential handling, authentication, database connectors or transport ACLs — or introducing security-relevant tokens anywhere in the tree. The automated pipeline cannot override it; only a human can, and the commit must record which security property was examined and why it still holds. - Every diff passes a security lens before it is built: does this weaken certificate or host-key validation, key derivation, credential storage, authorization, ACLs, input validation, or the release path?
- When a fix would weaken a security property, the answer is a different fix — or an honest explanation to the reporter. Never the weakening. If your issue is closed with "we won't do that, here's why", this is why.
- Issue-sourced requests to change CI, signing, tokens or release infrastructure are never acted on.
We will keep hardening this. These guardrails are a floor, not a finished design — the roadmap includes signed commits, branch protection with required checks, tighter least-privilege scoping for the automation's credentials, and provenance for release artifacts. As the pipeline does more, the constraints around it get tighter, not looser. If you spot a gap in this model, open an issue — that report is as valuable as any bug report, and it will be treated the same way.
Key results:
- 712/853 issues addressed (83.5%), 1,400+ commits, 7 regressions (1.2%)
- Cost: ~$320 total, stabilized at $1.49/commit (down from $4.02 on day 1)
- Best session: Codex Spark resolved 89/104 issues (86%) autonomously in a single run
- Quality: 5,247 analyzer warnings → 0 (drifted back to 181 and re-cleared 2026-08-13 — zero is a state to maintain, not a milestone)
- Code review: every fix now goes through independent Codex and Gemini counter-opinions before commit — each reviewer re-derives the root cause from the source first, so agreement means two models reached the same diagnosis independently, and disagreement surfaces bad fixes (in a recent batch the dual review caught and discarded an incorrect proposed fix before it shipped)
- 4 upstream PRs backported: URL injection fix, AD Protected Users, VNC Caps Lock, RDP resize
The complete research documentation is in scientific-paper/:
| Document | What's inside |
|---|---|
| PAPER.md | Full research paper — hypothesis, architecture, results, discussion |
| METHODOLOGY.md | Formal methodology, instruments, metrics, baseline |
| RELATED_WORK.md | Comparison with SWE-bench, Devin, Aider, AutoCodeRover, MetaGPT |
| COST_ANALYSIS.md | Detailed cost breakdown and learning curve |
| FAILURE_CATALOG.md | Post-mortems: 31-hour disaster, 7 regressions, Codex repo wipe |
| EVIDENCE.md | Verifiable data trail (git history, CI artifacts, metrics) |
Figures below were re-verified against live sources on 2026-08-15. Where a number is historical (a snapshot from an earlier phase) it is dated as such.
Upstream backlog (snapshot, 2026-03-02). All 853 upstream issues tracked at the time were triaged and classified:
| Status | Count | % |
|---|---|---|
| released | 712 | 83.5% |
| wontfix | 116 | 13.6% |
| duplicate | 25 | 2.9% |
Post-triage verification (2026-03-02): All 195 testing-status issues were resolved: 179 bulk-verified via commit hash validation, 3 manually verified, 13 reclassified during wontfix correction. Wontfix repass found 38% imprecision in AI triage (47/123 were implementable); corrected to 116 with individual justifications.
Status definitions:
- released — fix committed, build/test verified, included in a release
- wontfix — classified as out-of-scope (upstream limitation, requires hardware, or not reproducible)
- duplicate — merged with another issue tracking the same root cause
The fork's own inbox (live, 2026-08-15). Since the fork started accepting reports directly, 89 issues have been opened by external reporters and 84 are closed; 5 issues are open, all of them either fixed and awaiting reporter confirmation or deliberately left open with the reason stated in the thread. The upstream tracker now stands at 873 issues followed, against 841 currently open upstream.
This inbox is the part that matters day to day: it is where the pipeline meets real users, and where its failures are visible. See #167 for how reports are handled and what we ask of reporters.
5,247 analyzer warnings → 0 across 100+ files in a single session using parallel AI agents (Claude Opus + Sonnet; later passes added Codex and Gemini in parallel).
Zero is a state to maintain, not a milestone to announce. The backlog came back: by August 2026
it had drifted to 181 warnings — 139 of them from a single missing <Nullable> setting in the test
project — and was cleared again on 2026-08-13. Two lessons worth recording: an incremental build
re-emits nothing for unchanged projects, so a "clean" build can be an artefact of not rebuilding
(verify only after forcing a full rebuild); and a warning sweep is not cosmetic — that pass
surfaced four genuine defects, including a primary key built from a nullable column lookup and an
unguarded dereference in a log message.
| Phase | What was done | Count fixed |
|---|---|---|
| Autofix | CA1507 nameof, CA1822 static, CA1805 defaults, CA1510 ThrowIfNull, CA2263 generics, CA1825 Array.Empty |
~1,300 |
| String comparisons | MA0006 string.Equals, CA1309/CA1310 StringComparison, CA1304 IFormatProvider, MA0074 overloads |
~400 |
| Collection safety | MA0002 StringComparer on Dictionary/HashSet, MA0015/MA0016 enum comparison |
~350 |
| Misc fixes | CA1806, CA2201, CA1069, CA1305, CA1872, CA1850, CA1869, CA2249, RCS1075 | ~200 |
| Suppressed | 46 architectural/legacy rules demoted in .editorconfig (CA1711, CA5351, MA0062, etc.) |
~3,000 |
SonarCloud bugs fixed (beta.6): S2259 (null reference ×6), S2583 (dead branch), S4275 (getter/setter mismatch ×2), S1751 (no-op loop ×2), S3903 (missing namespace ×2), S3456 (redundant ToCharArray ×3), S2674 (unchecked Read), MA0037 (stray semicolon ×4). All ObjectListView issues (25) dismissed as won't fix — vendored dependency outside our control.
SonarCloud on fork (live, 2026-08-15): Quality Gate green. Reliability, security and maintainability all rate A, coverage on new code is 81.6% against an 80% threshold, duplication 0.6%, and 100% of security hotspots are reviewed.
Getting there was not a matter of adjusting thresholds. The gate went red on the security rating with six open findings, and each was examined on its merits: the private key a credential vault hands to PuTTY was being written to a temp file with a predictable name and an inherited DACL (a real weakness — now a random name and an owner-only DACL applied at creation); two regexes running over remote-influenced input had no timeout; the RSA "weak key" findings were false positives on a method that imports an existing key rather than generating one, and were made unambiguous rather than suppressed; and one hard-coded-credential finding is a genuine false positive on 1Password API field metadata, left annotated rather than obfuscated to please a scanner.
Then the gate stayed red on coverage, for a reason worth admitting: 63 of the uncovered lines were a maintenance script written the day before, being measured as product code. Tooling that never reaches a user is now scoped out of analysis, and the rest was covered with real tests rather than exclusions — including the SQL diagnostics that only execute while a save is already failing.
The earlier "PASSED — A/A/A, 80.7% coverage" figure was from the March 2026 upstream-PR push and was left in this README long after it stopped being true. That is exactly the failure mode this revision is meant to end.
TreatWarningsAsErrors enforced for compiler rules (CS0168, CS0219, CS0162, CS0164). Next: extend to analyzer rules once stable.
We use mRemoteNG ourselves, every day, on the latest build. That is the first line of human testing and it catches a real class of problems: startup regressions, broken tab handling, settings that do not persist, anything that makes the app unpleasant to live with.
What it cannot cover is someone else's environment — a specific SQL Server version, a MariaDB in strict mode, an RDP gateway, a locale where the regional format differs from the display language, a machine where a session drops at exactly the wrong moment. Several of the hardest bugs fixed here were invisible to both the test suite and our daily use, and only became findable when the reporter sent a log. That gap is the honest limit of testing on our side, and it is why reporter confirmation is treated as the real verification.
Why automated tests alone are not enough: beta.5 shipped 7 AI-introduced regressions out of 585 changes that passed all 6,201 automated tests at the time. A ~1.2% miss rate sounds tolerable until you look at what got through — one regression (PuTTY root save) would have silently destroyed a user's connections.
Protocol: a manual session at every release, focused on UX flows that cannot be unit tested:
- Tree navigation: click, double-click, drag-drop, context menu — no phantom tabs
- Tab management: switch, close, reorder — no focus stealing, no hangs
- Save/load round-trip:
confCons.xmlsurvives save → close → reopen → save - COM lifecycle: connect → disconnect → reconnect → close — no RCW crashes
- Settings persistence: change settings → restart → verify persistence (especially Portable mode)
Rewritten 2026-08-15. The previous version of this table described the March 2026 upstream-PR push and had gone stale — items were listed as unsolved that were fixed months ago, and the genuinely open problems below were missing entirely. The six open security findings that headed this list the same day are now resolved and the SonarCloud gate is green; that entry is gone, which is the most useful thing that can happen to a row in this table.
| # | Problem | Status | Why it's hard |
|---|---|---|---|
| 1 | Virtual list row-count desync (#149) | Guarded, not root-caused | SetVirtualListSize swallows an ArgumentOutOfRangeException when assigning VirtualListSize; the control then reports a stale row count while the model has grown, and an expand computed a redraw range of 427 against a 41-row list. The crash is contained by a guard and the condition is now instrumented, but the failing assignment has never been reproduced. It lives in vendored ObjectListView code shared by every list in the app, so a speculative fix is worse than the guard |
| 2 | VNC disconnect race (#166) | Narrowed, not closed | VncSharpCore polls the framebuffer on its own thread and marshals connection loss back with Control.Invoke; if the handle is gone, that throws on a thread we do not own and kills the process. Our teardown now stops the session while the handle is alive, which closes the common path — but the remaining window belongs to the package (v1.2.1), not to us |
| 3 | Legacy SQL upgraders swallow every provider error | Logged, narrowing deferred | The two oldest schema upgraders catch DbException and skip. Correct for the expected duplicate-object error, wrong to do silently for a permission or connectivity failure. They now classify and log what they skipped; tightening the catch waits on real field logs, because guessing the provider error set wrong turns a working legacy import into a hard failure |
| 4 | NUnit parallelization impossible | Architectural | Shared mutable singletons (DefaultConnectionInheritance.Instance, Runtime.EncryptionKey, Runtime.ConnectionsService) make fixture-level parallelism race. Multi-process isolation (9 groups, sliding-window concurrency) works but is slower. Fixing it properly means dependency injection throughout the application — a multi-month refactor |
| 5 | MSBuild output path vs. dotnet test |
Workaround | MSBuild outputs to bin/x64/Release/; dotnet test --no-build against the csproj looks in bin/Release/. Coverage cannot be collected through the standard dotnet test --collect path; the dotnet-coverage workaround functions but adds a tool dependency |
| 6 | Upstream PR #3189 still open | Waiting, understandably | 765 files, ~64K insertions. A diff that size is genuinely hard to review responsibly, and the upstream maintainers built this project — their caution is reasonable. The lesson is on our side: future contributions go upstream as smaller, focused PRs |
| 7 | Reporter confirmation is the bottleneck | Structural | Of the fork's closed external issues, a large share were closed on code and test evidence without the reporter ever replying. Those fixes are probably right, but "probably" is the honest word. There is no way around this other than making it easy and worthwhile to reply — which is what the transparency work is for |
Gen 5 is running, and it is not the "fully autonomous maintenance" that earlier drafts of this section aimed at. The target changed because the failure mode changed: throughput stopped being the constraint, and confidence became it. An agent that ships four wrong fixes quickly is worse than one that ships a right fix slowly.
What Gen 5 actually does:
- Verification is adversarial, not confirmatory. Before a non-trivial fix ships, an independent model family is tasked with breaking it — not reviewing it politely. Findings from that pass have killed fixes that would have shipped, including one that would have broken Quick Connect.
- Autonomy is bounded by an attempt budget. Two failed fixes on an unproven premise, and the next build must ship instrumentation instead of a third guess. Three failed rounds, and a human takes the issue. This is enforced in the pipeline's own instructions, not left to judgement.
- Security has a mechanical stop. A tripwire blocks delivery of any change touching cryptography, credentials, authentication or transport ACLs, regardless of test results, because weakening a security property breaks no test.
- Transparency is part of the output. Every fix announcement states that it is an automated fix awaiting the reporter's verification, and every guard that is not a root-cause fix says so.
- Some harnesses look for defects nobody reported. The persistence tests no longer assert a hand-written list of fields; they compare every property by reflection, across the XML, SQL and CSV backends, so a field that stops round-tripping fails immediately instead of waiting for a user to notice it missing. That pass found seven defects that were never reported — including connection Notes, which a SQL profile had silently discarded since the backend was written: no column, no write, no read, and no error. Silent data loss is the class least likely to arrive as a bug report, because the user has no reason to suspect the application rather than themselves.
Target state: not "no humans" — humans on the decisions that need judgement (security impact, scope, whether a repeated failure needs a different approach) and the pipeline on everything that can be verified mechanically.
PR #3189 (beta.6) passed the SonarCloud Quality Gate on 2026-03-01 after resolving 6 security vulnerabilities (S2068 ×3, S8264 ×2, S8233 ×1) and 50 security hotspots reviewed as SAFE. As of 2026-08-15 it is still open — 765 files, ~64K insertions. PR #3188 (beta.5) has since been closed as its predecessor.
Upstream currently has 841 open issues (873 tracked by our orchestrator). This fork addressed 712 of the 853 triaged in the March snapshot. We understand a diff that size takes time to review responsibly — the upstream team built this project and their careful stewardship is what makes it worth contributing to. The correction is ours to make: future upstream contributions go as smaller, focused PRs, because a 765-file PR asks more of a reviewer than is reasonable.
Additionally, 4 upstream copilot draft PRs (#3177, #3176, #3154, #3171) have been reviewed and their fixes backported to our fork's main branch, ahead of upstream merge.
The convergence runs in both directions. In July 2026 every upstream commit since the March sync point (~230, mostly dependency bumps) was triaged against this fork; the substantive pieces we lacked were ported and adapted: the Use Redirection Server Name RDP property (#3314, extended here with SQL-schema persistence upstream does not have), the Clear Cached RDP Credentials action (#3315), Explorer-style slow-click rename (#3251), RD Gateway access-token inheritance (#3243), and the PuTTY credential-pipe ACL hardening class. The same review surfaced and fixed a pre-existing CSV export bug of our own (#141) — porting with independent model review cuts both ways. Dependencies were synced to upstream levels at the same time (SqlClient 7, log4net, WebView2, AWSSDK).
This project demonstrates a reproducible model: orchestrator + supervisor + multi-model AI + human oversight applied to a legacy codebase with a large backlog.
The model is not specific to mRemoteNG. Any project with hundreds of open issues, a test suite, and a build system could benefit from the same approach. The orchestrator code is ~6,900 lines of Python — not trivial, but not a research project either.
The economics make it viable: ~$1.50/commit, 24/7 operation, no burnout, no context switching. This is complementary to human developers, not a replacement — humans set direction, review output, and handle the 30% that AI cannot.
Note: This section has not yet undergone peer review. Projections and priorities are subject to revision.
| Version | Date | Highlights |
|---|---|---|
| v1.82.0 | 2026-07-02 | First stable of the 1.82 line (.NET 10). GitHub-Releases-only update check, WebAuthn/FIDO2 + Entra ID auth, MSI installer (WiX 6), MS Remote Desktop + MobaXTerm importers, host-status LED icons, startup ~10s→1.2s, plus the 2-release model and a repo-wide simplification cleanup |
| v1.81.0 | 2026-03-02 | First stable of the 1.81 line — SonarCloud Quality Gate A/A/A, 0 analyzer warnings, upstream PR #3189 |
| v1.81.0-beta.6 | 2026-03-01 | SonarCloud Quality Gate pass on upstream PR #3189 — 6 security vulnerabilities fixed, 50 hotspots reviewed, 5,247→0 analyzer warnings, 4-level code quality (Roslynator + Meziantou + SonarCloud + CodeQL), coverage collection via dotnet-coverage, workflow permissions hardened (S8264/S8233), upstream sync with v1.78.2-dev |
| v1.81.0-beta.5 | 2026-02-27 | 7 manual-testing regressions fixed, AV false positive hardening (SendInput, DefaultDllImportSearchPaths, VirusTotal in CI), PortableSettingsInitializer for .NET 10, 5,963 tests |
| v1.81.0-beta.4 | 2026-02-25 | AV hardening, test suite expansion 2,916 → 5,963 via TestCaseSource parametrization |
| v1.81.0-beta.3 | 2026-02-24 | 585 issues addressed (70% of 838), 744 commits, 7 new protocols, 81s→ms deserialization fix, orchestrator v2 (Claude-only, self-healing supervisor) |
| v1.81.0-beta.2 | 2026-02-15 | 2,554 nullable warnings fixed (100% clean, 242 files), testable architecture via DI |
| v1.80.2 | 2026-02-14 | AlwaysShowPanelTabs initialization fix |
| v1.80.1 | 2026-02-13 | Security patch — AnyDesk command injection, Process.Start hardening, .NET 10.0.3 |
| v1.80.0 | 2026-02-10 | Self-contained builds, 6 security hardening items, external tool tokens, JSON export, live theme switching, 830-issue triage complete |
| v1.79.0 | 2026-02-08 | 26 bug fixes, 81 pre-existing test failures fixed, LDAP sanitizer, .NET 10 with x64/x86/ARM64 |
Full details: CHANGELOG.md | All releases
# Requires Visual Studio BuildTools (VS2026 or VS2022) with .NET SDK
# Full build (~15s on 48-thread Threadripper):
pwsh -NoProfile -ExecutionPolicy Bypass -File build.ps1
# Fast incremental (~9s, skips restore):
pwsh -NoProfile -ExecutionPolicy Bypass -File build.ps1 -NoRestore
# Self-contained (embeds .NET runtime, ~108-116MB output):
pwsh -NoProfile -ExecutionPolicy Bypass -File build.ps1 -SelfContainedNote:
dotnet builddoes not work — the project has COM references (MSTSCLib for RDP).build.ps1uses full MSBuild via VS BuildTools and auto-detects the newest VS installation.
| Level | Tool | Scope | Status |
|---|---|---|---|
| 1 | Roslynator + Meziantou Analyzers | Every local build | Active |
| 2 | SonarCloud | Push to main — quality gate |
|
| 3 | CodeQL | Push to main + weekly — security scanning |
|
| 4 | .NET Analyzers | AnalysisLevel=latest-recommended |
Active |
| 5 | Qodo Code Review | On-demand AI review | Complements static analysis |
0 analyzer warnings in main project. TreatWarningsAsErrors enforced for compiler rules (CS0168, CS0219, CS0162, CS0164). 46 noisy/architectural rules suppressed in .editorconfig for legacy WinForms code. Next: extend to analyzer rules once stable.
Qodo Code Review catches logic bugs that static analyzers miss — bounds checks, SQL schema mismatches, plaintext credential patterns, and validation gaps. Run on-demand via scripts/qodo-review.sh. Found and fixed: SQL INSERT missing 6 columns, URL scheme injection vulnerability (upstream #3177).
# Recommended (bash runner, 9 groups, max 2 concurrent, ~80s):
bash run-tests-core.sh
# PowerShell wrapper (builds first):
pwsh -NoProfile -ExecutionPolicy Bypass -File run-tests.ps1 -Headless
# Skip build (use existing binaries):
pwsh -NoProfile -ExecutionPolicy Bypass -File run-tests.ps1 -Headless -NoBuild6,666 tests, 9 groups with sliding-window concurrency (max 2) + 2 isolated, 0 failures.
Multi-process parallelism is required because the production code uses shared mutable singletons — NUnit fixture-level parallelism causes race conditions. Each dotnet test process gets isolated static state.
| Group | Namespace | Tests |
|---|---|---|
| 1 | Connection | 1,131 |
| 2 | Config.Xml | 151 |
| 3 | Config.Other | 889 |
| 4 | UI | 394 |
| 5 | Tools | 400 |
| 6 | Security | 176 |
| 7 | Tree + Container + Credential | 181 |
| 8 | Remaining | 3,298 |
| 9 | Integration | 44 |
| Isolated | FrmOptions (GDI handle leak) | 2 |
Counts live in test-config.json, which is the single source of truth.
A unit suite this size can be entirely green while the application does not start. It exercises classes in-process against the build output, so assembly layout, UI wiring, installer behaviour and anything involving a live protocol client are all invisible to it — which is exactly where this project's hardest bugs have been. So there are three levels, each catching what the one below cannot:
| Level | What runs | What only it can catch |
|---|---|---|
Unit suite — run-tests-core.sh |
6,666 tests, ~3 min | Logic, serialization, parsing, crypto |
UI battery — run-ui-tests.ps1 |
The built .exe, driven through UI Automation |
Startup, focus, dialogs, persistence across restarts, packaging |
Lab guest — lab-run.ps1 |
The same battery on a clean, isolated VM | Anything a warm machine already has: trusted certificates, cached host keys, answered prompts, installed runtimes |
The UI battery is gated behind the unit suite on purpose. It takes over the desktop while it runs, and there is no reason to occupy a machine for several minutes to discover a failure the cheap suite finds in three.
# UI battery on this machine (runs the unit suite first, refuses to start unless it is green)
pwsh -NoProfile -ExecutionPolicy Bypass -File run-ui-tests.ps1
# The same battery inside the isolated lab guest — build, deploy, run and report in one command
$env:MRNG_LAB_GUEST_PASSWORD = '...'
pwsh -NoProfile -ExecutionPolicy Bypass -File lab-run.ps1
# Installer: install, same-version upgrade, launch the installed app, uninstall
pwsh -NoProfile -ExecutionPolicy Bypass -File lab-msi.ps1The installer check is guest-only for the same reason it went untested for so long: it writes to Program Files and replaces whatever mRemoteNG is already installed, which is not something to do on a machine you are working on. It covers the upgrade path behind #129 — a stale-DLL bug where an upgrade left old assemblies in place — and confirms the installed application starts, which the unit suite cannot see because it runs against the build output rather than against what the installer shipped.
Why the lab guest earns its keep. The first run of the battery there found ten defects in one sitting, every one invisible on a developer machine. Three were failures reported against the product that turned out to be unanswered dialogs — an untrusted-certificate prompt, PuTTY's host-key alert, and its "close this session?" confirmation — each of which made the application look like it was refusing to exit. One was a real, long-standing focus bug (#143) that five previous fixes had missed, because the test meant to detect it could not fail: it set text through an accessibility API that bypasses Windows focus entirely.
Every scenario is paired with a control. A test that fails on a live RDP session proves nothing
unless the same test passes without one — otherwise "the session steals focus" and "clicking a text
box does not focus it here" are indistinguishable. Scenarios are labelled for what they actually
demonstrate: [Issues] when removing the fix makes them fail, [Touches] when they exercise the
neighbourhood without proving the fix, and [StressCoverage] for races, where passing means "did
not reproduce this time" rather than "fixed".
The lab is two VMs on an isolated internal network with no route to anything real: Ubuntu serving RDP, SSH, VNC and MariaDB, and a Windows Server guest that runs the battery itself.
This fork is based on mRemoteNG/mRemoteNG v1.78.2-dev. We submit fixes back upstream:
- v1.79.0: PRs #3105–#3130 (26 individual PRs)
- v1.80.0: #3133 (consolidated status)
- v1.81.0-beta.5: #3188
- v1.81.0-beta.6: #3189 — SonarCloud Quality Gate passed
This Community Edition is maintained by Geseidl IT Solutions, part of Geseidl Consulting Group — an IT infrastructure, cloud, and cybersecurity services provider in Ploiești, Romania.
We use mRemoteNG daily across our managed infrastructure (50+ servers, 300+ client connections) and built this modernized edition because we needed it to be better. The research paper documenting the AI-assisted development process is available at scientific-paper/PAPER.md.
geseidl.ro/servicii-it | About us
If you find this fork useful, please consider giving it a star — it helps others discover the project and motivates continued development.
Submit code via pull request. See the Wiki for development environment setup.
Building better tools, one commit at a time. Make it count.
make-it-count.ro
