<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MRUDULA SHISHUPAL</title>
    <description>The latest articles on DEV Community by MRUDULA SHISHUPAL (@mrudula_22).</description>
    <link>https://dev.to/mrudula_22</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4111651%2F4447898c-91d1-455c-94cd-6fe2eba75fdb.png</url>
      <title>DEV Community: MRUDULA SHISHUPAL</title>
      <link>https://dev.to/mrudula_22</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrudula_22"/>
    <language>en</language>
    <item>
      <title>DevGuard: A Zero-Dependency Security Scanner Built from Python's Standard Library</title>
      <dc:creator>MRUDULA SHISHUPAL</dc:creator>
      <pubDate>Mon, 07 Sep 2026 16:54:32 +0000</pubDate>
      <link>https://dev.to/mrudula_22/devguard-a-zero-dependency-security-scanner-built-from-pythons-standard-library-5706</link>
      <guid>https://dev.to/mrudula_22/devguard-a-zero-dependency-security-scanner-built-from-pythons-standard-library-5706</guid>
      <description>&lt;p&gt;&lt;strong&gt;What happens when you remove the usual security libraries and ask: can we still build a useful developer security tool?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Zero Dependency 2026&lt;/strong&gt;, we built &lt;strong&gt;DevGuard&lt;/strong&gt; — a lightweight security scanner for codebases and dependency manifests using Python's standard library.&lt;/p&gt;

&lt;p&gt;The constraint was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Build something useful without relying on third-party runtime packages.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That constraint ended up influencing almost every design decision we made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Built DevGuard
&lt;/h2&gt;

&lt;p&gt;Developers can accidentally expose credentials through source files, environment files, private keys, and other sensitive project assets.&lt;/p&gt;

&lt;p&gt;We wanted a small security tool that could provide an immediate first layer of protection without requiring a large security stack.&lt;/p&gt;

&lt;p&gt;Instead of trying to recreate every capability of a commercial security platform, we focused on three practical checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SecretScanner&lt;/strong&gt; — detects likely hardcoded secrets and private-key material.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FileRiskScanner&lt;/strong&gt; — detects sensitive files such as &lt;code&gt;.env&lt;/code&gt;, SSH keys, credential files, and certificate containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DependencyScanner&lt;/strong&gt; — detects dependency manifests and records declared dependencies without pretending that a dependency is automatically vulnerable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is DevGuard: a modular scanner with both a CLI and a lightweight local dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The core of DevGuard is built around one simple idea: every scanner should return the same kind of result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 DevGuard
                     |
        +------------+------------+
        |            |            |
   SecretScanner  FileRiskScanner  DependencyScanner
        |            |            |
        +------------+------------+
                     |
              Finding Contract
                     |
                scan_project()
                 /          \
                /            \
              CLI          Web Dashboard
                             |
                   Score + Findings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each scanner implements the shared scanner interface and returns standardized &lt;code&gt;Finding&lt;/code&gt; objects.&lt;/p&gt;

&lt;p&gt;A finding contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;file&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;line&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rule&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;severity&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;message&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;Finding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path/to/file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HARDCODED_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HIGH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Possible hardcoded credential detected&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the detection logic separate from reporting and presentation.&lt;/p&gt;

&lt;p&gt;Adding another scanner therefore doesn't require redesigning the entire application.&lt;/p&gt;

&lt;h2&gt;
  
  
  From CLI Scanner to Local Dashboard
&lt;/h2&gt;

&lt;p&gt;We didn't want DevGuard to stop at terminal output.&lt;/p&gt;

&lt;p&gt;So we also built a lightweight local dashboard.&lt;/p&gt;

&lt;p&gt;The backend uses Python's built-in &lt;code&gt;http.server&lt;/code&gt;, while the frontend is plain HTML, CSS, and JavaScript.&lt;/p&gt;

&lt;p&gt;There is no Flask.&lt;/p&gt;

&lt;p&gt;There is no FastAPI.&lt;/p&gt;

&lt;p&gt;There is no React dependency.&lt;/p&gt;

&lt;p&gt;The local server exposes the scan API and serves the dashboard directly.&lt;/p&gt;

