Remark42: Rate limit bypass via unconditional trust of X-Forwarded-For/X-Real-IP headers in direct-internet deployment
Exploitation and risk
Source statusCISA KEV lists vulnerabilities known to be exploited. FIRST EPSS estimates the likelihood of exploitation in the next 30 days. An unavailable score does not mean zero risk.
Which CVEs have scores here?
This view includes predictions for CVE identifiers explicitly listed in public NuGet advisories. Microsoft release pages have their own prediction coverage. Check source status for the scope and latest checks.
No exploitation or prediction data is available here for these CVEs. This does not mean they are safe or unlikely to be exploited.
cve-program · CVE-2026-77463
PublishedRemark42 is a self-hosted comment engine for blogs, articles, or any other place where readers can add comments. From 1.0.0 until 1.16.2, Remark42 globally trusts True-Client-IP, X-Real-IP, and X-Forwarded-For without verifying that the direct peer is a trusted proxy, and middleware.RealIP overwrites r.RemoteAddr before per-IP controls run. In a directly reachable deployment, or a proxy that forwards attacker-controlled headers, a remote attacker can rotate spoofed forwarding headers to obtain fresh token buckets for rate-limited endpoints, bypass vote de-duplication when --votes-ip is enabled, mint anonymous identities, and poison stored comment IPs and request logs. The global concurrent-request throttle and per-request timeouts still limit availability impact. Mitigation support is available in version 1.16.2, but operators must configure --trusted-proxy for the deployment topology.
- Source published
- 5 Nov 2026 20:54:09 UTC
- Source modified
- 10 Nov 2026 04:20:00 UTC
- Saved here
- 10 Nov 2026 06:02:11 UTC
- Source terms
- CVE Program Terms of Use
Original source record · Cite this exact observation · Complete original publisher JSON
Source: cve-program · CVE Program Terms of Use. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.
CVSS 3.1 · 6.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L
euvd · EUVD-2026-117799
PublishedRemark42 is a self-hosted comment engine for blogs, articles, or any other place where readers can add comments. From 1.0.0 until 1.16.2, Remark42 globally trusts True-Client-IP, X-Real-IP, and X-Forwarded-For without verifying that the direct peer is a trusted proxy, and middleware.RealIP overwrites r.RemoteAddr before per-IP controls run. In a directly reachable deployment, or a proxy that forwards attacker-controlled headers, a remote attacker can rotate spoofed forwarding headers to obtain fresh token buckets for rate-limited endpoints, bypass vote de-duplication when --votes-ip is enabled, mint anonymous identities, and poison stored comment IPs and request logs. The global concurrent-request throttle and per-request timeouts still limit availability impact. Mitigation support is available in version 1.16.2, but operators must configure --trusted-proxy for the deployment topology.
Additional publisher context
EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.
Original publisher date fields
datePublished: Nov 5, 2026, 8:54:09 PM
dateUpdated: Nov 10, 2026, 4:20:00 AM
- Source published
- Nov 5, 2026, 8:54:09 PM (timezone not stated)
- Source modified
- Nov 10, 2026, 4:20:00 AM (timezone not stated)
- Saved here
- 13 Nov 2026 23:06:15 UTC
- Source terms
- ENISA EUVD · source terms and attribution apply
Original source record · Cite this exact observation · Complete original publisher JSON
Source: euvd · ENISA EUVD · source terms and attribution apply. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.
EUVD CVSS 3.1 · 6.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L
nvd · CVE-2026-77463
PublishedRemark42 is a self-hosted comment engine for blogs, articles, or any other place where readers can add comments. From 1.0.0 until 1.16.2, Remark42 globally trusts True-Client-IP, X-Real-IP, and X-Forwarded-For without verifying that the direct peer is a trusted proxy, and middleware.RealIP overwrites r.RemoteAddr before per-IP controls run. In a directly reachable deployment, or a proxy that forwards attacker-controlled headers, a remote attacker can rotate spoofed forwarding headers to obtain fresh token buckets for rate-limited endpoints, bypass vote de-duplication when --votes-ip is enabled, mint anonymous identities, and poison stored comment IPs and request logs. The global concurrent-request throttle and per-request timeouts still limit availability impact. Mitigation support is available in version 1.16.2, but operators must configure --trusted-proxy for the deployment topology.
Additional publisher context
NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.
Source analysis status: Deferred
Weakness classifications: CWE-348 · CWE-807
Original publisher date fields
published: 2026-11-05T21:18:53.727
lastModified: 2026-11-12T22:18:51.470
- Source published
- 5 Nov 2026 21:18:53 UTC
- Source modified
- 12 Nov 2026 22:18:51 UTC
- Saved here
- 13 Nov 2026 22:59:46 UTC
- Source terms
- NIST NVD usage terms; underlying source attribution retained
Original source record · Cite this exact observation · Complete original publisher JSON
Source: nvd · NIST NVD usage terms; underlying source attribution retained. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.
CVSS 3.1 · [email protected] · Secondary · 6.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L
osv · GHSA-56x6-q882-mf27
Published### Summary Remark42 applied chi's `middleware.RealIP` globally, trusting `True-Client-IP` / `X-Real-IP` / `X-Forwarded-For` headers without verifying the request came from a trusted proxy. The per-IP rate limiters key on the overwritten `r.RemoteAddr`, so any client can bypass every per-IP rate limiter by rotating spoofed IP headers. The same spoofed IP also drives other per-IP controls (stored comment IP, anonymous identity derivation, and `--votes-ip` vote de-duplication). This affects deployments reachable directly from the internet (Remark42's built-in HTTP, static TLS, and ACME modes are all documented and supported), as well as any proxied deployment where the proxy forwards an attacker-controlled recognised header. ### Details The router applies `middleware.RealIP` globally, ahead of the per-route limiters, without any check that the server is behind a trusted proxy (in v1.16.1, `backend/app/rest/api/rest.go:207`). The `rateLimiter` function (v1.16.1, `backend/app/rest/api/rest.go:769-779`) builds a tollbooth limiter with `IPLookup{Name: "RemoteAddr"}`, which reads `r.RemoteAddr`. Since chi's `middleware.RealIP` (v1.16.1, `backend/vendor/github.com/go-chi/chi/v5/middleware/realip.go:42-55`) unconditionally overwrites `r.RemoteAddr` from `True-Client-IP > X-Real-IP > first X-Forwarded-For` (accepting any syntactically valid IP), any client can set its apparent IP to an arbitrary value. This bypasses every per-IP rate limiter that runs after `RealIP`: `/auth` (2/s), avatars (100/s), the image proxy (10/s), open / protected / admin route groups (10/s), root routes (50/s), and `/web/*` (20/s). Comment and vote creation go through the update limiter, whose server default is `UPDATE_LIMIT=0.5`/s (burst 1), not 10/s. The global 1,000 concurrent-request throttle still applies, so this is a per-IP-limit bypass rather than truly unlimited throughput. chi's own documentation warns that `middleware.RealIP` should be used only behind a trusted proxy. ### PoC ```bash # Deploy Remark42 reachable directly from the internet (built-in HTTP / TLS / ACME, no proxy that overwrites the headers). # Comment creation is limited to UPDATE_LIMIT (default 0.5/s, burst 1) per IP. # Rotate X-Real-IP across many requests; each distinct value gets its own token bucket. for i in $(seq 1 100); do curl -s -o /dev/null -w '%{http_code}\n' \ -H "X-Real-IP: 192.0.2.$i" \ -X POST 'https://remark42.example.com/api/v1/comment?site=site1' \ -H 'Authorization: Bearer YOUR_JWT' \ -H 'Content-Type: application/json' \ -d '{"text":"spam","locator":{"site":"site1","url":"https://example.com/post"}}' done | sort | uniq -c # With rotating headers the responses stay 201; without them, requests beyond the burst return 429. ``` ### Impact By rotating the spoofed client IP an attacker bypasses the per-IP token buckets on all rate-limited endpoints and defeats other per-IP controls, enabling: (a) spam comment creation beyond the configured per-IP limit, (b) confirmation-email / notification flooding to supplied addresses, (c) high-volume outbound image fetching and resource consumption via the image proxy (its transport still blocks private/reserved destinations and DNS rebinding, so this is amplification, not new SSRF reach), (d) authentication-endpoint abuse, (e) where `--votes-ip` is enabled, defeating per-IP vote de-duplication (ballot stuffing), and (f) minting fresh anonymous identities and poisoning the stored comment IP and request logs, since the anonymous user ID is derived from `name + RemoteAddr`. The global concurrency ceiling and per-request timeouts remain, so availability impact is limited. ### Resolution Mitigation support was added in v1.16.2 (umputun/remark42#2116, follow-up in #2118). **Upgrading alone does not remediate the issue: `--trusted-proxy` must be configured.** The fix adds `--trusted-proxy` / `TRUSTED_PROXY`. When set, the forwarding headers (`X-Real-IP`, then `CF-Connecting-IP`, then the leftmost public `X-Forwarded-For`) are honoured only when the direct TCP peer falls inside a trusted-proxy network; for a request from any other peer those headers are dropped and the real socket IP is used. When it is **unset**, the previous trust-all behaviour is preserved for backward compatibility and a startup warning is logged, so an un-configured v1.16.2 remains exploitable. `True-Client-IP` is no longer recognised. `TRUSTED_PROXY` takes a comma-separated list; on the command line, repeat `--trusted-proxy` per entry. **Required configuration:** - **Reachable directly from the internet:** set a value that no real client matches so the forwarding headers are always ignored, e.g. `--trusted-proxy=127.0.0.1/32` (only when Remark42 is not actually reached over loopback). - **Behind a reverse proxy:** point `--trusted-proxy` at the proxy's network only, block direct access to Remark42, and make the proxy **overwrite** `X-Real-IP` with the real client and discard client-supplied forwarding headers. A proxy that merely appends to `X-Forwarded-For`, or that forwards a client-supplied `X-Real-IP`, still lets the client choose the reported IP. Note that the shipped nginx manual sets `X-Real-IP` but does not strip a client `True-Client-IP`. - **Before v1.16.2:** strip `True-Client-IP`, `X-Real-IP`, and `X-Forwarded-For` at the edge and set a known-safe client-IP header. See the [Trusted proxies and client IP docs](https://remark42.com/docs/configuration/parameters/#trusted-proxies-and-client-ip).
- Source published
- 9 Nov 2026 21:18:29 UTC
- Source modified
- 9 Nov 2026 21:30:07 UTC
- Saved here
- 9 Nov 2026 22:04:13 UTC
- Source terms
- GitHub Advisory Database · CC-BY-4.0
Original source record · Cite this exact observation · Complete original publisher JSON
Source: osv · GitHub Advisory Database · CC-BY-4.0. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.
CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L
Publisher rating · MODERATE