Files
2026-11-04 14:29:22 -06:00

217 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Antivirus false positives — what is actually happening and what to do about it
LiveWall is flagged by a handful of engines out of seventy. This page explains why, what has already
been done about it, in what order to fix the rest, and what to tell users in the meantime.
Last reviewed: 2026-11-04, for `LiveWall-Setup-1.8.0.exe`.
---
## 1. What the scan actually said
VirusTotal, first submission 2026-11-04, **3 of 71 engines**:
| Engine | Verdict | What that engine is telling you |
|---|---|---|
| SecureAge (APEX) | `Malicious` | Reputation/heuristic verdict; APEX is well known for flagging new, unsigned, low-prevalence files. |
| Trapmine | `Malicious.high.ml.score` | A pure machine-learning score. No signature, no analyst: "this file shape looks like things we have seen". |
| VBA32 | `TScope.Malware-Cryptor.SB` | "SB" = **solid block**. VBA32 scores the NSIS solid archive as a crypter. |
Undetected: **Microsoft Defender, Kaspersky, BitDefender, ESET, Avast/AVG, Malwarebytes, Sophos,
Symantec, Trend Micro, McAfee, GData, Ikarus, ClamAV, DrWeb, CrowdStrike, SentinelOne, Palo Alto,
Fortinet, Webroot**, and 50 more.
Facts from the report that explain the three verdicts:
* **File is not signed.** No Authenticode signature, no publisher.
* **First submission = last submission.** Prevalence zero. Reputation engines have nothing to go on,
so they fall back to heuristics — and the fallback is "guilty until seen a lot".
* **DetectItEasy: `Installer: Nullsoft Scriptable Install System (3.11-1) [zlib,solid]`.** NSIS is the
single most abused installer format in the world, and `/SOLID` hides each file's structure behind
one compressed stream. That is exactly what the VBA32 and Trapmine scores are reacting to.
* Nothing else: no packer (UPX), entropy of `.text` is 6.09 (normal), imports are ordinary, the file
has proper version info (Product, Description, File Version, Copyright).
**This is not a detection of behaviour in the app.** The three engines never ran it — these are static
or reputation verdicts on an unsigned installer stub.
---
## 2. Why a wallpaper app trips heuristics at all
Beyond "unsigned + unknown", the app's own behaviour looks like the shape of a threat to a scanner:
| The app does | Scanners see |
|---|---|
| Finds `WorkerW`, re-parents a hidden window into the shell desktop | "hides a window inside Explorer" |
| Registers global hotkeys | "installs system-wide input handling" |
| Optionally starts with Windows (HKCU `Run`) | "persistence" — **off by default** in LiveWall |
| Loads .NET assemblies from `%APPDATA%\LiveWall\plugins` | "executes code from a user-writable directory" — **off by default**, needs two explicit consents, hash-pinned |
| Ships WebView2 and plays YouTube | "network access" |
None of that is malicious, and none of it is unique to LiveWall — every live-wallpaper app does the
first two. But it means the app will be *judged on reputation*, not on inspection. That is why the
answer is not "make the code cleaner", it is "get a signature and get seen".
Things that were already right (keep them that way): no bundled offers, no telemetry, no admin rights
(`RequestExecutionLevel user`), per-user install, real version metadata on both the installer and the
binaries, uninstaller registered, no obfuscation, no UPX.
---
## 3. Fixes, in order of how much they actually help
### 3.1 Sign everything with Authenticode (the only real fix)
An unsigned download is *the* variable here. It is also what every vendor replies with when you file a
false-positive report ("please sign your binaries").
* **EV code-signing certificate** (~$300–500/year, hardware token/HSM): SmartScreen and Defender
reputation trust it immediately, and heuristics weight signed files far higher.
* **OV code-signing certificate** (~$100–300/year): works, but reputation accumulates over weeks of
downloads. Expect fewer and fewer flags as it builds.
* **Self-signed certificate: do not bother.** An untrusted signature is worth no more than no
signature, and sometimes less.
* Sign **both** the published binaries and the installer, and let NSIS sign the uninstaller it
generates (`installer/sign.ps1` and the `SIGNTOOL` hook in `LiveWall.nsi` do all of this). Always
timestamp (RFC 3161) so signatures survive certificate expiry.
```powershell
# after signing, every file reports a publisher instead of "Unknown publisher"
.\installer\sign.ps1 -Thumbprint <sha1-of-cert> # or -Pfx .\codesign.pfx
```
### 3.2 Report the false positive — every one of the three
Vendors fix these in days when you tell them. Submit the file (or its hash), say what it is, and ask
for a reclassification. Use the "Contact vendor" link on the VirusTotal page for each detection, and:
| Vendor | Where |
|---|---|
| **Microsoft** (even though it currently passes — keeps Defender's cloud verdict clean) | <https://www.microsoft.com/en-us/wdsi/filesubmission> → *Software developer* → "I believe this file is incorrectly detected" |
| **SecureAge** | support@secureage.com, or the contact form on secureage.com — attach the VT link |
| **Trapmine** | Trapmine support (contact form / support@trapmine.com) — quote the exact ML verdict |
| **VBA32** | virus@vba32.com (their sample/FP mailbox) |
Text that works — it gives the analyst everything they need in one screen:
> Subject: False positive — LiveWall 1.8.0 installer (NSIS), unsigned open-source wallpaper app
>
> Hello,
>
> Your engine reports `<verdict>` for SHA-256
> `7242a2a3fd6fc142279aecf2ea83f02501af4df3fdd1ecfe7c481bf6aa7a1764`
> (`LiveWall-Setup-1.8.0.exe`, VirusTotal: <link>).
>
> LiveWall is a free live-wallpaper app for Windows 11 (GIF/video/YouTube on the desktop). The file is
> an NSIS 3.11 installer built by our own script from our own source; it installs per-user into
> `%LOCALAPPDATA%\Programs\LiveWall`, needs no admin rights, contains no bundled offers, no telemetry,
> no obfuscation and no downloader. It is currently unsigned while certification is in progress.
>
> The detection looks like a heuristic on the NSIS solid archive rather than on behaviour. Please
> reclassify. I can provide the source, the build script, signed builds, or any further sample you
> need.
>
> Thank you.
Also worth doing once: create a **VirusTotal account** and use *Reanalyze* after reporting, and keep the
VT link in the release notes so users see the same picture you do.
### 3.3 Change the container, not the app
Two variants are built from the same source specifically for this:
| Build | Command | Why |
|---|---|---|
| `LiveWall-Setup-1.8.0.exe` | `bash installer/build-installer.sh` | solid LZMA, smallest (709 KB) |
| `LiveWall-Setup-1.8.0-lzma.exe` | `COMPRESS=lzma OUT_SUFFIX=-lzma bash installer/build-installer.sh` | no solid block, one stream per file (809 KB) |
| `LiveWall-Setup-1.8.0-zlib.exe` | `COMPRESS=zlib OUT_SUFFIX=-zlib bash installer/build-installer.sh` | no solid block, no LZMA at all (972 KB) |
| `LiveWall-1.8.0-portable.zip` | `.\build.ps1 -Task portable` | **no executable container at all** — a plain zip of the app |
Upload the variants to VirusTotal and keep the one that scores cleanest. The zlib build is the one to
try first if VBA32/Trapmine are the only remaining flags: "solid" and "lzma" are exactly what those two
score. The ZIP walks around the whole class of problems — nothing to unpack, nothing to score as a
self-extracting stub — and is a perfectly good distribution format for a 2.7 MB app that needs the
.NET 8 Desktop Runtime anyway.
Longer term, a **signed MSI (WiX)** or **MSIX** is the most "boring" container Windows offers, at the
cost of more build work. Not worth it before signing.
### 3.4 Build reputation
* Publish from **one identity, consistently**: same certificate, same publisher name in the version
resources (`Company`, `LegalCopyright`, `OriginalFilename`), same download host.
* Get real download volume — GitHub Releases, winget (`winget-pkgs`), Chocolatey, PortableApps,
Scoop. High prevalence is itself an allow-list for every ML engine.
* Keep the source public and linked from the download page. Analysts and users both use it.
* Don't re-release new hashes constantly: every build resets file reputation. Batch fixes.
### 3.5 Keep the plugin system's shape defensible
The plugin system is the most "malware-shaped" feature in the app (loading arbitrary .NET assemblies
from `%APPDATA%`). It is already as gated as a design can be, and it is worth saying so in any
submission or user-facing explanation:
* the system is **off by default** (`Plugins.Enabled = false`);
* enabling it shows a mandatory third-party-code warning that must be acknowledged;
* each plugin is hashed (SHA-256) and shows its hash, publisher and permissions in its own warning
before a single line of it runs;
* the approved hash is pinned — a changed DLL is unverified again and stops loading;
* nothing is ever downloaded or executed automatically, and there is no network component in the loader.
---
## 4. What to tell users right now
Wording that is honest and de-escalates:
> **Heads-up about antivirus warnings.** `LiveWall-Setup-1.8.0.exe` is currently flagged by 3 of 71
> engines on VirusTotal (SecureAge, Trapmine, VBA32) and is clean on the other 68, including Microsoft
> Defender, Kaspersky, BitDefender, ESET and Malwarebytes. The three are reputation/ML verdicts on an
> installer that is not yet code-signed — not behaviour detections. The installer is built from the
> source in this repository, installs per-user without admin rights, and contains no telemetry, no
> bundled offers and no downloader.
>
> * Check it yourself: VirusTotal link, SHA-256 `…` (matches the file you downloaded).
> * Vendor reports filed on 2026-11-04; these verdicts typically clear within a few days.
> * Prefer no installer at all? Use the portable ZIP: unpack it and run `LiveWall.exe`.
> * If your AV quarantines it anyway: send me the engine name and the detection name, and add an
> exclusion only if you are comfortable doing so.
Two rules for that message: never tell users to "just disable your antivirus", and always give them a
hash they can verify.
---
## 5. Checklist per release
- [ ] `.\build.ps1 -Task publish`
- [ ] `bash installer/build-installer.sh` (and optionally the `-zlib` variant)
- [ ] `.\installer\sign.ps1 -Thumbprint <cert>` — verify every file has a publisher
- [ ] Upload the installer + `LiveWall.exe` to VirusTotal, check the score
- [ ] Publish the SHA-256 of every downloadable file in the release notes
- [ ] `.\build.ps1 -Task portable` as the fallback download
- [ ] If a new engine flags it: report with the template above, then *Reanalyze* a day later
- [ ] Keep a note of who flagged which version, so you can tell whether a change helped
## 6. Tracking
| Version | File | Result | Notes |
|---|---|---|---|
| 1.8.0 | `3d472fa6…3deba` | 3/71 — SecureAge, Trapmine (ML), VBA32 (TScope.Malware-Cryptor.SB) | unsigned, solid LZMA, first seen today |
| 1.8.0 (rebuild) | `7242a2a3…a1764` | to be measured | version-info improvements; same container |
| 1.8.0 (zlib) | `78cde58c…fc4b` | to be measured | no solid block — expected to clear VBA32/Trapmine |
| 1.8.2 | `843425a9…f321c` | to be measured | input-shield + cursor fixes; same container as 1.8.0 (unsigned, solid LZMA) |
| 1.8.2 (zlib) | `cb175d79…023a9` | to be measured | non-solid variant |
| 1.8.2 portable ZIP | `016c5793…7652e` | to be measured | no installer stub at all |
| 1.8.3 | `ce642909…a5d06` | to be measured | redesigned installer (same NSIS container, same compressor) |
| 1.8.4 | `d2de043f…906e4` | to be measured | side-menu layout fix; same container |
Also worth uploading to VirusTotal, because engines inspect them once the installer has run:
`prebuilt\LiveWall.exe` (SHA-256 `7ecaa8e2ada4833ce4b84388f17da0b5605e87cb4c3348577b23e26476c953cc` before the
last rebuild) and `LiveWall.Sdk.dll`. If those come back clean while the installer does not, that alone
proves the verdict is about the NSIS container.
Portable fallback for this build: `LiveWall-1.8.0-portable.zip`,
SHA-256 `83ce64aed61232afd6e5a39d55bf8856b4630d958de37cdc42386b92f43ab506`.