&lt;p&gt;The dashboard presents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;overall security score&lt;/li&gt;
&lt;li&gt;risk level&lt;/li&gt;
&lt;li&gt;severity counts&lt;/li&gt;
&lt;li&gt;scanner-wise findings&lt;/li&gt;
&lt;li&gt;detailed finding information&lt;/li&gt;
&lt;li&gt;recommended remediation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to turn a list of raw findings into something a developer can understand quickly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl6991ux9efdyteigxj1z.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl6991ux9efdyteigxj1z.jpeg" alt=" " width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning Findings Into an Explainable Security Score
&lt;/h2&gt;

&lt;p&gt;Finding a security issue is useful.&lt;/p&gt;

&lt;p&gt;Understanding its overall impact is even more useful.&lt;/p&gt;

&lt;p&gt;DevGuard therefore includes a deterministic risk engine.&lt;/p&gt;

&lt;p&gt;The score starts at &lt;strong&gt;100&lt;/strong&gt; and applies a fixed penalty for every finding:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Penalty&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CRITICAL&lt;/td&gt;
&lt;td&gt;-30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HIGH&lt;/td&gt;
&lt;td&gt;-15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MEDIUM&lt;/td&gt;
&lt;td&gt;-7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOW&lt;/td&gt;
&lt;td&gt;-2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The final score is constrained between &lt;strong&gt;0 and 100&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The score maps to a risk level:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Risk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;90–100&lt;/td&gt;
&lt;td&gt;LOW&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;70–89&lt;/td&gt;
&lt;td&gt;MEDIUM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40–69&lt;/td&gt;
&lt;td&gt;HIGH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0–39&lt;/td&gt;
&lt;td&gt;CRITICAL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We deliberately kept this calculation simple and explainable.&lt;/p&gt;

&lt;p&gt;A developer should be able to understand why a score changed instead of trusting an unexplained security number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret Detection Is More Than Searching for "password"
&lt;/h2&gt;

&lt;p&gt;A naive scanner could search for words such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;password
api_key
api_token
access_token
auth_token
secret_key
client_secret
private_key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But keyword matching alone creates false positives.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;doesn't contain the actual password.&lt;/p&gt;

&lt;p&gt;Compare that with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;actual-secret-value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DevGuard checks for obvious environment lookups and placeholder values before reporting a likely hardcoded secret.&lt;/p&gt;

&lt;p&gt;It also detects private-key material.&lt;/p&gt;

&lt;p&gt;The lesson we learned was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Finding more matches doesn't automatically make a security scanner better.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A useful scanner needs context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sometimes the Filename Is the Risk
&lt;/h2&gt;

&lt;p&gt;Secrets don't always appear inside source code.&lt;/p&gt;

&lt;p&gt;Sometimes the problem is the file itself.&lt;/p&gt;

&lt;p&gt;DevGuard checks for sensitive assets such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.env
.env.*
id_rsa
id_dsa
id_ecdsa
id_ed25519
credentials.json
secrets.json
*.key
*.pem
*.p12
*.pfx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is an important edge case.&lt;/p&gt;

&lt;p&gt;A file named &lt;code&gt;.env.example&lt;/code&gt; is commonly a safe template.&lt;/p&gt;

&lt;p&gt;So DevGuard excludes known-safe environment templates such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.env.example
.env.sample
.env.template
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a small implementation detail, but it makes the scanner much more practical.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dependency Scanner Knows Its Limits
&lt;/h2&gt;

&lt;p&gt;DevGuard recognizes several dependency manifest formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requirements.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go.mod&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pom.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.csproj&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It parses declared dependencies and reports the manifest as a finding.&lt;/p&gt;

&lt;p&gt;But DevGuard deliberately &lt;strong&gt;does not claim that a dependency is vulnerable simply because it exists&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Finding a dependency and determining whether that dependency has a known vulnerability are two different problems.&lt;/p&gt;

&lt;p&gt;We chose to keep that boundary explicit rather than produce misleading security claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Turned Out Harder Than Expected
&lt;/h2&gt;

&lt;p&gt;The hardest part wasn't importing &lt;code&gt;re&lt;/code&gt; or `pathlib.&lt;/p&gt;

&lt;p&gt;It was deciding what &lt;strong&gt;not&lt;/strong&gt; to report.&lt;/p&gt;

