Description: I let a reviewer pick apart my encryption tool. He found a bug that told users "safe" when it meant "unknown". Here's every fix, the attacks I ran on my own files, and how to get v5 early.
Last I posted about ATLOCK v5, my encryption and password-vault tool. Within hours, a reviewer left a comment longer than most of my commits.
It was polite. It was precise. It was devastating.
I could have gotten defensive. Instead I opened the code and tried to prove him wrong.
Some of it, he was. Here's what I found.
🐛 Bug #1: the "SAFE ✅" that meant "I have no idea"
ATLOCK checks your passwords against known breaches using the Have I Been Pwned range API. Only a 5-character hash prefix ever leaves your machine. Your password never does.
The flaw: if the check couldn't run (offline, blocked, timed out), the code quietly returned "not breached", and the UI showed a calm green "Safe from breaches."
A security tool saying safe when it means unknown is the worst kind of bug, because it looks like it's working.
# before: couldn't check -> "not breached"
return (False, 0) if n is None else (bool(n), n)
# after: unknown stays unknown
return (None, 0) if n is None else (bool(n), n)
Now it says "Could not check, NOT verified." The vault health audit has its own "could not be checked" section. Silence is no longer a green tick.
🚪 Bug #2: three network calls that trusted too much
Three urlopen calls accepted whatever URL scheme came along and followed redirects wherever a server pointed them. Now every request goes through one helper that:
- refuses anything that isn't
https - refuses a redirect to anything that isn't
https - always applies a timeout and a response size cap
One door. One lock.
🔨 "Your 200 bit-flip test mostly tests GCM's tag"
Ouch. And fair.
Flipping random bits proves AES-GCM's tag works. It doesn't prove my chunk logic works, and that's exactly where chunked encryption breaks: reordering, duplication, truncation.
So I wrote the attacks he described and aimed them at my own encrypted files:
| Attack on an encrypted file | Result |
|---|---|
| Flip one bit in every single header byte | ❌ rejected |
| Swap two chunks | ❌ rejected |
| Duplicate one chunk over another | ❌ rejected |
| Drop the first chunk | ❌ rejected |
| Append an extra chunk | ❌ rejected |
| Truncate exactly on a chunk boundary | ❌ rejected |
| Cut the file at an earlier "valid-looking" point | ❌ never opens as a whole file |
Every chunk authenticates its own index and a final-chunk flag, so a truncated file can never pass for a complete one.
🔑 Sender pinning: fail closed, not "please read the warning"
If you pin a sender's public key and the file is unsigned or signed by someone else, ATLOCK refuses. It raises an exception before any plaintext is written. Reading it anyway takes an explicit allow_sender_mismatch=True.
Why not just warn? Because a warning only works if a human reads it. A return value like {'signed': True, 'signer_matches': False} is exactly what a script checks halfway and ignores. The new test confirms that on a mismatch, nothing is left on disk.
🧾 What I am NOT claiming
I'd rather you hear it from me:
-
No third-party audit. The crypto primitives come from
cryptographyandargon2-cffi, which wrap audited libraries. ATLOCK's own container format and key handling have not been independently reviewed. The self-test and fuzzer are mine, not an audit. - Python can't reliably wipe secrets from RAM. Keys and passwords can linger in memory or swap. It's in the docs now.
- It protects data at rest. It won't save you from malware already running as you, a keylogger, or a weak password.
A short threat model now ships in the docstring too.
🔓 The part where you come in
ATLOCK v5 is finished, but it isn't public yet.
I'm releasing it when Akhouri Systems crosses 1,000 downloads.
Akhouri Systems downloads
[█████████████████████████████░░░] 940 / 1000
60 downloads. That's all that stands between you and v5.
You can grab the current public version, ATLOCK v4, right now:
Here's why I'm asking you to try it:
- You help unlock v5. Every download moves the bar.
- You'll know exactly what v5 improves. Everything above is going into it.
- Your feedback shapes the release. Reviewers like the one who roasted me are the reason v5 is better than the post I originally wrote.
💬 How to help (30 seconds)
- ⬇️ Download v4 and break something
- ⭐ Star the repo so more people find it: github.com/Akhouri-Anmol-Kumar
- 🗨️ Comment below with the one thing you'd attack first. If it's good, I'll test it on my own files and write up the result, the way I did here.
And if you're the reviewer who started all this: thank you. You made v5 better, and I mean that.
See you at 1,000. 🔐
Top comments (10)
This is the follow-up I wanted to see. 😄
The bugs are interesting, but honestly the more important part is the process: someone challenged an assumption, you reproduced it instead of defending it, changed the behavior, and then turned the failure into a regression test.
That “SAFE ✅ while offline” bug is a particularly good example. In security software, unknown must stay unknown. Turning an unavailable check into a positive security claim is much more dangerous than simply showing an error.
Now I think v5 needs one more milestone before you call this journey finished: preserve these adversarial cases permanently in CI.
Every bug you found here should become a test that future ATLOCK versions are never allowed to forget.
And when you hit 1,000 downloads, celebrate for five minutes.
Then we break v5 again. 😂🔐
break v5.... hehehe.
okay 🔒
bro Like can you give me some techniques to prevent ATLOCK v5 from Mustafa ERBAY LOL
Too late bro. 😂
You already made the first mistake: you told Mustafa ERBAY that v5 exists.
But I can suggest one mitigation:
Don’t try to protect ATLOCK from reviewers. Protect it from the assumptions reviewers will attack. 😄
Put every bug we’ve found into CI, fuzz the parsers and state transitions, fail closed whenever identity/authentication is uncertain, test interrupted operations and partial writes, and assume every input — including your own container format — is hostile.
Then when I try to break v5, hopefully the only thing I find is that your test suite already tried it first. 😂🔐
Although now that you’ve challenged me publicly…
I might have to take v5 personally. 😈
ok then from my side or you can say from akhouri systems side
I challenge you to break it.
Let's see who wins Mustafa ERBAY or Akhouri Anmol Kumar (Akhouri Systems)
Challenge accepted. 😈🔐
But let’s define “winning” properly.
If I find something, you get a bug report and ATLOCK gets stronger.
If I find nothing after a serious adversarial pass, you get to make fun of me publicly. 😂
So either way, ATLOCK wins.
When v5 is public, give me the exact release commit/tag I should test. No development branch, no moving target, no fixes halfway through the review.
I’ll treat that version as frozen and start from zero — threat model, container/parser boundaries, authentication and key handling, failure states, interrupted operations, malformed inputs, privilege assumptions, and whatever weird paths appear along the way.
And don’t tell me where you think the bugs are.
That would ruin the fun. 😈
See you at v5.
I may celebrate that ATLOCK v5 win against a experience security top tier expert but I am not worthy to make fun of you in public.
and yeah both is beneficial for v5
I'm feeling goosebumps that ATLOCK v5 has challenged a person whose experience is more than my total age (your experience written in dev.to bio 20+ my total age 13)
about to cross 1000downloads
940 reached...
I'm so happy.
may 2026- 79 downloads(when I learned first time how to fetch download counts I seen 79 downloads)
2 october - 940 downloads.
growth 📈📈📈🔥
🙃
hardwork finally paying off
Right 👍🏻