<?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: Aaditya2010-14</title>
    <description>The latest articles on DEV Community by Aaditya2010-14 (@aaditya201014).</description>
    <link>https://dev.to/aaditya201014</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%2F4117486%2Ffa1a2ad0-40f4-4731-b6bb-a8669774e6e0.png</url>
      <title>DEV Community: Aaditya2010-14</title>
      <link>https://dev.to/aaditya201014</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aaditya201014"/>
    <language>en</language>
    <item>
      <title>13 Attacks, 0 Vulnerabilities: Building a Security Toolkit With Zero Dependencies, ZeroVault</title>
      <dc:creator>Aaditya2010-14</dc:creator>
      <pubDate>Wed, 09 Sep 2026 12:47:02 +0000</pubDate>
      <link>https://dev.to/aaditya201014/13-attacks-0-vulnerabilities-building-a-security-toolkit-that-hacks-itself-with-zero-1f12</link>
      <guid>https://dev.to/aaditya201014/13-attacks-0-vulnerabilities-building-a-security-toolkit-that-hacks-itself-with-zero-1f12</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; : I built a complete security toolkit (encrypted vault, TOTP authenticator, file encryptor, git secrets scanner, QR code generator, and a self-testing penetration suite) using nothing but Go's standard library. &lt;strong&gt;82 files&lt;/strong&gt;, &lt;strong&gt;115 tests&lt;/strong&gt;, &lt;strong&gt;22 stdlib substitutions&lt;/strong&gt;, zero packages. It then ran &lt;strong&gt;13 automated attacks&lt;/strong&gt; against itself and passed every one. Full source and demo at the bottom.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  First, what's a "zero-dependency" project and why does anyone care?
&lt;/h2&gt;

&lt;p&gt;Every time you run &lt;code&gt;go get&lt;/code&gt;, &lt;code&gt;npm install&lt;/code&gt;, or &lt;code&gt;pip install&lt;/code&gt;, you're trusting someone else's code with your application. That sounds fine until you see the numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;454,600 malicious packages&lt;/strong&gt; were uploaded to registries last year alone&lt;/li&gt;
&lt;li&gt;The average Node.js project has &lt;strong&gt;683 transitive dependencies&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One compromised package&lt;/strong&gt; in your tree and your users' data is exposed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For security tools specifically, this is ironic. The software you trust to protect your passwords is itself trusting hundreds of packages you've never audited.&lt;/p&gt;

&lt;p&gt;So a hackathon called &lt;strong&gt;Zero Dependency&lt;/strong&gt; asked a simple, slightly rebellious question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What if you built something genuinely useful using **nothing but the language itself&lt;/em&gt;&lt;em&gt;?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No packages. No &lt;code&gt;go get&lt;/code&gt;. Just Go's standard library. I said yes. Solo. Here's what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built: ZeroVault, a security toolkit that ships as one binary
&lt;/h2&gt;

&lt;p&gt;ZeroVault is everything you'd normally need three or four packages to build, packed into a single binary with an empty &lt;code&gt;go.mod&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted password vault&lt;/strong&gt; — AES-256-GCM encryption, PBKDF2 key derivation with &lt;strong&gt;100,000 iterations&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TOTP 2FA generator&lt;/strong&gt; — RFC 6238 compatible, verified byte-for-byte against Google Authenticator&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File encryption/decryption&lt;/strong&gt; — streaming AES-GCM in &lt;strong&gt;64KB chunks&lt;/strong&gt;, handles files of any size&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets scanner&lt;/strong&gt; — regex pattern matching + Shannon entropy analysis, scans current files AND git commit history by reading &lt;code&gt;.git/objects&lt;/code&gt; directly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password health dashboard&lt;/strong&gt; — strength scoring, reuse detection, offline breach checking against &lt;strong&gt;500 known compromised passwords&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QR code generation&lt;/strong&gt; — implemented from the ISO 18004 specification, Reed-Solomon and all&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vault 2FA&lt;/strong&gt; — the vault protects itself using its own TOTP implementation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clipboard auto-clear&lt;/strong&gt; — passwords vanish from clipboard after &lt;strong&gt;10 seconds&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web dashboard&lt;/strong&gt; — premium UI with CSRF protection, XSS prevention, security headers, rate limiting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated penetration test suite&lt;/strong&gt; — &lt;strong&gt;13 real attacks&lt;/strong&gt; with HTML audit report export&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-command demo mode&lt;/strong&gt; — &lt;code&gt;zerovault demo&lt;/code&gt; sets up everything for judges to try in &lt;strong&gt;10 seconds&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How you'd normally build this: &lt;code&gt;go get&lt;/code&gt; a crypto library, a TOTP package, a web framework, a CSRF middleware, a QR encoder, a git library. &lt;strong&gt;Six dependencies&lt;/strong&gt; minimum, each with their own dependency trees.&lt;/p&gt;