&lt;p&gt;We had to account for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;environment-variable lookups&lt;/li&gt;
&lt;li&gt;placeholder values&lt;/li&gt;
&lt;li&gt;binary files&lt;/li&gt;
&lt;li&gt;test and fixture directories&lt;/li&gt;
&lt;li&gt;generated directories&lt;/li&gt;
&lt;li&gt;safe environment templates&lt;/li&gt;
&lt;li&gt;different dependency manifest formats&lt;/li&gt;
&lt;li&gt;consistent findings across scanners&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, scanning a project blindly can lead to irrelevant results from directories such as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;text&lt;br&gt;
.git/&lt;br&gt;
.venv/&lt;br&gt;
node_modules/&lt;br&gt;
build/&lt;br&gt;
dist/&lt;br&gt;
tests/&lt;br&gt;
fixtures/&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;DevGuard therefore maintains project-level exclusions.&lt;/p&gt;

&lt;p&gt;The secret scanner also skips binary files.&lt;/p&gt;

&lt;p&gt;These details aren't as visually impressive as a dashboard.&lt;/p&gt;

&lt;p&gt;But they are the details that determine whether developers will actually trust and use a security scanner.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Standard Library Made Possible
&lt;/h2&gt;

&lt;p&gt;The zero-dependency constraint forced us to look at Python's standard library differently.&lt;/p&gt;

&lt;p&gt;We used standard-library modules for the core functionality:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Standard Library&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTP server&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http.server&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI parsing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;argparse&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP utilities&lt;/td&gt;
&lt;td&gt;&lt;code&gt;urllib.request&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON parsing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TOML parsing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tomllib&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XML parsing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xml.etree.ElementTree&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File/path handling&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pathlib&lt;/code&gt;, &lt;code&gt;os&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pattern matching&lt;/td&gt;
&lt;td&gt;&lt;code&gt;re&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data models&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dataclasses&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;&lt;code&gt;collections&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unittest&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The point wasn't that third-party packages are bad.&lt;/p&gt;

&lt;p&gt;Packages are valuable because they provide mature solutions and save development time.&lt;/p&gt;

&lt;p&gt;The interesting question was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How much functionality do we actually need, and how much of that functionality is already available?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  We Documented the Substitutions Too
&lt;/h2&gt;

&lt;p&gt;We created a &lt;code&gt;STDLIB.md&lt;/code&gt; file to document the standard-library substitutions behind the project.&lt;/p&gt;

&lt;p&gt;Some examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;requests&lt;/code&gt; → &lt;code&gt;urllib.request&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;click&lt;/code&gt; → &lt;code&gt;argparse&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;python-dotenv&lt;/code&gt; → &lt;code&gt;os&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pathlib2&lt;/code&gt; → &lt;code&gt;pathlib&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tomli&lt;/code&gt; → &lt;code&gt;tomllib&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;simplejson&lt;/code&gt; → &lt;code&gt;json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This wasn't about claiming that a standard-library module is always a complete replacement for a third-party package.&lt;/p&gt;

&lt;p&gt;It was about documenting the smaller requirements DevGuard actually needed and why we chose not to add another runtime dependency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommendations Instead of Just Findings
&lt;/h2&gt;

&lt;p&gt;A scanner that only says &lt;strong&gt;"something is wrong"&lt;/strong&gt; leaves the developer with the next problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What should I do about it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DevGuard includes deterministic remediation recommendations for its known finding rules.&lt;/p&gt;

&lt;p&gt;For example, a hardcoded secret can produce guidance to move the value to an environment variable or secure secret manager.&lt;/p&gt;

&lt;p&gt;A detected private key can produce guidance to remove it and rotate or revoke it if it has been exposed.&lt;/p&gt;

&lt;p&gt;A sensitive file can produce guidance around &lt;code&gt;.gitignore&lt;/code&gt; and environment variables.&lt;/p&gt;

&lt;p&gt;We wanted the output to be actionable rather than simply alarming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Without Adding a Test Framework
&lt;/h2&gt;

&lt;p&gt;The zero-dependency principle also applies to testing.&lt;/p&gt;

&lt;p&gt;DevGuard uses Python's built-in &lt;code&gt;unittest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The test suite covers areas including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;secret detection&lt;/li&gt;
&lt;li&gt;private-key detection&lt;/li&gt;
&lt;li&gt;environment-variable handling&lt;/li&gt;
&lt;li&gt;binary-file handling&lt;/li&gt;
&lt;li&gt;sensitive-file detection&lt;/li&gt;
&lt;li&gt;dependency parsing&lt;/li&gt;
&lt;li&gt;CLI integration&lt;/li&gt;
&lt;li&gt;risk scoring&lt;/li&gt;
&lt;li&gt;risk-level calculation&lt;/li&gt;
&lt;li&gt;recommendation logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The test command is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
python -m unittest discover -s tests -v&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running DevGuard
&lt;/h2&gt;

