Making Mimiri Notes Secure
When we built Mimiri Notes (at the time named Mimer Notes) almost 20 years ago, our primary motivation was to create a secure place for us to store credentials, software activation keys, recovery keys, credit card information, and anything else we wanted to keep readily available - while still keeping it safe from both disasters and bad actors.
At the time, there were no password managers, and at work, we were just beginning to become aware of password hashing, the weaknesses of MD5, and the need for individual salting. In other words, this was during the early stages of the industry’s awakening to security.
Before creating Mimiri Notes, we stored our passwords in a plain text file - fully aware of the risks involved, but not really knowing what else to do. Reusing passwords was obviously intolerable, and who could possibly hope to remember 50 unique passwords?
So we built a tool that would allow us to keep our passwords - and anything else we wanted to keep safe - safe. At the time, we considered turning it into a product and shared it with a few friends, but ultimately decided the effort required for productization was too great.
In 2024, however, when the Zürich IT consulting market took a nosedive along with the rest of the global economy, we found ourselves with more time on our hands than we knew what to do with. And so, Mimiri Notes - the product - was born.
Our motivations remained the same: we still wanted a place that was secure from both disasters and bad actors, and we wanted it to be readily accessible so we would actually use it. Since we had been using Mimer Notes for more than just highly sensitive data, we wanted to improve its usability for general plain text note-taking.
Mimer/Mimiri Notes was always a “cloud-first” service - though no one had coined that term yet. Back then, the hottest new concept was Infrastructure as a Service, but that’s essentially how we were thinking. There isn’t a lot of disaster resilience in storing encrypted data only on your personal computer, after all. And we also wanted to be able to access our data from other locations.
In this post, I want to discuss the security aspects of building Mimiri Notes in particular, though much of it is equally relevant to any other secure system.
Making It Actually Secure
When you’re trying to build a secure system, it’s easy to get caught up in fancy algorithms and best practices espoused on various blogs. While these are all relevant and helpful, they are nowhere near enough.
It doesn’t matter if you’re using AES with a key derived using PBKDF2 - complete with all the bells and whistles - if, at the same time, you’re sending that password in plain text over HTTP. You need to bring everything together and create a cohesive system.
Nor is it enough to simply make something secure. Anyone can put a thumb drive in a bank vault - it will be impervious to network attack, but it will also be inaccessible to you. And every time you take it out of the vault and plug it into your PC, you’re opening it up to attack.
Security must be maintained while the system performs its intended function. That combination will invariably involve compromise. You cannot send your password to a service provider without first decrypting it, and while it exists decrypted in memory on your PC, it is far more vulnerable than when stored encrypted on a thumb drive in a bank vault.
Now, authentication is a solved problem - it’s just that every solution comes with trade-offs. That’s why simply sending a plain text password to the server remains the most common mechanism.
While more services are rolling out 2FA (Two-Factor Authentication), you’re unlikely to see your local mom-and-pop shop implement it on their webshop anytime soon. For them, the drawbacks still substantially outweigh the benefits.
There are other effective solutions, too, but they are all far less convenient than simple password authentication. And simple password authentication works a lot better than the prevailing winds of the internet would have you believe - and it will continue to do so, regardless of advances in computational power (I have another post about this).
Analyzing the Threats
In order to make the right compromises, we first need to understand what the actual threats are. When we designed the security model for Mimiri Notes, these were the threats we identified from the end-user perspective, listed in roughly descending order of severity:
- The provider started out with malicious intent
- The provider is incompetent
- The provider becomes compromised on the human level (coercion, conversion, change of ownership, etc.)
- The infrastructure becomes secretly compromised for an extended period of time
- The infrastructure becomes temporarily compromised
- Some amount of server data is breached and nobody knows about it
- Some amount of server data is breached and it is quickly discovered
- The communication between client and server is compromised
- The device is long-term compromised (by malware)
- The device is short-term compromised (by malware)
- The unlocked device is stolen
- The locked device is stolen
- The powered-down device is stolen
- An attacker gains temporary access to an unlocked client device
- An attacker is able to observe the monitor
- The user accidentally shares the client during a screen-sharing session
Some of these threats are quite broad, while others are highly specific - but let’s address each of them in turn.
Trust
We will group items 1–3 under the umbrella of trust.
The intentions or competence of any service provider are always difficult to verify. Fortunately, in most cases, it’s not critically important - the blast radius is usually limited to the service in question (this is why using unique passwords is important), and most services we use are of limited consequence.
That said, we’ve all heard unsettling stories of security cameras that were, ironically, very insecure. While the consequences of those cases aren’t always severe, they certainly can be.
Unfortunately, it’s extremely hard for a layperson to make that determination. Generally, we’re somewhat better at spotting malicious intent than at spotting incompetence. But if someone is well-spoken and says all the right buzzwords, it becomes incredibly difficult to judge whether they’re trustworthy - and it takes an unusual level of cynicism to even ask the question.
So we asked ourselves not “how do we convince laypeople to buy our product?” but instead, “what would it take to convince us that a provider was both competent and well-intentioned?”
Until this point, we had never planned to open-source Mimiri Notes. Ideologically, we would best describe ourselves as open-source agnostic. It had always seemed natural that, if you want to make money, proprietary software is the way to go - after all, why would you open the door for users to circumvent the paywall?
But we realized soon enough - once we began thinking seriously about it - that Mimiri Notes had to be open-source. No amount of third-party auditing - real or imagined - could adequately address the reasonable doubt that any sensible, even remotely security-conscious person would have to have.
We could have tried to play some kind of shared-source game, remaining as proprietary as possible while allowing “review” of the code that supposedly is what actually gets compiled and shipped.
But ultimately, we decided that if we were going to open-source it, we should do it properly, rather than trying to eat our cake and have it too. And it’s not as though there are no benefits to open-sourcing in its own right.
So we made the decision not only to open-source it under the GPL, but also to help you compile it yourself and self-host it, if you choose. We decided to change the economic model to work with the community - to make it desirable to pay us, rather than trying to extract payment by withholding service from so-called freeloaders.
It wasn’t an easy decision, but once we started down that path, it quickly became clear it was the only good option. While we haven’t undergone a full ideological conversion to the FOSS mindset, we’ve come to recognize that you don’t need to be altruistic to see real value in it - and arguably, that’s exactly why the GPL exists, as opposed to more permissive licenses like BSD or MIT.
This approach was mostly aimed at addressing our intent and competence, but it has the added benefit of significantly reducing the third risk as well: It becomes much harder for us to act maliciously - even if we wanted to - once we’ve taken the full step into open-source. Hiding malicious code becomes significantly more difficult, and should we ever become less trustworthy, nothing stops someone else from creating a replacement service and continuing in the original spirit. And the very possibility of that happening acts as a deterrent to malice in its own right.
It’s a clear win for the objective, even if it does come with certain financial uncertainties.
That said, we actually believe it’s the right move financially in the long run too - though that belief is less grounded in traditional economic theory.
Compromised Servers
We will group items 4–7 under the heading of compromised servers. And the name of the game is defense in depth.
All data is encrypted before it even reaches our servers, so even in the event of full access to server storage, the data should remain secure - provided the user has chosen a half decent password.
In addition, we encrypt all backups using ChaCha20-Poly1305 with a key that is not present on any of the servers involved in operating the service. Naturally, that key does exist on another server that could, in theory, also be breached - but this adds an extra layer of protection. It helps mitigate the fact that backups must, by necessity, be stored off-site, where exposure is inherently higher (if for no other reason: the introduction of yet another party).
The shared secret - i.e. the derivative of your password - is likely to be the weakest link in the chain, even though it’s run through PBKDF2-SHA512 1,000,000 times. It is ultimately the least complex element to verify a password guess against. For this reason, the server encrypts this, and any other similarly sensitive data, using AES-CBC-256 before storing it in the database. The encryption key used for this step is not stored in the database and is not known to the servers running the database.
As a result, even if the database - or a backup - is somehow breached, it would still be impossible to access user data, even if a weak password was used. (A sufficiently weak password is, of course, still vulnerable to online attack, but the threshold for “good enough” is many orders of magnitude lower than it would be in an offline attack.)
Even in the case of a total breach, or the compromise of an employee with full access, any data already stored on the servers remains only as vulnerable as the password chosen by the user. In such a scenario, the additional mitigations would be nullified, and the password would be the final line of defense.
Malicious Updates
There is one remaining challenge when it comes to compromised servers: the possibility of a malicious update.
Under normal circumstances, all updates are signed using keys that reside only on servers separate from those used in the operation of the actual service. However, in the event of a sufficiently deep compromise - whether of systems or personnel - this safeguard could be bypassed, and a malicious update could be pushed that compromises user data or passwords.
That’s why we’ve made update notifications intentionally unobtrusive. At no point should a user feel forced into updating. If you’re ever concerned, you can - and probably should - wait a little while before applying the update.
[Edit from the future: We’ve since changed our stance on this and made automatic updates the default. This decision reflects the reality that most use cases aren’t driven by absolute paranoia - and updates delivered through FlatHub, Snapcraft, the App Store, and Google Play will typically be installed naturally as part of the system’s update flow anyways.
That said, it’s still entirely possible to customize how updates are delivered - including turning them off completely.]
This risk is also partially mitigated by the open-source nature of the project. But unless you’re compiling the application yourself, it can be difficult to verify that the code on GitHub actually matches the binary you’re being prompted to install.
This is an area where there’s more work to be done - and we already have some ideas in motion. We consider it a high priority. If you have suggestions, by all means, reach out to us on Discord. Similarly, if you’re ever unsure about an update, engaging with the community there can provide a way to validate things not just with us, but with other users as well.
Two-Factor Authentication
Now might be a good time to address what, for some, might feel like the elephant in the room: Why aren’t we using 2FA?
While we are considering offering various forms of two-factor authentication - including traditional tokens, device binding in various forms, and using one device as a second factor for another - it will never be mandatory.
The reason lies in the core goal of Mimiri Notes. Both personally and as a product, we believe Mimiri Notes should serve as a viable last resort - a tool to help you put your life back together after a disaster. And a second factor is something you can lose. So is a recovery key to that second factor - and frankly, I’ve yet to see a recovery key that it’s realistic to remember.
Sure, you could write the recovery key on a piece of paper and bury it in a sealed box in the woods a few hundred miles from your home. That would likely work and is less likely to be lost than, say, the key to a safe deposit box or a piece of ID. But it’s also absurdly impractical - and it won’t help you if disaster strikes while you’re on vacation.
If you choose a password that isn’t itself a disaster, it will be more than adequate. How strong your password needs to be will depend on your specific circumstances. But unless you’re being directly targeted, the requirements really aren’t that high - especially once you factor in the use of key stretching (e.g. PBKDF2).
Insecure Communications
That brings us to threat number 8.
We obviously use HTTPS for all communication - but HTTPS isn’t impervious to man-in-the-middle attacks. In fact, many corporate networks intentionally intercept and inspect encrypted traffic through HTTPS termination to protect the broader system.
Creating an account over compromised communications does come with some risk, as the shared secret is transmitted to the server. However, gaining access to the shared secret only downgrades your security from an online attack to an offline attack. And while that’s not a trivial concern, the ability to withstand offline attacks is one of our key design principles.
This isn’t a particularly reliable attack vector, but it does represent a small weakness under certain conditions, and we’ll likely address it further once it becomes the most significant remaining vulnerability.
[Edit from the future: This vulnerability has now been eliminated. The account creation request is now encrypted using RSA+AES, with the public key compiled directly into the application and the private key known only to the server.]
Login, on the other hand, uses a challenge-response mechanism in which knowledge of the shared secret is proven without ever transmitting it. If you’re not familiar with the process: the server generates a challenge (typically including a timestamp and some random data), and the client computes a hash of that challenge using the shared secret as a key in an HMAC operation. The client sends the result back to the server, which computes the same value independently - if the results match, authentication is successful.
Subsequent communication is effectively protected by one or more layers of AES-GCM-256. Any action or query directed at the server is signed with a 4096-bit RSA key and verified individually by the server.
The server has no concept of a session, which prevents man-in-the-middle attackers from hijacking session tokens and issuing arbitrary commands on your behalf. This design also simplifies horizontal scaling of the API frontend.
Compromised Client Device
We will group items 9 and 10 under the heading of compromised client device.
If malware is installed on your device - whether it monitors keystrokes, captures screen activity, or specifically targets programs to extract data - a lot of damage can be done in a very short amount of time.
Unfortunately, there are very few effective mitigations against such attacks. The only truly bulletproof solution is to not install the malware in the first place.
It’s bad enough if you’re hit and notice it immediately. But it’s a whole different story if you don’t notice, and a silent piece of malware monitors your activity over an extended period.
In that scenario, as you gradually access your various secrets, the malware can intercept each one individually. And no realistic mitigation strategy will be effective in preventing that.
Mimiri Notes currently benefits from being relatively unknown, which makes it highly unlikely to be specifically targeted by malware - but that won’t last forever.
There are steps we can take, and in time we likely will harden Mimiri Notes as much as is practical against these types of attacks. But ultimately, we can only do so much. If you can access the data, so can the malware. We can limit the window of opportunity, but at some point, you’ll need to access the information-and at that moment, no amount of additional security layers will help.
There’s a lot you can do on your own to actively defend against malware - but that’s a huge topic in itself. Maybe one day I’ll write a dedicated post about it, but today is not that day.
Loss of Physical Control
We will group items 11–14 under the heading of loss of physical control.
If your device is stolen by someone interested primarily in its economic value, the effort they’re willing to invest in accessing your data is likely to be minimal - so even basic mitigations are often sufficient.
Our primary client-side mitigation is to never persist unencrypted data to disk.
Unfortunately, we have very limited control over what the operating system does with swap, hibernation, or memory dumps. While we’ve never heard of an attack exploiting these specifically, it’s plausible that a sophisticated attacker could extract sensitive information this way. And that is only one of many good reasons to use full disk encryption.
If your device is captured in a locked but powered-on state, your operating system is likely secure enough to be functionally equivalent to a powered-down system - assuming it’s using modern protections.
In all of these cases, though, the strength of the password you use for your operating system and/or disk encryption is critical. Just how strong it needs to be depends on the implementation. For example, BitLocker combined with TPM is quite effective - provided your password isn’t something atrocious like 1234 or P4ssw0rd!. I’d expect other competent encryption solutions to similarly reduce the effective requirements on the password, but if you’re concerned, it’s worth researching your specific setup.
The really hard case to defend against is if your device is stolen while powered on and unlocked.
On iOS and Android, we’ve implemented a lock that requires biometric authentication (e.g. FaceID) if the app has been suspended for more than 60 seconds. This adds an extra layer of protection against loss of physical control.
We’re planning to introduce a similar feature on PCs. (I’ll update this post once that happens.)
[Update: A PIN code is now available offering similar protection on PC]
But as things stand today: if you lose control of your device while Mimiri Notes is unlocked, you lose.
We could - and probably will - add the option to apply an additional layer of protection to specific notes marked as highly sensitive. But this will come at a cost to usability.
Until then, it’s advisable to log out of Mimiri Notes before entering any situation where there’s a high likelihood of losing physical control of your device.
Loss of Environmental Control
Lastly, we will group items 15 and 16 under the heading of loss of environmental control.
If you’re sitting alone in a locked room, minding your own business, there are a lot of threats you simply don’t need to worry about. But if you’re at work - or you don’t live alone - there are many opportunities for someone to do something as simple as observe your monitor.
If your secrets are plainly visible on screen, anyone walking by could see them - and so could security cameras. Likewise, if you’re screen sharing and need to access a note, you might open Mimiri Notes and inadvertently reveal a password to everyone watching.
It’s worth noting that Mimiri Notes originally started out as a set of organized, encrypted text documents - not a dedicated password manager.
But seeing as we’re using it for password storage, it seemed prudent to harden it - at least a little - against prying eyes. So, we introduced a syntax for hiding passwords from plain view. Instead of displaying the actual password, it shows something like p`********`, masking the content.
Users can still copy or reveal the password when needed, but at least it’s not sitting there in plain view.
Another significant mitigation we’ve implemented is hiding Mimiri Notes from screen-sharing, so you don’t accidentally flash sensitive content to an audience.
Unfortunately, we haven’t yet figured out how to implement this reliably on X11 or Wayland. But on both Windows and macOS, it’s a readily available feature.
We’ll continue to add mitigations like these as we come up with new ideas.
In Conclusion
Mimiri Notes is not perfect - and like any security product that operates in the real world, it never will be.
But we do believe we’ve built a tool that, if used sensibly, can be secure enough for any scenario a normal person is likely to encounter.
We haven’t done much to protect users from themselves - and we don’t plan to, at least not in a coercive way. If you want to use 1234 as your password, we’ll warn you - but we won’t stop you.
If you choose to share your screen and show Mimiri Notes, you can. But we’ve taken steps to help ensure you don’t do it by accident. Likewise, no one forces you to use the p`` syntax for passwords - but it’s there if you want it.
We believe in education, not enforcement. You know your situation better than we ever could - and ultimately, you should be the one making those decisions.