The Uncomfortable Truth
Right now, on the machine you are reading this on, there are probably dozens of secrets sitting in plain sight.
Your OPENAI_API_KEY is set as an environment variable — visible to every process you run. Your ~/.aws/credentials file has your AWS access key in cleartext. There is an SSH private key in ~/.ssh/id_rsa that has no passphrase. You have three .env files across various project directories, each with database credentials and tokens. Your clipboard may still have an API key you copied an hour ago.
Now ask yourself: if an AI assistant running locally on your machine wanted to read all of this, could it?
The answer is almost certainly yes.
I built shadowscan to make this concrete. Run one command. See exactly what an AI — or any process running as you — can read right now.
What shadowscan does
shadowscan is a local security scanner. It checks eight categories of exposure and generates a risk-rated report. Zero network calls. All findings stay on your machine. Secret values are always redacted.
SHADOW SCAN REPORT
==================
[CRITICAL] ~/.aws/credentials — AWS access key found
[HIGH] ENV: OPENAI_API_KEY — API key exposed to all child processes (sk-a****)
[HIGH] ~/.ssh/id_rsa — Unencrypted SSH private key
[MEDIUM] Dotenv file found: /home/user/project/.env — review manually
[LOW] Clipboard — empty
Overall risk: CRITICAL | Findings: 5
Run 'shadowscan explain <category>' for details and fix instructions.
That output is from a typical developer machine. The (sk-a****) is the redaction format — first four characters, then ****. You see enough to identify the key, never enough to use it.
The eight scan categories
| Category | What it checks |
|---|---|
env |
Environment variables matching secret patterns (*KEY*, *TOKEN*, *SECRET*, *PASSWORD*, ...) |
creds |
~/.aws/credentials, ~/.netrc, ~/.pypirc, ~/.npmrc
|
ssh |
~/.ssh/id_* — checks for unencrypted private keys |
dotenv |
.env files in current directory and home (2 levels deep) |
clipboard |
Clipboard content — detects secrets via heuristics |
mcp |
Claude and Cursor MCP config files for embedded API keys |
git |
Last 50 commits for accidentally committed secrets |
tmp |
/tmp/ for files with sensitive-sounding names |
The MCP config scanner is the one that surprises people most. If you use Claude Desktop or Cursor, your MCP configuration file may contain API keys embedded directly in the JSON. Most developers set those up once and never think about them again.
How it works under the hood
Every scanner inherits from a single abstract base class:
from abc import ABC, abstractmethod
from shadowscan.models import Finding
class BaseScanner(ABC):
"""All scanners must inherit from this and implement scan()."""
@abstractmethod
def scan(self) -> list[Finding]:
"""Run the scanner and return a list of findings."""
...
def redact(self, value: str) -> str:
"""Return first 4 characters of value followed by '****'."""
if len(value) <= 4:
return "****"
return value[:4] + "****"
Clean contract. Each scanner is independent and testable in isolation. The redact method is the only place where secret values are transformed — it runs before anything reaches the reporter.
The privacy contract
shadowscan makes four guarantees:
- Zero network calls. No HTTP, DNS, or socket calls of any kind. The binary can run fully air-gapped.
- No file writes. Reads files, never writes to them.
-
All values redacted in output. Secret values are truncated to 4 characters +
****. - No persistent state. Each run is stateless. No scan history is stored.
These are not aspirational. The test suite includes test_no_network.py which patches socket.socket to raise immediately and verifies every scanner still completes cleanly.
Install and run
pip install shadowscan
# Full scan
shadowscan run
# Faster scan — skips git history and tmp
shadowscan run --quick
# Explain a specific category
shadowscan explain env
shadowscan explain mcp
# Check version
shadowscan version
What did your machine find?
Run it and drop your risk level in the comments — CRITICAL, HIGH, MEDIUM, or LOW. No need to share findings. Just the level.
My guess: most developers reading this will hit HIGH or CRITICAL on the first run.
GitHub: https://github.com/LakshmiSravyaVedantham/shadowscan
Top comments (0)