Developer machines are the new attack surface. They hold high-value assets — GitHub tokens, cloud credentials, SSH keys — and routinely execute untrusted code through dependencies and AI-powered tools. Recent supply chain attacks have shown that malicious VS Code extensions can steal credentials, rogue MCP servers can access your codebase, and compromised npm packages can exfiltrate secrets. EDR and traditional MDM solutions monitor device posture and compliance, but they have zero visibility into the developer tooling layer:
Dev Machine Guard is complementary to EDR/MDM — not a replacement. Deploy it alongside your existing tools via MDM (Jamf, Kandji, Intune) or run it standalone.
Quick Start
The steps below install the binary directly and are intended for community users evaluating Dev Machine Guard on a single machine.
Enterprise customers should not install the binary manually. Deploy Dev Machine Guard across your fleet using the loader script through your MDM or EDR tooling. See the Installation Script documentation for the supported, auto-updating deployment flow.
Install from release (community)
Download the latest binary for your platform from GitHub Releases. Release asset filenames embed the version (for example, stepsecurity-dev-machine-guard-1.18.1-darwin), so the snippets below resolve the latest tag first rather than hardcoding a version.
macOS (universal binary — Apple Silicon and Intel)
VERSION=$(curl -fsSL https://api.github.com/repos/step-security/dev-machine-guard/releases/latest | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//')
curl -fsSL "https://github.com/step-security/dev-machine-guard/releases/download/v${VERSION}/stepsecurity-dev-machine-guard-${VERSION}-darwin" -o stepsecurity-dev-machine-guard
chmod +x stepsecurity-dev-machine-guard
# Run the scan
./stepsecurity-dev-machine-guard
Windows (PowerShell)
$version = (Invoke-RestMethod https://api.github.com/repos/step-security/dev-machine-guard/releases/latest).tag_name.TrimStart('v')
$arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { 'arm64' } else { 'amd64' }
Invoke-WebRequest -Uri "https://github.com/step-security/dev-machine-guard/releases/download/v$version/stepsecurity-dev-machine-guard-$version-windows_$arch.exe" -OutFile "stepsecurity-dev-machine-guard.exe"
# Run the scan
.\stepsecurity-dev-machine-guard.exe
Linux
VERSION=$(curl -fsSL https://api.github.com/repos/step-security/dev-machine-guard/releases/latest | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//')
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -fsSL "https://github.com/step-security/dev-machine-guard/releases/download/v${VERSION}/stepsecurity-dev-machine-guard-${VERSION}-linux_${ARCH}" -o stepsecurity-dev-machine-guard
chmod +x stepsecurity-dev-machine-guard
# Run the scan
./stepsecurity-dev-machine-guard
Pre-built .deb and .rpm packages are also available on the releases page.
Build from source
git clone https://github.com/step-security/dev-machine-guard.git
cd dev-machine-guard
make build
./stepsecurity-dev-machine-guard
Requires Go 1.26+. The binary has zero external dependencies.
Usage
stepsecurity-dev-machine-guard [COMMAND] [OPTIONS]
Commands
Output Formats
Options
Examples
# Pretty terminal output (default)
./stepsecurity-dev-machine-guard
# JSON output
./stepsecurity-dev-machine-guard --json
./stepsecurity-dev-machine-guard --json | python3 -m json.tool # formatted
./stepsecurity-dev-machine-guard --json > scan.json # to file
# HTML report
./stepsecurity-dev-machine-guard --html report.html
# Verbose scan with npm packages — shows progress spinners and timing
./stepsecurity-dev-machine-guard --verbose --enable-npm-scan
# Scan specific directories instead of $HOME
./stepsecurity-dev-machine-guard --search-dirs /Volumes/code
./stepsecurity-dev-machine-guard --search-dirs /tmp /opt # multiple dirs
# Pipe JSON through jq to extract just AI tools
./stepsecurity-dev-machine-guard --json | jq '.ai_agents_and_tools'
# Count IDE extensions
./stepsecurity-dev-machine-guard --json | jq '.summary.ide_extensions_count'
# Check for MCP configs (exit 1 if any found — useful in CI)
count=$(./stepsecurity-dev-machine-guard --json | jq '.summary.mcp_configs_count')
[ "$count" -gt 0 ] && echo "MCP servers detected!" && exit 1
# Disable colors for piping or logging
./stepsecurity-dev-machine-guard --color=never 2>&1 | tee scan.log
# Enterprise: configure all settings interactively
./stepsecurity-dev-machine-guard configure
# Enterprise: view saved configuration (API key masked)
./stepsecurity-dev-machine-guard configure show
# Enterprise: install scheduled scanning (launchd / systemd / schtasks)
./stepsecurity-dev-machine-guard install
# Enterprise: one-time telemetry upload
./stepsecurity-dev-machine-guard send-telemetry
# Enterprise: scan even when the dashboard-managed scan cadence says "not due"
# (equivalent env var: STEPSEC_FORCE_SCAN=1; disable gating: STEPSEC_DISABLE_RUN_GATE=1)
./stepsecurity-dev-machine-guard send-telemetry --force-scan
# Enterprise: remove scheduled scanning
./stepsecurity-dev-machine-guard uninstall
Configuration
Run configure to set up enterprise credentials and default search directories:
./stepsecurity-dev-machine-guard configure
This interactively prompts for all configurable settings:
View current settings:
./stepsecurity-dev-machine-guard configure show
Configuration (~/.stepsecurity/config.json):
Customer ID: my-company
API Endpoint: https://api.stepsecurity.io
API Key: ***a1b2
Scan Frequency: 4 hours
Search Directories: $HOME, /Volumes/code
Enable NPM Scan: auto
Enable Brew Scan: auto
Enable Python Scan: auto
Color Mode: auto
Output Format: pretty
Log Level: error
Configuration is saved to ~/.stepsecurity/config.json with 0600 permissions (owner read/write only).
To use a custom device ID, add "device_id": "my-device-123" to the existing
config JSON, or set Device ID through configure. The override is also
supported in JSON supplied to configure --from-file. An omitted, empty, or
whitespace-only value uses the machine serial as before. The agent continues
reporting the actual machine serial in serial_number. WSL guest scans derive
separate IDs from the host ID and distro ID.
Choose an ID unique within your customer and keep it stable: changing the ID registers a separate device in the backend; it does not migrate existing history.
CLI flags always override config file values — this matches the shell script behavior. For example, if your config has output_format: json, running ./stepsecurity-dev-machine-guard --pretty uses pretty output. To clear a value during configuration, enter a single dash (-).
Logging and Verbose Mode
By default in community mode, progress messages (spinners, step details) are suppressed — you only see the final output. This keeps stdout clean for piping.
# Default: quiet — clean output, no progress spinners
./stepsecurity-dev-machine-guard --json > scan.json
# Verbose: show progress spinners and step timing
./stepsecurity-dev-machine-guard --verbose
# Fine-grained control: set log level
./stepsecurity-dev-machine-guard --log-level=info
# Save log level in config so it persists across runs
./stepsecurity-dev-machine-guard configure
In enterprise mode (send-telemetry, install), progress is always shown regardless of the log level — the output is captured as execution logs and sent to the backend for debugging.
What It Detects
See SCAN_COVERAGE.md for the full catalog of supported detections.
Package Configs & Suspicious Files
Beyond inventorying what is installed, Dev Machine Guard inspects how each machine is configured to pull packages, and whether any files associated with known attacks are present.
Package-manager config auditing
Compromised packages most often reach a machine because that machine resolves directly from a public registry with no cooldown window against freshly published versions. Dev Machine Guard audits the package-manager configuration on each machine across every scope (project, user, and global) and resolves three things per package manager:
- Effective registry — the registry packages actually resolve from, accounting for configuration precedence, so you can confirm machines route through StepSecurity Secure Registry or an internal artifact manager rather than straight to the public registry.
- Cooldown policy — whether a cooldown window against newly published packages is in effect.
- Authentication surface — what credentials are configured against the registry.
Configuration is read from .npmrc (npm), pnpm config, bunfig.toml (bun), .yarnrc / .yarnrc.yml (yarn classic and berry), pip.conf (pip), Go's go/env and process environment (proxy, checksum database, private-module and auth settings, redacted on the device), and Cargo's .cargo/config.toml files and process environment (registries, source replacement, proxy and TLS settings, redacted on the device). In enterprise mode this rolls up into the Package Configs view in the dashboard, where you can spot machines that are unprotected or pointed at the wrong registry.
Composer auditing reads selected global config.json, root manifests and verified process overrides. It reports observed repository, proxy, TLS and plugin settings with credentials redacted. It does not infer the repository that supplied a package or execute Composer to reconstruct runtime configuration. See PHP Packages for scope and limits.
NuGet auditing reads project, ancestor, user and machine NuGet.Config files plus verified process overrides. It reports package sources, source mapping, fallback folders, proxy, TLS and audit settings with credentials redacted, and records which configuration applied to each project and restore. It never executes dotnet or nuget or reads credential-provider output. See .NET Packages for scope and limits.
Ruby auditing reads RubyGems gemrc files and Bundler global, project and process settings for the resolved developer. It reports package sources, mirrors, install and cache paths, proxy, TLS and checksum settings with credentials redacted, and records which configuration applied to each project. It never executes ruby, gem or bundle, and reads ~/.gem/credentials for existence only. See Ruby Packages for scope and limits.
Enterprise Device Policy can also set StepSecurity Secure Registry as the sole user-level Python index for pip and uv. It manages only the resolved developer's user configuration and shared StepSecurity .netrc entry, keeps pip and uv results independent, and restores owned settings on an explicit policy clear. Project files, virtual environments, system configuration, environment variables, direct URLs, and Poetry are not modified.
Suspicious file detection
Some supply chain attacks plant files that trigger code execution outside the package lifecycle scripts most tools watch — for example a malicious binding.gyp that runs during npm install, or an editor configuration file that runs when a project is opened. Dev Machine Guard ships a rules-engine scanner that flags these files as IOCs and wires the results into scan telemetry. The detector streams one file at a time, so scan memory stays bounded regardless of repository size.
The detection rules are authored and maintained by StepSecurity, so the feature works out of the box with nothing to configure. As new attack techniques are identified, the rule set is updated centrally and your machines are evaluated against the new rules automatically. In enterprise mode, flagged files surface in the Suspicious Files view with a confidence level and attribution to the associated attack campaign.
Output Formats
Pretty Terminal Output (default)
./stepsecurity-dev-machine-guard
JSON Output
./stepsecurity-dev-machine-guard --json
See examples/sample-output.json for the full schema, or Reading Scan Results for the schema reference. Recent scans also emit package-manager configuration inventory and pnpm_audit / bun_audit / yarn_audit results on the wire payload.
HTML Report
./stepsecurity-dev-machine-guard --html report.html
Community vs Enterprise
Enterprise mode requires a StepSecurity subscription. Start a 14-day free trial by installing the StepSecurity GitHub App.
Enterprise Setup
# 1. Configure credentials (interactive)
./stepsecurity-dev-machine-guard configure
# 2. Install scheduled scanning (launchd on macOS, systemd on Linux, schtasks on Windows)
./stepsecurity-dev-machine-guard install
# 3. Or run a one-time telemetry upload
./stepsecurity-dev-machine-guard send-telemetry
# 4. Uninstall scheduled scanning
./stepsecurity-dev-machine-guard uninstall
Open-source commitment: StepSecurity enterprise customers use the exact same binary from this repository. There is no separate closed-source version — all scanning capabilities are developed and maintained here in the open. Enterprise mode adds centralized infrastructure (dashboard, policy engine, alerting) on top of the same open-source scanning engine.
How It Works
Dev Machine Guard is a single compiled binary that scans your developer environment. Here's what it does and — importantly — what it does not do:
What it collects:
- Installed IDEs, AI tools, and their versions
- IDE extension/plugin names, publishers, and versions (VS Code, Cursor, Windsurf, Antigravity, JetBrains, Eclipse, Xcode, Android Studio)
- Browser extension records read from the browsers' own state files (Chrome, Edge, Firefox): identity, enabled state, install source, and the permissions the browser currently honours. Browsing history, cookies, saved passwords, and page content are never opened
- MCP server configuration (server names and commands only)
- Node.js, Homebrew, Python, and system package listings (opt-in)
- Package-manager configuration: effective registry, cooldown policy, and authentication surface across every scope (
.npmrc, pnpm config,bunfig.toml,.yarnrc/.yarnrc.yml,pip.conf) - Suspicious files flagged by StepSecurity-maintained malicious-file rules (path and matched rule only — file contents are not collected)
Detection uses platform-specific methods: /Applications/ and Info.plist on macOS, %LOCALAPPDATA%/%PROGRAMFILES% and Windows Registry on Windows, /opt//usr/share/.desktop files on Linux, and $PATH lookups on all platforms.
What it does NOT collect:
- Source code, file contents, or project data
- Secrets, credentials, API keys, or tokens
- Browsing history or personal files
- Any data from your IDE workspaces
In community mode, all data stays on your machine. Nothing is sent anywhere.
In enterprise mode, scan data is sent to the StepSecurity backend for centralized visibility. The source code is fully open — you can audit exactly what is collected and transmitted.
Building from Source
# Build
make build
# Run unit tests (with race detector)
make test
# Run integration smoke tests
make smoke
# Run linter
make lint
# Clean build artifacts
make clean
Project Structure
cmd/stepsecurity-dev-machine-guard/ # Binary entry point
internal/
├── buildinfo/ # Version and build metadata
├── cli/ # Argument parser
├── config/ # Configuration file management and configure command
├── detector/ # All scanners (IDE, AI CLI, agents, frameworks, MCP, extensions, Node.js) — cross-platform
├── device/ # Device info (hostname, serial, OS version)
├── executor/ # OS abstraction interface (enables mocked unit tests)
├── launchd/ # macOS launchd install/uninstall
├── lock/ # PID-file instance locking
├── model/ # JSON struct types
├── output/ # Formatters (JSON, pretty, HTML)
├── progress/ # Progress spinner and logging
├── scan/ # Community mode orchestrator
├── schtasks/ # Windows Task Scheduler install/uninstall
├── systemd/ # Linux systemd user timer install/uninstall
└── telemetry/ # Enterprise mode orchestrator and S3 upload
How It Compares
Dev Machine Guard is not a replacement for dependency scanners, vulnerability databases, or endpoint security tools. It covers a different layer — the developer tooling surface — that these tools were never designed to inspect.
Dev Machine Guard fills the gap by inventorying what is actually running in your developer environment. Deploy it alongside your existing security stack for complete coverage.
Known Limitations
- Package scanning (Node.js, Homebrew, Python) is opt-in in community mode and results are basic (package manager detection and package/project lists). Full dependency tree analysis is available in enterprise mode.
- MCP config auditing shows which tools have MCP configs (source, vendor, and config path) but does not display config file contents in community mode. Enterprise mode sends filtered config data (server names and commands only, no secrets) to the dashboard.
- System package scanning (rpm, dpkg, pacman, apk, snap, flatpak) is Linux-only.
- Package-manager config auditing reports the effective registry, cooldown status, and authentication surface from configuration files; it reflects configuration as written and does not intercept package installs at runtime.
- Suspicious file detection flags files that match StepSecurity-maintained rules and records the path and matched rule. It does not collect or transmit file contents. Confidence levels and attack-campaign attribution surface in the enterprise dashboard.
Roadmap
Check out the GitHub Issues for planned features and improvements. Feedback and suggestions are welcome — open an issue to start a conversation.
JSON Schema
See examples/sample-output.json for a complete sample of the JSON output, or Reading Scan Results for the full schema reference.
Contributing
We welcome contributions! Whether it's adding detection for a new AI tool, improving documentation, or reporting bugs.
See CONTRIBUTING.md for guidelines.
Quick contribution ideas:
- Add a new AI tool or IDE to the detection list
- Improve documentation
- Report bugs or request features via issues
Resources
- Changelog
- Scan Coverage — full catalog of detections
- Release Process — how releases are signed and verified
- Deploying via SCCM — Windows fleet rollout via Microsoft Configuration Manager (signed MSI, no PowerShell)
- macOS TCC Permissions — how the agent handles Documents/Downloads/Mail TCC dirs and network volumes (container-runtime mounts), PPPC profile for MDM-pushed Full Disk Access and network-volume pre-approval, and the
include_tcc_protected/include_network_volumesconfig fields - macOS MDM packaging — ready-made PPPC
.mobileconfigfor fleet deployment - Versioning — why the version starts at 1.8.1
- Security Policy — reporting vulnerabilities
- Code of Conduct
License
This project is licensed under the Apache License 2.0.
If you find Dev Machine Guard useful, please consider giving it a star. It helps others discover the project.