Skip to content

Reduce antivirus false positives: embed full Windows manifests + AV docs#8

Merged
DemOnJR merged 1 commit into
mainfrom
fix-ci-rustsec
Jun 26, 2026
Merged

Reduce antivirus false positives: embed full Windows manifests + AV docs#8
DemOnJR merged 1 commit into
mainfrom
fix-ci-rustsec

Conversation

@DemOnJR

@DemOnJR DemOnJR commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Why

A user reported Kaspersky closing the running app after the Cursor-agent feature landed. Investigation this session (a multi-agent code audit + VirusTotal scans of every shipped binary) confirmed:

  • No malicious or evasion code anywhere — no packing, injection, AMSI/ETW tricks, or obfuscation.
  • The main app is statically clean: 0/75 on VirusTotal, Kaspersky's own engine included.
  • Kaspersky closing the running app is therefore purely behavioral/reputation: an unsigned binary, recompiled fresh on each user's PC (clone+compile → a brand-new hash every time → zero reputation), that spawns a hidden node.exe child (the Cursor agent) opening SSH/network.

The durable remedy is code signing — but clone+compile makes the per-user-compiled main app unsignable, so per the maintainer's choice this keeps clone+compile and ships honest hardening + a free user-side mitigation route (Kaspersky exclusion / false-positive report).

What changed (this session — commit fa05ab8)

  • Embed a complete Windows application manifest in the main app and the installer. Tauri's built-in default ships only a Common-Controls dependency (no trustInfo/asInvoker, no supportedOS, no DPI awareness), leaving the shipped exes with a bare, identity-less manifest. New src-tauri/app.manifest and installer/app.manifest declare a clear identity, asInvoker (never requireAdministrator), the Win7–11 supportedOS GUIDs, PerMonitorV2 DPI and long-path support — wired through each build.rs via WindowsAttributes::app_manifest.
  • User-facing AV guidance where users actually hit it: a callout in README.md and a note on the installer release page (installer-release.yml), both with SmartScreen "Run anyway" + Kaspersky exclusion + FP-report steps.
  • installer/ANTIVIRUS.md: full diagnosis, fresh 75-engine VirusTotal numbers, the ML-verdict-variance finding, why per-user self-signed certs don't help, and the free durable path (SignPath Foundation for OSS).
  • installer-release.yml also carries an optional Authenticode signing step (no-op unless a WINDOWS_SIGN_PFX_BASE64 secret is set).

Also in this branch (prior commit 5d50705)

This branch was already one commit ahead of main: "Remove the old signed-NSIS-bundle installer + tauri-updater path" (deletes release.yml, src-tauri/installer/*.nsi/bmp, and the tauri-plugin-updater wiring). It rides along in this PR since it's unmerged branch history.

Testing

  • VirusTotal (75 engines), all generic ML false positives that wander both directions across rebuilds of identical source (the stub even lost one — proven with a no-manifest control build): main app 0–1/75, installer 1–2/75, stub 3–4/75. No real-signature hits; Kaspersky's static engine never flags any.
  • Rebuilt the main app and installer on the GNU toolchain users compile with (cargo +stable-x86_64-pc-windows-gnu build --release): both build clean and the PEs now carry trustInfo/supportedOS/dpiAwareness (verified by inspecting the resource section); version info intact.

Reviewer notes

  • The manifest nudges one moderate-confidence ML engine (Elastic) on the main app (0→1/75) — invisible to a Kaspersky machine and trivial; kept because it's genuinely correct (DPI/long-path/identity) and the right end-state for a signed build. Easy to drop if you'd rather keep a pristine 0/75.
  • The rest of the branch's in-progress work (hooks, voice, bench, the single-exe stub) is intentionally left uncommitted and out of this PR.
  • No code logic changed — only build.rs, two manifests, and docs.

🤖 Generated with Claude Code

…tives

Kaspersky was closing the running main app after the Cursor-agent feature
landed. A multi-agent audit plus VirusTotal scans of every shipped binary
confirmed there is NO malicious or evasion code (no packing/injection/AMSI
tricks): the main app is statically clean (0/75 — Kaspersky's own engine
included). The detection is purely behavioral/reputation — an unsigned binary,
recompiled fresh on each user's PC (so a brand-new hash every time = zero
reputation), that spawns a hidden node.exe child opening SSH/network.

Honest hardening only (deliberately no packing/encryption/obfuscation):

- Embed a COMPLETE Windows application manifest in the main app and the
  installer. Tauri's built-in default ships only a Common-Controls dependency
  (no trustInfo/asInvoker, no supportedOS, no DPI awareness), leaving the
  shipped exes with a bare, identity-less manifest — part of the suspicious
  profile. New src-tauri/app.manifest and installer/app.manifest declare a
  clear identity, asInvoker (never requireAdministrator), the Win7-11
  supportedOS GUIDs, PerMonitorV2 DPI and long-path support, wired through each
  build.rs via WindowsAttributes::app_manifest. Verified it embeds and builds
  clean on the GNU toolchain users compile with (and on MSVC in CI).

- User-facing antivirus guidance where users actually hit it: a callout in
  README.md and a note in the installer release page, both with the SmartScreen
  "Run anyway" + Kaspersky exclusion + false-positive-report steps.

- installer/ANTIVIRUS.md: full diagnosis, fresh 75-engine VirusTotal numbers,
  the ML-verdict-variance finding (scores wander both directions across
  rebuilds of identical source), why per-user self-signed certs don't help, and
  the genuinely-free durable path (SignPath Foundation for OSS).

- installer-release.yml also carries an optional Authenticode signing step
  (no-op unless a WINDOWS_SIGN_PFX_BASE64 secret is set) — the durable remedy.

Per the maintainer's choice this keeps the clone+compile model and relies on
the free Kaspersky exclusion + FP-report route documented above. The branch's
other in-progress work (hooks, voice, bench, the single-exe stub) is left
uncommitted and intentionally out of this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@DemOnJR DemOnJR merged commit 170294e into main Jun 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant