Software inventory tools work off install records. They read the entries behind Programs and Features, list the applications that registered themselves during setup, and produce a report you can use for license counts and patch planning.
Those records only cover software that went through an installer, and plenty of Windows software doesn’t. Portable apps, standalone executables, scripts, and anything a user runs from their own folders all execute without registering, so none of it reaches the report. The list describes the machine’s installed software while the machine runs more than that.
That gap is a minor reporting nuisance when it’s a portable tool someone downloaded to get a job done. It becomes a real problem when an attacker on a standard-user account is using the same blind spot to run code that inventory built from install records will never show you.
How inventory knows what’s on a machine
A normal installation writes an entry to a set location in the registry, drops files into Program Files, and registers the application with Windows. Programs and Features reads that entry, and inventory tools query the same place, which is why installed software appears on the list and software removed through its uninstaller drops off again.
The whole thing depends on the software cooperating. A legitimate installer registers itself because it wants to be found later for updates and clean removal, and that registration is what leaves the record behind. Built into the model is an assumption that code arrives on a machine through an install process that declares itself.
For the software you deploy and the apps users install through supported channels, that assumption holds and the report is accurate. The category it can’t see is everything that puts nothing in the registry in the first place.

The software that skips the installer
Portable applications run from any folder without installing, and many small utilities are one executable that runs on a double-click. Scripts execute through interpreters Windows already ships, and a downloaded file runs from the Downloads folder or a USB stick as it is. None of these involves a setup step or a registry entry.
What makes it possible is where the files sit. A standard user can write to and execute from their own profile directories, AppData and Temp among them, with no admin rights and no elevation prompt. Program Files is protected and the profile folder is not, so code the user can write there runs under their account, installed or not.
The categories that most often run without installing:
- Portable applications that execute from any folder
- Standalone executables run from Downloads or removable media
- Scripts run through interpreters already present on the system
- Executables in user profile paths such as AppData or Temp
Install-based inventory returns nothing for any of this, because there’s no registry entry for it to find. The code runs and Programs and Features has no record that it did.
Why attackers count on this
Malware usually lands running as a standard user, not an administrator, so it can’t write to Program Files or install itself the normal way. It runs from a folder the user controls instead. Government advisories document the pattern: in its Volt Typhoon advisory, CISA describes attackers operating on files inside a user’s AppData directory.
Persistence works off the same ground. Surviving a reboot means having something relaunch the malware, and the usual mechanisms, registry Run keys and the Startup folder, run at logon as the current user with no installer involved. MITRE ATT&CK documents these under Boot or Logon Autostart Execution and points out they resist prevention because they abuse features Windows provides on purpose.
In one case, a CISA report on a breached federal agency describes attackers keeping access through scheduled tasks while running malware that got past the agency’s anti-malware. None of this registers as installed software, which is the point of doing it this way. An executable can run out of AppData, relaunch at every logon, and reach out to an external server while the inventory still reports a clean machine.
What closes the gap
The control that addresses this watches execution instead of installation: what runs, where it runs from, and under which account. Government baselines are built around it.
Application control is the first item in the Australian Signals Directorate’s Essential Eight, written to stop execution from standard user profiles and temporary folders. CISA gives the same instruction in a nation-state threat advisory: permit execution from Program Files and System32 by default, and deny anywhere else unless an exception is granted and documented.
This is separate work from antivirus, which matches files against known-bad signatures and has to recognize a threat before it can block it. Controlling where things run doesn’t depend on knowing the file in advance.

Where it gets difficult
Application control is one of the harder Essential Eight controls to deploy, by the framework’s own account, because you have to learn what users legitimately run before you enforce, or you break their work. It’s a project rather than a setting you switch on. Even done well it won’t catch everything, since some persistence relies on legitimate Windows behavior that has to be watched for rather than blocked.
Install-based inventory still does the licensing and patch work it was built for, as long as nobody mistakes it for a full account of what can run. Admin By Request’s EPM solution works at the point where things run and elevate rather than reading install manifests, which is where the no-install activity turns up. You can try it on up to 25 endpoints with no time limit through the Free Plan.

