Collectors What digger pulls from the host. Cross-platform first, OS-specific where it matters.
How they work
Each collector is a subclass of digger.core.collector.Collector with:
- name
- Unique identifier — used in
--only, in detector cross-references, and in artifact rows. - category
- Coarse grouping (
process,persistence,network,logs,identity,inventory, …). - supported_os
- Tuple of OSes. Collectors are silently skipped on others.
- requires_admin
- If true, collector is skipped (with a logged reason) when not running elevated.
The runner catches all exceptions per collector — a single failing collector
never aborts the case. Skip reasons and errors land in log.
Cross-platform
| Name | What it collects | Needs admin |
|---|---|---|
system | Host fingerprint, boot time, uptime, filesystems, CPU/memory | no |
processes | Every running process: pid, ppid, exe, exe SHA-256, cmdline, user, network connections per pid, open files, env sample | more detail with admin |
network | Interfaces, listening sockets, established connections, routing table, ARP cache, hostname/FQDN | some platforms |
users | Current sessions, every local account, sudo/wheel/admin group membership | no |
browsers | Chrome / Edge / Brave / Arc / Vivaldi / Opera / Firefox: history, downloads, extensions (perms + host_permissions), cookies (per-domain counts + bytes — values NEVER captured), saved-passwords summary (counts only), IndexedDB origins+bytes, Local Storage origins+bytes, installed PWAs, profile defaults (search engine / homepage / startup URLs), service workers (origins + script count + storage bytes). See browser scanner. | no |
env | Process environment with special attention to PATH, LD_PRELOAD, DYLD_INSERT_LIBRARIES, BASH_ENV, PROMPT_COMMAND, proxy vars | no |
dns | /etc/hosts, /etc/resolv.conf, DNS cache (ipconfig /displaydns, scutil --dns, resolvectl) | no |
recent_files | Files modified in the last 14 days under common drop locations (Downloads, Desktop, /tmp, %TEMP%, AppData/Local/Temp, /Users/Shared, /dev/shm…) | no |
installed_software | macOS .app bundles + brew, Linux dpkg/rpm/snap/flatpak, Windows registry Uninstall keys | no |
python_packages | pip list in the current interpreter and discovered virtualenvs | no |
npm_packages | package.json + package-lock.json + yarn.lock + pnpm-lock.yaml across common project dirs (max depth 4) | no |
github_workflows | Every .github/workflows/*.yml across local repos — for Shai-Hulud worm detection | no |
ssh_keys | ~/.ssh contents: authorized_keys, known_hosts, config, key fingerprints | no — more users with admin |
service_versions | Probes <binary> --version for 30+ services (sshd, nginx, apache, redis, postgres, mysql, mongo, openssl, curl, git, docker, php, ruby, go, node, python, kubelet, samba, bind9, etc.) — only from trusted system paths (/usr/bin, /usr/sbin, /opt/homebrew/, etc.). Used by service_cve detector against the live NVD feed. | no |
memory_regions | Per-process VM region snapshot. Records only suspect regions: RWX, anonymous-executable, or file-backed by a drop location. | some processes only |
code_signing | Code-signature status for every running binary via codesign (macOS) / dpkg -V + rpm -V (Linux). Feeds the unsigned-binary detector. | no |
Windows
| Name | What it collects | Needs admin |
|---|---|---|
windows.registry_persistence | Run/RunOnce, Winlogon, Image File Execution Options, AppInit_DLLs, Active Setup, Office Resiliency, COM CLSID, … | some keys |
windows.scheduled_tasks | schtasks /query /XML + CSV verbose dump | no |
windows.services | Every service via psutil: name, display name, start type, binpath, account, status | no |
windows.event_logs | Security, System, Application, Sysmon, PowerShell Operational, Defender Operational, Task Scheduler Operational, WMI-Activity, RDP sessions | yes |
windows.defender | Get-MpComputerStatus, Get-MpPreference, Get-MpThreat, Get-MpThreatDetection | recommended |
windows.firewall | Profiles + enabled rules via Get-NetFirewallProfile / Get-NetFirewallRule | no |
windows.wmi_persistence | EventFilter, EventConsumer, FilterToConsumerBinding (MITRE T1546.003) | recommended |
windows.startup_folders | Per-user + all-users Start Menu Startup folders | no |
macOS
| Name | What it collects | Needs admin |
|---|---|---|
macos.launchd | Every /System/Library/Launch*, /Library/Launch*, ~/Library/LaunchAgents plist (parsed: ProgramArguments, RunAtLoad, KeepAlive, MachServices, watch paths, …) | no |
macos.login_items | BackgroundTaskManagementAgent btm.plist + osascript fallback (T1547.015) | no |
macos.tcc | TCC.db — apps with camera, mic, screen recording, AppleEvents, full-disk permission | system DB needs FDA |
macos.quarantine | QuarantineEventsV2 — what was downloaded by what app from where | no |
macos.unified_logs | log show slices for auth, network, XProtect, Gatekeeper, sudo | yes |
macos.kext | kmutil showloaded + systemextensionsctl list | no |
macos.profiles | Configuration profiles (MDM + manually installed) | no |
macos.security_posture | SIP (csrutil), Gatekeeper (spctl), FileVault (fdesetup), XProtect / MRT versions | no |
macos.firewall | pf ruleset + info + NAT (pfctl -sr / -s info / -s nat) plus the macOS Application Firewall state (socketfilterfw: global state, stealth mode, block-all, logging). Audited by firewall_audit detector. | no |
macos.privesc | Walks /usr/bin, /usr/sbin, /usr/libexec, /opt/homebrew/{bin,sbin}, /tmp, /private/tmp, /Users/Shared, /Users/*, /private/var/root for setuid/setgid binaries. Each artifact records owner_uid, mode, world-writable, in-system-dir. | no |
Linux
| Name | What it collects | Needs admin |
|---|---|---|
linux.systemd | systemctl list-units + list-unit-files + per-user units; full unit files from /etc/systemd, /usr/lib/systemd, /lib/systemd, /run/systemd | no |
linux.cron | /etc/crontab, /etc/anacrontab, /etc/cron.d, /etc/cron.{hourly,daily,weekly,monthly}, /var/spool/cron, /var/spool/at | some paths |
linux.auth_logs | /var/log/auth.log + secure + journalctl _COMM=sshd / sudo + last / lastb / who | recommended |
linux.audit | auditd.conf, /etc/audit/rules.d, auditctl -l, tail of /var/log/audit/audit.log | yes |
linux.kmod | /proc/modules, lsmod, /etc/modules-load.d, /etc/modprobe.d | no |
linux.sudoers | /etc/sudoers and /etc/sudoers.d/* | yes |
Selecting and skipping
List which collectors will run on the current host:
python -c "from digger.collectors import all_collectors; \
[print(f'{c.name:30} admin={c.requires_admin}') for c in all_collectors()]"
Run only a subset:
digger collect --case-dir x --only system,processes,network,macos.launchd
Skip everything needing elevation:
digger collect --case-dir x --no-admin
Adding a new collector
See the Extending page for the full walkthrough.
Short version: subclass Collector, yield Artifacts from
collect(), register in digger/collectors/__init__.py.
Graceful degradation. CatchPermissionError,OSError,subprocess.SubprocessError, and missing binaries (shutil.which(...)is None). A collector with no artifacts to yield should just return an empty iterator — that's the only way the runner can keep going for the next collector.