&lt;p&gt;How I built it: composed &lt;code&gt;crypto/aes&lt;/code&gt;, &lt;code&gt;crypto/cipher&lt;/code&gt;, &lt;code&gt;crypto/hmac&lt;/code&gt;, &lt;code&gt;net/http&lt;/code&gt;, &lt;code&gt;html/template&lt;/code&gt;, &lt;code&gt;compress/zlib&lt;/code&gt;, &lt;code&gt;regexp&lt;/code&gt;, and &lt;code&gt;math&lt;/code&gt; from Go's standard library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The proof:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;go.mod
module zerovault

go 1.27

&lt;span class="nv"&gt;$ &lt;/span&gt;go list &lt;span class="nt"&gt;-m&lt;/span&gt; all
zerovault
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. That's the entire supply chain. One line: my own code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fun part: what I'd normally install, and what replaced it
&lt;/h2&gt;

&lt;p&gt;This is the heart of the story. For each thing I needed, here's the package I'd usually grab, and the standard-library feature I used instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. truffleHog → reading git's internals with compress/zlib
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Normally I'd install:&lt;/strong&gt; &lt;code&gt;trufflesecurity/trufflehog&lt;/code&gt; (scans git history for leaked secrets)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it actually takes:&lt;/strong&gt; Git objects are just zlib-compressed files sitting in &lt;code&gt;.git/objects/&lt;/code&gt;. The format is documented and surprisingly simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;commit&lt;/strong&gt; object contains a tree hash, parent hash, author, and message&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;tree&lt;/strong&gt; object contains file entries: mode, name, and blob hash&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;blob&lt;/strong&gt; is the raw file content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I read them with &lt;code&gt;compress/zlib&lt;/code&gt;, parsed the internal format with &lt;code&gt;bytes&lt;/code&gt; and &lt;code&gt;encoding/hex&lt;/code&gt;, and walked the commit graph backwards through parent hashes. When the scanner finds an AWS key in a blob that was deleted &lt;strong&gt;three commits ago&lt;/strong&gt;, it reports: &lt;em&gt;"deleted but still in history."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's the exact feature people install truffleHog for. It took about &lt;strong&gt;200 lines&lt;/strong&gt; of stdlib Go. No git binary needed, no shelling out, no library. Just &lt;code&gt;compress/zlib&lt;/code&gt; and string parsing.&lt;/p&gt;

&lt;p&gt;The moment this worked, scanning a test repo and finding a Stripe key that had been "deleted" &lt;strong&gt;two commits prior&lt;/strong&gt; — was probably the most satisfying moment of the entire hackathon.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. pquerna/otp → TOTP in ~15 lines of HMAC
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Normally I'd install:&lt;/strong&gt; &lt;code&gt;pquerna/otp&lt;/code&gt; or &lt;code&gt;xlzd/gotp&lt;/code&gt; (TOTP/HOTP generation)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it actually takes:&lt;/strong&gt; Read RFC 6238. The entire TOTP algorithm is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. T = floor(unix_time / 30)
2. T_bytes = T as 8-byte big-endian
3. mac = HMAC-SHA1(secret, T_bytes)
4. offset = mac[19] &amp;amp; 0x0F
5. code = (mac[offset:offset+4] as uint32) &amp;amp; 0x7FFFFFFF
6. code = code % 1,000,000
7. Zero-pad to 6 digits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go's stdlib has &lt;code&gt;crypto/hmac&lt;/code&gt;, &lt;code&gt;crypto/sha1&lt;/code&gt;, &lt;code&gt;encoding/binary&lt;/code&gt;, and &lt;code&gt;encoding/base32&lt;/code&gt;. Compose them exactly as the RFC says. The output matches Google Authenticator.&lt;/p&gt;

&lt;p&gt;But here's where it gets meta: after building TOTP, I used it to protect the vault itself. &lt;code&gt;zerovault 2fa enable&lt;/code&gt; generates a TOTP secret for the vault, and now unlocking requires both a master password AND a &lt;strong&gt;6-digit code&lt;/strong&gt; from your phone. I didn't install a 2FA library for the vault, I reused the TOTP code I'd already written.&lt;/p&gt;