&lt;p&gt;From the project root, the CLI can be run with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
python -m devguard scan .&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If running directly from the source tree, the source directory can be placed on &lt;code&gt;PYTHONPATH&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;powershell&lt;br&gt;
$env:PYTHONPATH="src"&lt;br&gt;
python -m devguard scan .&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The scanner returns a non-zero exit code when findings are detected, which makes the CLI suitable for automation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F95tq2z77fe0eamjrqiwc.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F95tq2z77fe0eamjrqiwc.jpeg" alt=" " width="800" height="381"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9gxq9ntfilph8eotgqhb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9gxq9ntfilph8eotgqhb.jpeg" alt=" " width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F68r2zj53nun3qyyyhpj9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F68r2zj53nun3qyyyhpj9.jpeg" alt=" " width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Learned
&lt;/h2&gt;

&lt;p&gt;The biggest lesson wasn't that third-party packages are unnecessary.&lt;/p&gt;

&lt;p&gt;They aren't.&lt;/p&gt;

&lt;p&gt;The lesson was that &lt;strong&gt;dependencies should solve a problem we actually have&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without the usual libraries, we had to think more carefully about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what the scanner really needed&lt;/li&gt;
&lt;li&gt;how findings should be represented&lt;/li&gt;
&lt;li&gt;how false positives should be reduced&lt;/li&gt;
&lt;li&gt;how the dashboard should communicate risk&lt;/li&gt;
&lt;li&gt;how much parsing was actually necessary&lt;/li&gt;
&lt;li&gt;where a dependency would genuinely add value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The standard library didn't magically build DevGuard for us.&lt;/p&gt;

&lt;p&gt;It gave us the building blocks.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Empty &lt;code&gt;requirements.txt&lt;/code&gt; Was the Easy Part
&lt;/h2&gt;

&lt;p&gt;At first, "zero dependency" sounded like a restriction.&lt;/p&gt;

&lt;p&gt;By the end, it felt more like an engineering exercise.&lt;/p&gt;

&lt;p&gt;The interesting part wasn't avoiding &lt;code&gt;pip&lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;It was learning to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What problem are we actually solving?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is the smallest reliable implementation we can build?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And finally:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Does the standard library already give us the pieces we need?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DevGuard is our answer to those questions.&lt;/p&gt;

&lt;p&gt;A small security scanner.&lt;/p&gt;

&lt;p&gt;A modular architecture.&lt;/p&gt;

&lt;p&gt;A local dashboard.&lt;/p&gt;

&lt;p&gt;An explainable risk model.&lt;/p&gt;

&lt;p&gt;Actionable recommendations.&lt;/p&gt;

&lt;p&gt;And a runtime that doesn't depend on a third-party security framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  DevGuard at a Glance
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Python&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runtime dependencies:&lt;/strong&gt; 0&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core focus:&lt;/strong&gt; Developer security and codebase scanning&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scanners:&lt;/strong&gt; Secret, File Risk, Dependency&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interfaces:&lt;/strong&gt; CLI + local web dashboard&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing:&lt;/strong&gt; Python &lt;code&gt;unittest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standard-library documentation:&lt;/strong&gt; &lt;code&gt;STDLIB.md&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hardcoded secret detection&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Private-key detection&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensitive-file detection&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency manifest analysis&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standardized &lt;code&gt;Finding&lt;/code&gt; objects&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explainable security scoring&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Risk-level classification&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remediation recommendations&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project and fixture exclusions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLI scanning&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local dashboard&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero third-party runtime dependencies&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try DevGuard
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Divyarani089/DevGuard.git" rel="noopener noreferrer"&gt;https://github.com/Divyarani089/DevGuard.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;DevGuard started with one constraint:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Build something useful without relying on third-party runtime packages.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That constraint changed how we thought about the entire project.&lt;/p&gt;

&lt;p&gt;We didn't try to replace every security tool.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't start with the dependency. Start with the problem.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>hackathon</category>
      <category>cybersecurity</category>
      <category>hackathonraptors</category>
    </item>
  </channel>
</rss>
