# Finding eight high-severity vulnerabilities in NodeBB in six hours

Eight high-severity NodeBB flaws: federation XSS, template-injection XSS, admin auth bypass via homepage rewrite, signature-bypass PM leak, pid mass assignment, unauthenticated category outbox, upvote inflation.

- Payout: Research
- Severity: high
- Program: NodeBB
- Write-up by: Aikido Security
- Disclosed: 2026-07-22
- Write-up quality: 8/10
- Original: https://www.aikido.dev/blog/eight-high-severity-vulnerabilities-nodebb
- Library page: https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-eight-high-severity-vulnerabilities-nodebb
- Tags: area:web domain:web impact:ato impact:data-leak kind:research platform:threat-intel sev:high tech:nodejs technique:source-review vuln:access-control vuln:auth-bypass vuln:ssti vuln:xss

**Target:** NodeBB forum (Node.js) ActivityPub federation, Benchpress templates, admin middleware
**Root cause:** Multiple: unescaped federated profile icon in meta tag; identity __escape in errors.tpl; translation pass after template render allows [[...]] injection; admin privilege middleware runs before custom homepage rewrite; ActivityPub signature only verified on POST; pid trusted from request body; outbox route lacks read permission check; Announce-embedded Like actor unverified.
**Steps:**
1. Federation XSS: host /.well-known/webfinger and /ap/actor/xss returning icon.url `"><img src onerror="alert(origin)">`, then visit `/user/xss@attacker.tld`
2. Admin XSS: sign an Update with mismatched actor/object.id to trigger origin-mismatch error storing `<img src onerror=alert(origin)>` as id; admin views Federation Errors
3. Template injection: request `/test[[topic:merged-message,A,B]][[topic:merged-message,javascript:alert(origin),CLICK%20ME]]` to break out of og:url meta and inject javascript: link
4. Admin bypass: PUT /api/v3/users/:id/settings with homePageCustom=`admin/advanced/cache`, then GET `/` to reach admin pages
5. PM leak: GET `/message/{mid}` with `Signature: keyId="{uid}"` header (no POST verification) to read others' messages
6. Mass assignment: POST /api/v3/topics with `"pid": 1` to hijack welcome post, then edit to overwrite content
7. Outbox leak: GET `/category/{cid}/outbox` with `Accept: application/activity+json` to read private category posts
8. Upvote inflation: POST /category/1/inbox with Announce wrapping a Like whose actor is arbitrary fake uid, repeat
**How found:** Whitebox AI pentest: spotted HTML concatenation in helpers.common.js buildMetaTag, identity __escape in errors.tpl, translation pass ordering in render.js, middleware ordering vs home rewrite, POST-only signature verification, req.body passed to topicsAPI.create, missing auth on outbox, and Announce actor not verified by assertPayload.
**Exploitation:** Federation XSS requires victim to visit attacker-controlled federated user link; admin XSS stored via signed inbox POST then triggered when admin opens error log, enabling full instance takeover via admin JS. Template injection reflected in URL/flags and storable in posts, executing JS on click. Admin bypass lets any logged-in user read admin pages/APIs (CSV export, error logs, logo upload). PM leak enumerates incremental message IDs impersonating any uid. pid mass assignment hijacks arbitrary posts. Outbox leaks private categories unauthenticated. Upvote inflation floods fake likes.
**Escalation:** Admin-panel XSS escalates to full instance compromise; admin bypass exposes user CSV and error logs; PM leak enumerates all private chats by iterating mid.
**Insight:** When a feature has multiple entry paths (direct inbox vs Announce-embedded Like, POST vs GET signature checks, main admin routes vs rewritten homepage), the alternative path often skips the security check the primary path enforces — audit every parallel route for the same middleware.
