Security Scanning: The Pre-Adoption Gate
Before any external code enters your stack, it passes through sec-scan — a six-category security gate that checks for committed secrets, dangerous patterns, suspicious destinations, and known CVEs. No exceptions.
You found a promising open source library. The README looks solid. The stars are high. The API fits your use case. You are about to pip install it into a system that manages real money, runs autonomous agents, and operates 24/7.
Stop. You have not scanned it yet.
What sec-scan Does
sec-scan lives at ~/.local/bin/sec-scan. It wraps bandit (Python SAST) and pip-audit (dependency CVE scanning) into a single gate with six check categories. Run it against any path before adoption:
sec-scan /path/to/repo
The six categories it checks:
1. Committed secrets. API keys, tokens, passwords, and private keys that were accidentally committed to the repository. This is the most common security failure in open source. A project with committed AWS credentials in its git history is a project that does not take security seriously — and those credentials may still be live.
2. Hardcoded credentials. Passwords, connection strings, and authentication tokens embedded directly in source code rather than loaded from environment variables. Even if they are test credentials, the pattern indicates the developer's security posture.
3. Dangerous code patterns. eval(), exec(), subprocess.call(shell=True), pickle.loads() on untrusted data, and other patterns that indicate either intentional malice or dangerous carelessness. Not every eval() is malicious, but every eval() requires justification.
4. Suspicious network destinations. Outbound HTTP calls to unexpected domains. A library that claims to be a local data processor should not be phoning home to an unknown endpoint. This check catches data exfiltration attempts and unauthorized telemetry.
5. Python SAST via bandit. Static analysis security testing that catches Python-specific vulnerabilities: SQL injection patterns, insecure use of hashlib, weak cryptography, and dozens of other CWE-mapped issues.
6. Dependency CVEs via pip-audit. Scans requirements.txt, setup.py, and pyproject.toml for known Common Vulnerabilities and Exposures in the dependency tree. A library with a clean codebase but a dependency with a critical CVE is still a risk.
Exit Codes and What They Mean
sec-scan produces three exit codes. Each one triggers a different action:
Exit 0 — CLEAN. No issues found across all six categories. The repository passes the security gate. Proceed to the adoption decision framework (Lesson 146).
Exit 1 — WARN. Issues found that require human review. These are not automatic blockers but they demand attention. A WARN might indicate a pattern that looks suspicious but has a legitimate explanation — a test file using eval() for assertion purposes, for example. Review each warning. Clear it with justification or flag it as a blocker.
Exit 2 — FAIL. Critical issues found. Committed secrets, known CVEs with high severity scores, or patterns strongly associated with malicious code. A FAIL is a hard stop. Do not adopt. Do not override. The code does not enter your stack until the issues are resolved — either by the upstream maintainer or by your own remediation after forking.
What Each Check Catches in Practice
Secrets scanning is not academic. In production adoption reviews, we have caught:
- AWS access keys committed in a
.env.examplefile that was clearly a copy of the real.env - Slack webhook URLs in test fixtures — live webhooks that still worked
- Private keys in configuration templates with comments like "replace with your own" — but the original key was still valid
Dangerous patterns are equally common. Libraries that shell out to system commands with unsanitized input. Data processing tools that use pickle.loads() on user-provided data — a known remote code execution vector in Python. When you are building competitive intelligence systems that handle sensitive market data, these patterns are not just code smells — they are attack vectors.
Dependency CVEs are the most insidious category because they are invisible. Your direct dependency is clean. Its dependency has a known vulnerability. Its dependency's dependency has another. You are three layers deep in someone else's supply chain, and pip-audit is the only thing standing between that CVE and your production system.
The parallel: a security scan that runs before every adoption — even an imperfect one — is infinitely better than a thorough audit that you keep meaning to do and never get around to.
Integrating sec-scan Into Your Workflow
The scan is the first step in the adoption pipeline. Before you evaluate whether to adopt (Lesson 146), before you design the wrapper (Lesson 147), before you write a single line of integration code — you scan.
# Step 1: Clone the candidate repo
git clone https://github.com/org/promising-tool /tmp/promising-tool
# Step 2: Run sec-scan
sec-scan /tmp/promising-tool
# Step 3: Check exit code
echo $? # 0=CLEAN, 1=WARN, 2=FAIL
If the exit code is 2, stop. You are done evaluating this tool. Either find an alternative or fork and remediate — but the original does not enter your stack.
If the exit code is 1, review each warning. Document your assessment of each flagged item. If every warning has a legitimate explanation and the risk is acceptable, proceed. If any warning lacks justification, treat it as a FAIL.
If the exit code is 0, proceed to the adoption decision framework.
Beyond the Initial Scan
The pre-adoption scan is not a one-time event. Dependencies change. Maintainers push updates. New CVEs are disclosed against packages you already adopted.
The 90-day review cycle (Lesson 149) includes re-running sec-scan against every adopted dependency. A tool that was clean six months ago may have accumulated issues. A dependency that passed pip-audit in January may have a critical CVE disclosed in March.
Security is not a gate you pass once. It is a condition you maintain continuously.
Lesson 145 Drill
Pick three open source tools you are currently using in production. Clone their latest versions. Run sec-scan against each one.
- Record the exit code for each
- For any WARN results, review each flagged item and document your assessment
- For any FAIL results, determine whether the issue exists in the version you are running
- If a FAIL exists in your production version, prioritize remediation this week
This exercise takes thirty minutes. The alternative — discovering a committed secret or a critical CVE after it has been exploited — takes weeks to remediate and may cost you more than time.
Bottom Line
Open source is not inherently dangerous. But it is inherently untrusted until verified. The sec-scan gate exists because trust is not transferred by GitHub stars, README quality, or community reputation. Trust is earned by passing a concrete, automated security check that examines the actual code for actual risks.
Six categories. Three exit codes. One rule: The gate is simple. The discipline is what makes it work.