What happens when you remove the usual security libraries and ask: can we still build a useful developer security tool? For Zero Dependency 2026 , we built DevGuard — a lightweight security scanner for codebases and dependency manifests using Python's standard library. The constraint was simple: Build something useful without relying on third-party runtime packages. That constraint ended up influencing almost every design decision we made. Why We Built DevGuard Developers can accidentally expose credentials through source files, environment files, private keys, and other sensitive project assets. We wanted a small security tool that could provide an immediate first layer of protection without requiring a large security stack. Instead of trying to recreate every capability of a commercial security platform, we focused on three practical checks: SecretScanner — detects likely hardcoded secrets and private-key material. FileRiskScanner — detects sensitive files such as .env , SSH keys, credential files, and certificate containers. DependencyScanner — detects dependency manifests and records declared dependencies without pretending that a dependency is automatically vulnerable. The result is DevGuard: a modular scanner with both a CLI and a lightweight local dashboard. The Architecture The core of DevGuard is built around one simple idea: every scanner should return the same kind of result. DevGuard
|
+------------+------------+
| | |
SecretScanner FileRiskScanner DependencyScanner
| | |
+------------+------------+
|
Finding Contract
|
scan_project()
/
/
CLI Web Dashboard
|
Score + Findings Each scanner implements the shared scanner interface and returns standardized Finding objects. A finding contains: file line rule severity message For example: Finding ( file = " path/to/file " , line = 12 , rule = " HARDCODED_SECRET " , severity = " HIGH " , message = " Possible hardcoded credential detected " , ) This keeps the detection logic separate from reporting and presentation. Adding another scanner therefore doesn't require redesigning the entire application. From CLI Scanner to Local Dashboard We didn't want DevGuard to stop at terminal output. So we also built a lightweight local dashboard. The backend uses Python's built-in http.server , while the frontend is plain HTML, CSS, and JavaScript. There is no Flask. There is no FastAPI. There is no React dependency. The local server exposes the scan API and serves the dashboard directly. The dashboard presents: overall security score risk level severity counts scanner-wise findings detailed finding information recommended remediation The goal is to turn a list of raw findings into something a developer can understand quickly. Turning Findings Into an Explainable Security Score Finding a security issue is useful. Understanding its overall impact is even more useful. DevGuard therefore includes a deterministic risk engine. The score starts at 100 and applies a fixed penalty for every finding: Severity Penalty CRITICAL -30 HIGH -15 MEDIUM -7 LOW -2 The final score is constrained between 0 and 100 . The score maps to a risk level: Score Risk 90–100 LOW 70–89 MEDIUM 40–69 HIGH 0–39 CRITICAL We deliberately kept this calculation simple and explainable. A developer should be able to understand why a score changed instead of trusting an unexplained security number. Secret Detection Is More Than Searching for "password" A naive scanner could search for words such as: password
api_key
api_token
access_token
auth_token
secret_key
client_secret
private_key But keyword matching alone creates false positives. For example: password = os . getenv ( " PASSWORD " ) doesn't contain the actual password. Compare that with: password = " actual-secret-value " DevGuard checks for obvious environment lookups and placeholder values before reporting a likely hardcoded secret. It also detects private-key material. The lesson we learned was: Finding more matches doesn't automatically make a security scanner better. A useful scanner needs context. Sometimes the Filename Is the Risk Secrets don't always appear inside source code. Sometimes the problem is the file itself. DevGuard checks for sensitive assets such as: .env
.env.*
id_rsa
id_dsa
id_ecdsa
id_ed25519
credentials.json
secrets.json
*.key
*.pem
*.p12
*.pfx But there is an important edge case. A file named .env.example is commonly a safe template. So DevGuard excludes known-safe environment templates such as: .env.example
.env.sample
.env.template This is a small implementation detail, but it makes the scanner much more practical. The Dependency Scanner Knows Its Limits DevGuard recognizes several dependency manifest formats: requirements.txt package.json go.mod Cargo.toml pom.xml .csproj It parses declared dependencies and reports the manifest as a finding. But DevGuard deliberately does not claim that a dependency is vulnerable simply because it exists . Finding a dependency and determining whether that dependency has a known vulnerability are two different problems. We chose to keep that boundary explicit rather than produce misleading security claims. What Turned Out Harder Than Expected The hardest part wasn't importing re or `pathlib. It was deciding what not to report. We had to account for: environment-variable lookups placeholder values binary files test and fixture directories generated directories safe environment templates different dependency manifest formats consistent findings across scanners For example, scanning a project blindly can lead to irrelevant results from directories such as: text .git/ .venv/ node_modules/ build/ dist/ tests/ fixtures/ DevGuard therefore maintains project-level exclusions. The secret scanner also skips binary files. These details aren't as visually impressive as a dashboard. But they are the details that determine whether developers will actually trust and use a security scanner. What the Standard Library Made Possible The zero-dependency constraint forced us to look at Python's standard library differently. We used standard-library modules for the core functionality: Requirement Standard Library HTTP server http.server CLI parsing argparse HTTP utilities urllib.request JSON parsing json TOML parsing tomllib XML parsing xml.etree.ElementTree File/path handling pathlib , os Pattern matching re Data models dataclasses Analytics collections Testing unittest The point wasn't that third-party packages are bad. Packages are valuable because they provide mature solutions and save development time. The interesting question was: How much functionality do we actually need, and how much of that functionality is already available? We Documented the Substitutions Too We created a STDLIB.md file to document the standard-library substitutions behind the project. Some examples include: requests → urllib.request click → argparse python-dotenv → os pathlib2 → pathlib tomli → tomllib simplejson → json This wasn't about claiming that a standard-library module is always a complete replacement for a third-party package. It was about documenting the smaller requirements DevGuard actually needed and why we chose not to add another runtime dependency. Recommendations Instead of Just Findings A scanner that only says "something is wrong" leaves the developer with the next problem: What should I do about it? DevGuard includes deterministic remediation recommendations for its known finding rules. For example, a hardcoded secret can produce guidance to move the value to an environment variable or secure secret manager. A detected private key can produce guidance to remove it and rotate or revoke it if it has been exposed. A sensitive file can produce guidance around .gitignore and environment variables. We wanted the output to be actionable rather than simply alarming. Testing Without Adding a Test Framework The zero-dependency principle also applies to testing. DevGuard uses Python's built-in unittest . The test suite covers areas including: secret detection private-key detection environment-variable handling binary-file handling sensitive-file detection dependency parsing CLI integration risk scoring risk-level calculation recommendation logic The test command is: bash python -m unittest discover -s tests -v Running DevGuard From the project root, the CLI can be run with: bash python -m devguard scan . If running directly from the source tree, the source directory can be placed on PYTHONPATH : powershell $env:PYTHONPATH="src" python -m devguard scan . The scanner returns a non-zero exit code when findings are detected, which makes the CLI suitable for automation. What We Learned The biggest lesson wasn't that third-party packages are unnecessary. They aren't. The lesson was that dependencies should solve a problem we actually have . Without the usual libraries, we had to think more carefully about: what the scanner really needed how findings should be represented how false positives should be reduced how the dashboard should communicate risk how much parsing was actually necessary where a dependency would genuinely add value The standard library didn't magically build DevGuard for us. It gave us the building blocks. We still had to design the architecture, handle edge cases, define the scanner contract, build the risk model, and decide what the tool should and should not claim. The Empty requirements.txt Was the Easy Part At first, "zero dependency" sounded like a restriction. By the end, it felt more like an engineering exercise. The interesting part wasn't avoiding pip commands. It was learning to ask: What problem are we actually solving? Then: What is the smallest reliable implementation we can build? And finally: Does the standard library already give us the pieces we need? DevGuard is our answer to those questions. A small security scanner. A modular architecture. A local dashboard. An explainable risk model. Actionable recommendations. And a runtime that doesn't depend on a third-party security framework. DevGuard at a Glance Language: Python Runtime dependencies: 0 Core focus: Developer security and codebase scanning Scanners: Secret, File Risk, Dependency Interfaces: CLI + local web dashboard Testing: Python unittest Standard-library documentation: STDLIB.md Key Features Hardcoded secret detection Private-key detection Sensitive-file detection Dependency manifest analysis Standardized Finding objects Explainable security scoring Risk-level classification Remediation recommendations Project and fixture exclusions CLI scanning Local dashboard Zero third-party runtime dependencies Try DevGuard GitHub: https://github.com/Divyarani089/DevGuard.git If you're building developer tooling under a zero-dependency constraint, we'd love to hear what you chose to implement yourself — and what you decided was still worth depending on. Final Thought DevGuard started with one constraint: Build something useful without relying on third-party runtime packages. That constraint changed how we thought about the entire project. We didn't try to replace every security tool. We focused on a specific problem, used the standard library where it made sense, documented the trade-offs, and built the smallest architecture that could support the features we wanted. Don't start with the dependency. Start with the problem.

DevGuard: A Zero-Dependency Security Scanner Built from Python's Standard Library
MRUDULA SHISHUPAL