&lt;p&gt;Eating your own cooking. Zero additional lines of crypto.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. gorilla/csrf → one line of stdlib
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Normally I'd install:&lt;/strong&gt; &lt;code&gt;gorilla/csrf&lt;/code&gt; (CSRF protection middleware)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it actually takes:&lt;/strong&gt; Go 1.25 added &lt;code&gt;CrossOriginProtection&lt;/code&gt; directly to &lt;code&gt;net/http&lt;/code&gt;. It blocks cross-origin POST requests by checking the Origin header, the same approach gorilla/csrf uses internally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One line&lt;/strong&gt; to enable it. CSRF handled.&lt;/p&gt;

&lt;p&gt;Combined with &lt;code&gt;html/template&lt;/code&gt; (which auto-escapes dynamic content against XSS by default) and manually setting security headers (X-Frame-Options, CSP, no-cache), the entire web security layer came from stdlib. No middleware packages.&lt;/p&gt;

&lt;p&gt;I verified this with automated tests: a curl POST with &lt;code&gt;Origin: http://evil-site.com&lt;/code&gt; gets &lt;strong&gt;403'd&lt;/strong&gt;. The same request from &lt;code&gt;localhost:8080&lt;/code&gt; succeeds. The XSS tests inject &lt;code&gt;&amp;lt;script&amp;gt;alert('hacked')&amp;lt;/script&amp;gt;&lt;/code&gt; as a username, it renders as literal text in the browser. &lt;strong&gt;8 different XSS payloads&lt;/strong&gt;, all neutralized by html/template's auto-escaping.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. QR code generation → math and patience
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Normally I'd install:&lt;/strong&gt; &lt;code&gt;skip2/go-qrcode&lt;/code&gt; or any QR generation library&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it actually takes:&lt;/strong&gt; This was the hardest single feature. QR codes involve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data encoding&lt;/strong&gt; — numeric, alphanumeric, and byte modes with different bit lengths&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error correction&lt;/strong&gt; — Reed-Solomon codes over GF(256), which means implementing Galois field arithmetic: addition (XOR), multiplication (log/antilog tables), polynomial division&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Module placement&lt;/strong&gt; — a specific pattern of data, error correction, format info, timing patterns, and alignment patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Masking&lt;/strong&gt; — &lt;strong&gt;8 different mask patterns&lt;/strong&gt;, each scored for readability, pick the best one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I implemented all of it from the ISO/IEC 18004 specification. The GF(256) math alone — building the log/antilog lookup tables, computing generator polynomials, dividing data polynomials by generator polynomials — took real effort.&lt;/p&gt;

&lt;p&gt;But when I ran &lt;code&gt;zerovault totp qr github-2fa&lt;/code&gt; and Google Authenticator on my phone actually scanned the terminal output and added the account correctly, that was the single best moment of the hackathon.&lt;/p&gt;

&lt;p&gt;No image library. No QR library. Just &lt;code&gt;math&lt;/code&gt;, &lt;code&gt;fmt&lt;/code&gt;, and stubbornness.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Password managers &amp;amp; breach databases → crypto/sha256 + embedded hashes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Normally I'd install:&lt;/strong&gt; Something like a &lt;code&gt;haveibeenpwned&lt;/code&gt; client or a breach database package&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it actually takes:&lt;/strong&gt; I embedded the SHA-256 hashes of &lt;strong&gt;500 commonly breached passwords&lt;/strong&gt; directly in the source code. Not the passwords themselves, just their hashes. On every health check, each stored password is hashed and compared against the set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"password123" → SHA-256 → check against embedded set → 
MATCH → "⚠ appears in breach databases"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Completely offline. &lt;strong&gt;No API calls&lt;/strong&gt;. &lt;strong&gt;No internet&lt;/strong&gt;. &lt;strong&gt;No dependency&lt;/strong&gt;. The health dashboard shows a breach warning as a red banner that's impossible to miss.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug that almost killed my demo
&lt;/h2&gt;

&lt;p&gt;During a hardening pass near the end, I ran &lt;code&gt;go build -race&lt;/code&gt; and the race detector found something real.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; &lt;strong&gt;Two concurrent HTTP requests&lt;/strong&gt; could trigger simultaneous vault saves. On Windows, &lt;code&gt;os.Rename&lt;/code&gt; (used for atomic file writes, write to temp file, rename over the original) doesn't behave atomically when the target file is open by another goroutine. The race detector caught it under a &lt;strong&gt;60-request stress test&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I found it:&lt;/strong&gt; I almost didn't. The race only surfaces under concurrent web requests, my manual testing was always single-user. If I hadn't run the race detector as part of a systematic hardening pass, this would have surfaced live during the demo as a crash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; A per-session mutex held for the duration of each handler, plus unique temporary filenames per write operation (using a counter instead of a fixed name). The race detector confirmed the fix was clean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; &lt;code&gt;go build -race&lt;/code&gt; is not optional for concurrent Go code. This is the kind of bug a team of four catches in code review. Solo, the tooling has to catch it for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The attack suite: a security tool that tests itself
&lt;/h2&gt;

