One of my recent hobbies has been reviewing open source tools created with AI, and determining the relative safety (or lack thereof) within them. I really liked the idea behind supermemoryai’s Claude Supermemory, but I didn’t love that they forced everything to write to their servers. With a long history in online and affiliate marketing, no affiliate who knows what they’re doing trusts networks with their ads.
This leads to an atmosphere where affiliates submit fake ads to their affiliate reps and then reps send them to the advertiser (or approve based on advertiser guidelines) knowing they’re fake (it’s a poorly-kept secret). On the publisher side, the same thing happens…the ads consumers will see are almost never what gets approved by the publisher. There are lots of tools and tricks to make this happen, which I won’t get into here, but I was in the industry for about 11 years and I still keep my ties.
“But Erik,” (I imagine you saying) “this isn’t at all what vibe coders do!”
You’re right! It’s not, but affiliates didn’t start out paranoid of networks, either. Early networks would see which creative and sources were performing best, steal it, and run their own ads in those traffic sources. They’d let affiliates eat the cost of testing, get in on the performing creative in the best traffic, and have better profit margins on all sides (they weren’t paying an affiliate for those sales—and they had the spread from their original margin—so they could outbid on traffic).
I’m not here to call out online marketing shadiness (in this post), but rather to take a look at how we’re treating AI tools.
Let’s take another look at supermemoryai’s Claude Supermemory: they made the repo public, so anyone can install it. To actually use it, you need to have a pro account; there’s tons of people using it (you can see it all over Reddit, YouTube, etc.)…but I wonder how many people have taken the time to look at the issues with it (I did, because I don’t like to install things that I suspect are not tested or validated). I started with the basics: asking Claude Code to do a review, then moved onto asking Claude Code to use Zen MCP to instruct Google Gemini (via API) to do another review. Finally, I did a human review…and it’s still possible I missed something.
Security Fixes
| Issue | Concern | Fix |
| Timing attack vulnerability | Attackers can deduce valid tokens character-by-character by measuring response times. A string comparison that exits early on mismatch leaks timing information—repeated requests can crack a token in minutes to hours. | Use constant-time comparison for token validation |
| CORS wildcard (*) | Any website the user visits could make authenticated requests to your local backend. A malicious page could read/write memories, exfiltrate data, or inject false memories without user knowledge. | Replace with localhost-only origin validation |
| No API authentication | Any process on the machine (or network if exposed) could access the backend. Malware, other apps, or rogue scripts could read all stored memories or corrupt data. | Add bearer token authentication to local backend |
| Hardcoded HMAC secret | Anyone who reads the source code knows the secret. All HMAC signatures become forgeable—attackers could craft valid auth tokens or tamper with signed data. | Derive HMAC secret from API key dynamically |
| Silent auth failures | Security incidents go undetected. Failed login attempts, token theft, or brute-force attacks leave no trace, making forensics and incident response impossible. | Add audit logging to empty catch blocks in auth.js |
| Token exposure in logs | Log files (often world-readable, backed up, or shipped to monitoring services) become credential stores. Anyone with log access gains full API access. | Mask auth token (show only first/last 4 chars) |
| Session ID in logs | Session IDs in logs enable session hijacking. An attacker with log access can impersonate users without knowing their credentials. | Remove sensitive session ID from sanitization warnings |
| Large payload attacks | 10MB bodies enable denial-of-service. Attackers can exhaust memory/disk, crash the server, or slow it to a crawl with a few large requests. | Reduce request body limit from 10MB to 2MB |
| Input validation | Without sanitization: path traversal (read /etc/passwd), injection attacks, prototype pollution, or arbitrary code execution depending on how inputs are used downstream. | Add comprehensive security module (security.js) |
Recall..this is running on your computer…hopefully not the same one that you use to bank with, do your taxes, etc. This isn’t fear-mongering, it’s reality smacking you in the face because you never bothered to try and understand what the risks were before running your plugins.
I hate how AI-generated that last paragraph reads. I’m sorry I write like an automaton. Thanks to my IB English teacher whose name momentarily escapes me.
Performance Optimizations
| Area | Concern | Optimization |
| Sync file I/O | Node.js event loop blocks during disk reads/writes. The server becomes unresponsive—all requests queue behind slow disk operations. Under load, times out and drops connections. | Convert sync operations to async (fs.promises) |
| Inefficient rate limiter | filter() on every request creates O(n) overhead that grows with traffic. During trafficspikes, the rate limiter itself becomes the bottleneck, causing latency spikes or crashes. | Index-based pruning instead of filter() |
| Full transcript re-parsing | Re-reading entire transcript files on each request wastes CPU and I/O. Large conversations cause multi-second delays; the system doesn’t scale with usage. | Incremental parsing with file offset tracking |
Memory leaks (especially in toolUseMap) | Unreleased references accumulate over time. Server memory grows unbounded, eventually triggering out-of-memory (OOM) kills or garbage collection pauses that freeze the process. | Ensure toolUseMap cleanup in finally block |
| Triple-pass search scoring | filter().map().filter() iterates the dataset 3x. Search latency scales poorly—noticeable lag with hundreds of memories, unusable with thousands. | Single-pass loop instead of filter/map/filter chain |
| Regex recompilation | Compiling regex on every call is expensive. High-frequency functions like generateProfile waste CPU cycles repeatedly building the same patterns. | Cache compiled patterns at module level |
Stale lastIndex | Global regexes with /g flag retain state. After partial matches, subsequent calls canskip valid matches or return wrong results. This results in subtle, hard-to-debug data corruption. | Reset lastIndex for proper global pattern reuse |
All-in-all, there’s a lot of carelessly written code out there…not to mention that Supermemory is getting a copy of everything you ask Claude Code to do on their servers.
I pushed my security and performance changes (along with a local server that writes JSON files) if you would like to use my refined codebase. I’ll be filing a PR with these changes; we will see if they take me up on the fixes.
If you want to use the original, you can find it on GitHub.