Security and privacy have always been at the core of how we designed and built zeitkapsl. Not as a checkbox feature, but as a fundamental principle. Still, principles alone are not enough, especially when you ask people to trust you with something as personal as their personal memories and data.
TL;DR
- Your memories were never accessible to attackers: end-to-end encryption works as designed.
- An independent security firm found 16 issues; 12 were fixed immediately and re-verified.
- The full report is now public.
We have successfully completed an independent security audit conducted by PWND Labs, a team with deep, hands-on expertise in penetration testing and real-world system exploitation.
Why it took a while
For a bootstrapped company without external investors, a professional audit is not a trivial step. It is a significant financial and organizational commitment. There are always competing priorities when you’re building something from the ground up. And because we want zeitkapsl to stay economically healthy, it took us some time to find the right partner, define the right scope, and acquire the budget for it.
But this wasn’t just our decision.
An external audit was one of the most upvoted and requested items on our public roadmap. Many of you asked for it, and rightly so. It took time, but we wanted to do it properly instead of rushing it.
Transparency is a journey
Last autumn, we open sourced our apps and all client-side code. That was a deliberate step towards transparency.
We don’t want you to have to simply trust us. You should be able to verify what we are doing.
Having the source code is nice, but not all of us are security experts. In fact, the majority of our customers choose zeitkapsl because they don’t want to bother with all the nitty-gritty technical details. They just want a product that works, is easy to use, and, most of all, is private and secure.
We designed zeitkapsl with privacy and security as first-class principles instead of add-ons. But of course we also make mistakes, and that is exactly why it is so valuable to have an independent external third party take a closer look.
So we went off and started looking for the right company.
Choosing the right partner
Back in January, we started evaluating potential audit partners. We weren’t looking for a checkbox exercise or a superficial review.
We needed a team that was capable of understanding a system like ours in depth:
- Large-scale infrastructure (Storage, Database, Servers)
- Distributed systems with syncing primitives
- Backend development with Go and PostgreSQL
- Shared core architectures and integration points
- Native mobile apps (Android and iOS)
- PWA Web apps (Svelte 5)
- End-to-end encrypted systems expertise
And most importantly: real-world attack vectors
Peter (Co-Founder of zeitkapsl) and Felix (Co-Founder of PWND Labs) met each other at an OWASP Security Meetup, and a few months later a PTA (permission to attack) was finally signed.
So is zeitkapsl secure now?
The short version:
The audit confirms that zeitkapsl’s end-to-end encrypted architecture is sound and works as intended.
Of course, no thorough audit ends with “everything is perfect”. That would be a serious red flag.
PWND Labs identified several issues, as expected in any complex system. None of these, however, were major. None of these issues ever endangered the privacy or security of zeitkapsl users.
For us, the audit was again a confirmation that the choice of unconditionally using end-to-end encryption was the right one. Even with access to encrypted media files and their metadata, a potential attacker could at no point gain access to the underlying, unencrypted media files, and neither could we.
But of course, we don’t want you to take our word for that. That is why we are publishing the full report, including all findings and the analysis methods used.
- 12 out of 16 findings were addressed and fixed. The remaining findings are not exploitable. We are still committed to resolving them to comply with best practices.
- The fixes were re-reviewed.
- The resolution was formally verified and attested.
As a result, zeitkapsl is now measurably more secure than before. You no longer have to take our word for it, and you don’t have to be an expert to verify that.
We also want to quote the executive summary here:
The codebase is clean and well-structured, with solid use of authentication and centralized error handling. No high-risk code-level vulnerabilities were found, but several issues arise from business logic and access control weaknesses. Dependencies are generally up to date, though some security controls, such as the Content Security Policy, could be further improved. The audit of the cryptographic protocol and its implementations found no vulnerabilities in the core end-to-end encryption scheme. Cryptographic primitives and parameters are well-chosen and aligned with current recommendations. Several protocol flows were formally modelled in ProVerif and verified to preserve confidentiality under different threat models. The issues identified in relation to the cryptographic layer (e.g. missing Additional Authenticated Data (AAD)) require additional assumptions to exploit (such as a malicious server combined with physical observation, or main key compromise). End-to-end encryption mitigates many attacks but does not address authorization or account management flaws, which require separate controls. Multiple access control issues were identified, including unauthorized access to other users’ encrypted media, unauthorized uploads, and exposure of internal errors. Although cryptography protects sensitive data, other information leaks remain, such as cross-user metadata exposure and email enumeration. Zeitkapsl was responsive and professional throughout the whole audit process. Any vulnerabilities we deemed sufficiently critical were immediately communicated and quickly fixed by them.
What issues were identified?
Below is a plain-English overview of the most relevant findings. You can find the full report here if you want to dig deeper. We added the issue reference used in the report for each issue at the end of each title.
Broken media access control leading to disclosure of encrypted media files and video duration (M2)
During the rollout of improvements for shared collections, we introduced a bug in a database query that was used to check access permissions for retrieving (encrypted) media files. This allowed a potential attacker with a zeitkapsl account to access encrypted media files as well as HLS playlist files from any zeitkapsl account. Due to our end-to-end encryption, the impact was very limited. For photos, the only information that could be gained by an attacker was the file size of the media item queried. For videos, in addition to the file size, the attacker could also access the video duration.
Even though the impact was limited, we treated this as a serious issue. PWND Labs informed us about the issue as soon as it was discovered. We immediately fixed and deployed the fix before verifying the fix through PWND Labs again.
Leaking of encrypted media metadata (L2)
On another endpoint, any authenticated zeitkapsl user could access the encrypted metadata of any media file by its ID. This was caused by a bug in the media update endpoint. This endpoint is used by the zeitkapsl apps to update the metadata of media files and change the liked and hidden status of media files. After a successful update, the endpoint returns the newly updated metadata of the media file so the zeitkapsl apps can update their local database. While the write actions had correct access control checks, the endpoint itself did not check access permissions before writing the submitted changes to the server database. When a potential attacker submitted a specifically crafted empty update request, no access-controlled write action would be performed and the metadata would be returned to the attacker.
On another endpoint, the ad-hoc share creation endpoint, another issue led to the same leakage. The endpoint did not check whether a media file belonged to the authenticated user. An attacker could create a share for any media file of any user and access the metadata of that media file.
Similarly to the previous issue, the impact was limited due to end-to-end encryption. Except for the timestamp and aspect ratio, all metadata is encrypted with the same key as its media file. This means an attacker could only access the timestamp and aspect ratio of any media file if they knew the ID of the media file.
We fixed this issue by adding the appropriate access checks to the affected endpoints.
Media-share corruption (M3)
Missing access control in the endpoints managing media shares allowed a potential attacker with an authenticated zeitkapsl account to add media files to any collection from any account. While this issue did not allow an attacker to gain access to any media files, a potential attacker could corrupt collections and their shares. In practice, this could prevent the victim from opening their collection in the web app because the injected media file was encrypted with the wrong key, causing the whole loading process to stop.
We fixed this issue by adding the appropriate access checks to the affected endpoints.
Email oracle (I2)
By observing behavior such as error messages and request duration on different endpoints (login, password, and support ticket creation), a potential attacker could determine whether a given email address was registered on zeitkapsl. In addition, the support ticket creation endpoint would return the internally used ID of the user with the given email address. No additional information about the user could be obtained.
We fixed this issue by changing the affected endpoints so that they behave the same way, regardless of whether an email address submitted to those endpoints is registered or not.
Disclosure of internal server errors (M1)
Several endpoints disclosed internal server errors, such as database errors or errors returned by external providers like Stripe, to the user. While no sensitive user data was exposed this way, we fixed this issue to make it harder for a potential attacker to learn anything about the internal server state.
Missing ownership verification in email change workflow (M4)
When a zeitkapsl user changes their email address, they have to re-enter their current password to verify ownership of their account. Additionally, the user has to verify ownership of the new email address by clicking a link sent to the new email address. zeitkapsl does not verify ownership of the old email address before the change.
In the case of a compromised password, a potential attacker could use the compromised password to change the email address of the victim to their own email address. If the attacker changes the email address a second time to another email address they control, the victim would have no idea which email address is currently used for the account. This means they would not be able to use their recovery kit to recover their account without the assistance of zeitkapsl support.
While we may make adjustments to the email change workflow in the future, we currently do not plan to change this behavior right now. By contacting zeitkapsl support, the victim would be able to revert the email change and recover their account this way. Since we believe the victim of such an attack should contact our support anyway to avoid such a compromise in the future, we don’t regard a change to this behavior as a high-priority issue.
Informational issues
In addition to the issues listed above, PWND Labs identified a number of non-exploitable issues and violations of security best practices. Where countermeasures could be implemented promptly, we applied them to improve the overall security of zeitkapsl. This includes issues such as reuse of two-factor authentication codes within the same time window, missing session invalidation on password change, and outdated dependencies in the zeitkapsl apps.
We plan to address the remaining, unfixed findings as well, but for transparency, we did not want to delay the release of the audit report.
Deep dive
The full report with all findings can be found here.
It is quite comprehensive, so grab a cup of tea or coffee and enjoy :)