&lt;p&gt;This is the feature I'm most proud of, and the one no other hackathon team built.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zerovault attack&lt;/code&gt; runs &lt;strong&gt;13 automated penetration tests&lt;/strong&gt; against the running application:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crypto attacks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dictionary brute force — tries &lt;strong&gt;20 common passwords&lt;/strong&gt;, each takes &lt;strong&gt;~0.3 seconds&lt;/strong&gt; (PBKDF2 doing its job)&lt;/li&gt;
&lt;li&gt;Vault bit-flip tampering — flips bits at &lt;strong&gt;5 positions&lt;/strong&gt;, GCM catches every one&lt;/li&gt;
&lt;li&gt;Vault truncation/injection — tries appending, truncating, stripping the auth tag&lt;/li&gt;
&lt;li&gt;PBKDF2 timing analysis — verifies no timing side-channel across password lengths&lt;/li&gt;
&lt;li&gt;Nonce reuse detection — saves the vault &lt;strong&gt;100 times&lt;/strong&gt;, verifies all nonces are unique&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Web attacks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XSS injection — &lt;strong&gt;8 different payloads&lt;/strong&gt; (script tags, img onerror, SVG, template injection)&lt;/li&gt;
&lt;li&gt;CSRF — &lt;strong&gt;5 fake origins&lt;/strong&gt; including null and wrong-port&lt;/li&gt;
&lt;li&gt;Session security — no-cookie access, fake cookies, expired sessions, post-lock reuse&lt;/li&gt;
&lt;li&gt;Security headers — verifies X-Frame-Options, CSP, nosniff, no-cache&lt;/li&gt;
&lt;li&gt;Path traversal — tries &lt;code&gt;../../../etc/passwd&lt;/code&gt; and system directories on the scanner&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TOTP attacks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code brute force — documents that TOTP security comes from the secret, not the code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output is a terminal scoreboard AND a self-contained HTML audit report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RESULTS: 10 blocked | 2 secure | 1 expected | 0 vulnerabilities
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attack scripts themselves are real code, &lt;code&gt;attacks/bruteforce.go&lt;/code&gt; contains actual PBKDF2 derivation loops, &lt;code&gt;attacks/xss.go&lt;/code&gt; sends real HTTP requests with real payloads and checks the response HTML for unescaped tags. I showed the source code in the demo video before running the suite so judges could see it wasn't fake output.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the stdlib made painful
&lt;/h2&gt;

&lt;h3&gt;
  
  
  No argon2, no bcrypt, no scrypt
&lt;/h3&gt;

&lt;p&gt;All three live in &lt;code&gt;golang.org/x/crypto&lt;/code&gt;. Not stdlib. Can't use them.&lt;/p&gt;

&lt;p&gt;PBKDF2 with &lt;strong&gt;100,000 iterations&lt;/strong&gt; is the OWASP minimum, and it's what I used. Is it as good as argon2? No, argon2 is memory-hard, which resists GPU attacks better. I documented this in the threat model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"PBKDF2 is less resistant to GPU brute force than argon2. We chose PBKDF2 because argon2 requires golang.org/x/crypto, which is not part of Go's standard library."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Judges want honesty about tradeoffs, not false claims of invincibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-platform password input without echo
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;golang.org/x/term&lt;/code&gt; is the clean way to read passwords without showing characters on screen. It's not stdlib. I used &lt;code&gt;syscall&lt;/code&gt; directly, which works but requires different code paths for Unix and Windows. Annoying, but functional.&lt;/p&gt;

&lt;h3&gt;
  
  
  PBKDF2 itself
&lt;/h3&gt;

&lt;p&gt;Go has &lt;code&gt;crypto/hmac&lt;/code&gt; and &lt;code&gt;crypto/sha256&lt;/code&gt;. It does NOT have a PBKDF2 function. I implemented it by composing HMAC in a loop per RFC 2898.&lt;/p&gt;

