Scanning local drives
A command-line agent that runs the engine fleet against an attached disk — a USB drive, an external SSD, a forensic copy — on the machine the disk is plugged into. The drive is never uploaded.
Private preview. The agent ships behind a feature flag and is enabled per organisation. Talk to us if you want it turned on for yours.
1Why it runs locally
Vulnios' cloud pipeline fetches a target and scans it on a managed worker. That model cannot work for an attached disk, for two independent reasons:
- The data would have to travel. Uploading a multi-terabyte drive to scan it is impractical, and for most of the drives people want scanned — incident-response copies, client media, decommissioned disks — it is exactly the thing you are trying to avoid.
- The worker cannot reach your desk. A cloud container has no path to
/Volumes/MyDrive.
So the agent inverts it: the engines come to the data. Scanning happens on your machine, and only findings are ever sent anywhere — and only if you ask for them to be.
2Results that admit what they missed
The design principle that matters most here: a scanner that could not read the disk must never report a clean disk. Every engine returns one of three outcomes, and they are not interchangeable:
assessed
The engine read the target and evaluated it. Findings are meaningful, including zero findings.
not applicable
Nothing in scope for this engine to assess — no package manifests for a dependency scanner, for instance.
engine error
The engine did not assess the target: missing binary, permission denial, timeout, unreadable output. Never presented as clean.
An engine that errors reports no counts at all. “0 findings” on a failed engine is indistinguishable from a clean scan, so it is not offered. The scan exits non-zero whenever any requested engine failed to assess, and the report says so on its face rather than in a footnote.
A real example. On a 1 TB drive, one vulnerability engine exited successfully but produced a report too large to parse. The honest outcome is engine_error with the reason stated and the raw report retained — not a green tick over an unread result.
3Install
Requires Node.js 22.12 or newer. Engines are installed separately, and you only need the ones you intend to run.
# macOS — engines brew install clamav yara gitleaks syft grype trivy osv-scanner # ClamAV ships without signatures; fetch them once freshclam # Vulnerability databases (first run downloads ~100 MB) grype db update trivy fs --download-db-only /tmp
Then confirm what the agent can actually see:
vulnios-agent doctor --mount /Volumes/MyDrive
doctor lists which engine binaries are present and runs the mount preflight described below. Run it before a long scan rather than discovering a missing engine an hour in.
4macOS permissions
Grant Full Disk Access to your terminal, then restart it.
System Settings → Privacy & Security → Full Disk Access (or Files and Folders → Removable Volumes). macOS applies the grant only to newly launched processes, so the terminal must be restarted afterwards.
This matters more than it sounds. When macOS denies a read, it does not always return an error — depending on the volume, the directory listing can come back silently empty. An agent that scanned that listing would report a clean drive that nobody read.
So the agent refuses to start when the listing is empty but the volume reports substantial space in use, and names the application you need to grant access to. It is deliberately a hard stop, not a warning.
5Running a scan
Local only — nothing leaves the machine:
vulnios-agent scan disk \ --mount /Volumes/MyDrive \ --engines clamav,gitleaks,trivy,grype,syft \ --engine-timeout 21600
Reporting findings to your Vulnios organisation is an explicit opt-in via --org-id:
vulnios-agent enroll --api-url <url> --enrollment-id <id> --token <token> vulnios-agent scan disk --mount /Volumes/MyDrive --org-id <orgId>
Useful flags:
--include/--exclude— narrow the scope to specific paths.--local-out <dir>— where the report and raw engine output are written. Outputs persist, so an interrupted scan keeps its evidence.--engine-timeout <seconds>— per-engine budget. A drive-wide malware pass on a large disk legitimately runs for hours.
Enrollment tokens are single-use and expire in 15 minutes. Generate them from Settings → Agents, where you can also revoke or rotate an agent's credential — both take effect on the agent's very next request.
6Which engines apply to a drive
Most of the fleet reads a filesystem, so most of it applies. What does not is worth stating plainly, because a tool that silently skips engines is as misleading as one that silently fails them:
Applies to a drive
Malware signatures and rules, secret detection, SBOM generation, dependency and OS-package vulnerabilities, IaC and source analysis, and file-forensics tooling.
Does not
Network and web scanners take a URL or host, not a path. Some host-audit tools would report on the container they run in rather than your drive, so they are excluded rather than run misleadingly.
Source and IaC analysers only produce signal if the drive actually holds code, so asking for every engine on a photo archive will burn time for nothing. The agent tells you which engines it ran, which it skipped, and why.
7What leaves the machine
Without --org-id, nothing does.
The scan runs entirely offline and writes its report to disk. No enrollment, no account, no network call.
With cloud reporting enabled, what is sent is each engine's findings file — not your files:
- Sent: engine findings, outcomes, and coverage statistics.
- Not sent: the scanned files themselves, at any point.
One honest exception. The OSV-Scanner engine queries the OSV.dev API with package names and versions while it runs, even in local-only mode — that is how it matches vulnerabilities. The agent prints this before it starts. Drop it from --engines if that metadata must not leave the machine.
Findings files can themselves carry sensitive material — a secret scanner's output quotes the secret it found. Redaction controls are the next thing on the roadmap; until then, secret-scanning engines are kept local-output-only when reporting to the cloud.
8Limits worth knowing
- macOS first. The current agent is developed and tested on macOS. Windows and Linux hosts are on the roadmap.
- exFAT loses permissions. Drives formatted exFAT store no POSIX ownership or mode bits, so checks for unexpected setuid binaries or world-writable paths are impossible from such a copy — they need the original system.
- Archives are not deeply expanded. Large compressed files may be skipped by size limits. The report states coverage rather than implying everything was opened.
- Signature scanning is not compromise assessment. No known-signature malware is a useful fact, not a clean bill of health for a host.