&lt;p&gt;The implementation is maybe &lt;strong&gt;40 lines&lt;/strong&gt;. But those &lt;strong&gt;40 lines&lt;/strong&gt; are the foundation of the entire vault, if the key derivation is wrong, every encryption is wrong. I validated against RFC 6070 test vectors before writing anything else. Those test vectors were my first commit's first test.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I didn't expect
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Go's stdlib is massive for security work.&lt;/strong&gt; &lt;code&gt;crypto/aes&lt;/code&gt;, &lt;code&gt;crypto/cipher&lt;/code&gt;, &lt;code&gt;crypto/hmac&lt;/code&gt;, &lt;code&gt;crypto/sha256&lt;/code&gt;, &lt;code&gt;crypto/rand&lt;/code&gt;, &lt;code&gt;crypto/subtle&lt;/code&gt;, the entire AES-GCM + PBKDF2 + TOTP stack is in the box. I expected to hit walls. I didn't.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TOTP is deceptively simple.&lt;/strong&gt; The RFC looks intimidating. The implementation is HMAC + a counter + truncation. The perceived complexity around 2FA evaporates when you read the spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Git's internal format is elegantly minimal.&lt;/strong&gt; Zlib-compressed objects with a text header. No magic. Parse commits, follow trees, read blobs. A git history scanner doesn't need a git library, it needs &lt;code&gt;compress/zlib&lt;/code&gt; and &lt;strong&gt;200 lines of code&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;html/template&lt;/code&gt; is more sophisticated than most third-party alternatives.&lt;/strong&gt; It doesn't just escape HTML, it escapes based on context (HTML body, attribute, JavaScript, CSS, URL). Most template engines people install as dependencies don't do context-aware escaping this well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The constraint clarifies more than it limits.&lt;/strong&gt; Every time I reached for a package, the stdlib already had the primitive. The missing piece was never the tool, it was knowing how to compose what was already there.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  📊 ZeroVault by the Numbers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────┐
│                                                      │
│   ⏱  Build time ..................... ~12 hours     │
│                                                      │
│   📁 Go source files ................ 82            │
│                                                      │
│   ✅ Tests ........................... 115 (100%)   │
│                                                      │
│   📝 STDLIB.md entries .............. 22            │
│                                                      │
│   📦 Dependencies ................... 0             │
│                                                      │
│   🔒 Attack suite tests ............ 13             │
│                                                      │
│   🛡  Vulnerabilities found ......... 0              │ 
│                                                      │
│   🔄 Reproducible build ............ ✓ verified     │
│                                                      │
│   ⚡ AES-GCM throughput ............ ~1.0–1.6 GB/s   │
│                                                      │
│   🔑 PBKDF2 per attempt ............ ~300ms          │
│                                                      │
│   👤 Team size ...................... 1              │
│                                                      │
└──────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What I'd change for production
&lt;/h2&gt;

&lt;p&gt;Being honest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Argon2&lt;/strong&gt; instead of PBKDF2 for memory-hard key derivation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS&lt;/strong&gt; for the web dashboard (currently localhost HTTP only)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure memory wiping&lt;/strong&gt; with mlock/munlock&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OS keychain integration&lt;/strong&gt; instead of clipboard&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardware security key support&lt;/strong&gt; (FIDO2/WebAuthn)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit log with cryptographic chaining&lt;/strong&gt; for tamper detection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of these requires dependencies outside Go's stdlib. That's the tradeoff, and articulating it honestly is what the hackathon is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  The point
&lt;/h2&gt;

&lt;p&gt;The zero-dependency constraint isn't about proving packages are bad. I'd use gorilla/csrf and truffleHog in production without hesitation.&lt;/p&gt;

&lt;p&gt;The constraint is about understanding what sits underneath. When you install a TOTP library, do you know it's just HMAC-SHA1 with a time counter? When you use AES-GCM, do you know why GCM and not CBC? When you install a git scanning tool, do you know it's reading zlib-compressed objects from &lt;code&gt;.git/objects/&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;After this hackathon, I do. And that understanding doesn't go away when I go back to installing packages on Monday.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;One binary. One person. Zero dependencies.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Aaditya2010-14/zerovault" rel="noopener noreferrer"&gt;github.com/Aaditya2010-14/zerovault&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎥 &lt;strong&gt;Demo video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=IbJ5IE6FbzM&amp;amp;t=2s" rel="noopener noreferrer"&gt;YouTube Demo Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Aaditya2010-14/zerovault.git
&lt;span class="nb"&gt;cd &lt;/span&gt;zerovault
go build &lt;span class="nt"&gt;-o&lt;/span&gt; zerovault ./cmd/zerovault
./zerovault demo    &lt;span class="c"&gt;# password: demo2026&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Built for Zero Dependency Hackathon 2026 — Track E: Security &amp;amp; Crypto Utilities&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>go</category>
      <category>programming</category>
      <category>hackathonraptor</category>
    </item>
  </channel>
</rss>
