{"id":"CVE-2026-125321","kind":"vulnerability","aliases":["CVE-2026-125321"],"related":[],"title":"pgEdge Postgres MCP Server: spoofed X-Forwarded-For defeats login rate limiting","description":"pgEdge Postgres MCP Server enables SQL queries against PostgreSQL databases through Model Context Protocol compatible clients. Prior to 1.1.0, deployments exposing the nondefault HTTP transport with authentication enabled used the leftmost caller-supplied X-Forwarded-For value as the client address for login rate limiting. ExtractIPAddress in internal/auth/middleware.go supplied that value to IsAllowed and RecordFailedAttempt in internal/auth/rate_limiter.go, allowing an unauthenticated caller to rotate addresses to evade throttling or assert another user's address to consume that user's limiter bucket. The published nginx configuration appended rather than replaced X-Forwarded-For, making the issue reachable without an operator misconfiguration. Username-keyed account lockout did not use the client address, but shipped defaults disabled that separate control through MaxFailedAttemptsBeforeLockout: 0. This issue is fixed in version 1.1.0.","summary":"The pgEdge Postgres MCP Server trusted the leftmost X-Forwarded-For header from callers when rate-limiting logins over its HTTP transport. An unauthenticated attacker can rotate or forge that address to bypass login throttling or exhaust another user's login attempts.","severity":"medium","cvss":6.5,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["ai-tooling","http-transport","mcp","nginx","pgedge","postgres"],"not_affected_if":["auth-disabled","stdio-transport"],"how_to_check":"- Check the installed pgEdge Postgres MCP Server version; versions below `1.1.0` are affected.\n- Check whether the HTTP transport with authentication is enabled, since that is the nondefault configuration the advisory describes.\n- Check the reverse proxy config for whether it appends to X-Forwarded-For instead of replacing it.","fix":"- pgEdge Postgres MCP Server: upgrade to `1.1.0`.","status":"open","published_at":"2026-11-10T18:17:33+00:00","first_seen_at":"2026-11-10T18:22:55+00:00","triaged_at":"2026-11-10T18:24:53+00:00","updated_at":"2026-11-10T18:24:53+00:00","category":"ai-tooling","confidence":0.6,"triage":{"at":"2026-11-10T18:24:53Z","model":"claude-haiku-5-5","output":{"fix":"- pgEdge Postgres MCP Server: upgrade to `1.1.0`.","reach":"internet","title":"pgEdge Postgres MCP Server: spoofed X-Forwarded-For defeats login rate limiting","impact":"medium","summary":"The pgEdge Postgres MCP Server trusted the leftmost X-Forwarded-For header from callers when rate-limiting logins over its HTTP transport. An unauthenticated attacker can rotate or forge that address to bypass login throttling or exhaust another user's login attempts.","audience":"developers","category":"ai-tooling","nicknames":[],"who_cares":["pgedge","postgres","mcp","http-transport","nginx"],"confidence":0.6,"fix_status":"available","needs_auth":"no","worst_case":"attacker bypasses login throttling and brute-forces accounts over HTTP","analyst_note":"Fetch the vendor advisory and patch linked from the sources to confirm the fix and the exact affected configuration.","how_to_check":"- Check the installed pgEdge Postgres MCP Server version; versions below `1.1.0` are affected.\n- Check whether the HTTP transport with authentication is enabled, since that is the nondefault configuration the advisory describes.\n- Check the reverse proxy config for whether it appends to X-Forwarded-For instead of replacing it.","plain_action":"","product_name":"","needs_analyst":true,"not_affected_if":["stdio-transport","auth-disabled"],"who_is_affected":"Deployments of the pgEdge Postgres MCP Server that use the HTTP transport with authentication enabled are exposed; the published nginx configuration appends X-Forwarded-For, which makes the issue reachable without operator misconfiguration. Stdio-only or unauthenticated deployments are not described as affected by the sources.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"unknown"},"cost_usd":0.000822,"input_tokens":4819,"output_tokens":680,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-125321':16A,19A '-2026':15A,18A '0':196C '1.1.0':92C,203C 'account':179C 'address':62B,116C,139C,148C,186C 'ai':21B 'ai-tool':20B 'allow':133C 'anoth':69B,145C 'append':160C 'assert':144C 'attack':56B 'attempt':73B 'authent':100C 'bucket':155C 'bypass':64B 'caller':44B,106C,136C 'caller-suppli':105C 'client':89C,115C,185C 'compat':88C 'configur':159C 'consum':150C 'context':86C 'control':193C 'cve':14A,17A 'databas':83C 'default':189C 'defeat':10A 'deploy':93C 'disabl':190C 'enabl':78C,101C 'evad':141C 'exhaust':68B 'expos':94C 'extractipaddress':121C 'fix':200C 'forg':60B 'forward':8A,40B,110C,166C 'header':42B 'http':24B,52B,97C 'http-transport':23B 'internal/auth/middleware.go':123C 'internal/auth/rate_limiter.go':132C 'isallow':128C 'issu':170C,198C 'key':178C 'leftmost':37B,104C 'limit':13A,48B,120C,154C 'lockout':180C 'login':11A,49B,65B,72B,118C 'make':168C 'maxfailedattemptsbeforelockout':195C 'mcp':3A,26B,33B,76C 'misconfigur':175C 'model':85C 'nginx':27B,158C 'nondefault':96C 'oper':174C 'pgedg':1A,28B,31B,74C 'postgr':2A,29B,32B,75C 'postgresql':82C 'prior':90C 'protocol':87C 'publish':157C 'queri':80C 'rate':12A,47B,119C 'rate-limit':46B 'rather':161C 'reachabl':171C 'recordfailedattempt':130C 'replac':163C 'rotat':58B,138C 'separ':192C 'server':4A,34B,77C 'ship':188C 'spoof':5A 'sql':79C 'suppli':107C,124C 'throttl':66B,142C 'tool':22B 'transport':25B,53B,98C 'trust':35B 'unauthent':55B,135C 'use':102C,183C 'user':70B,146C,152C 'usernam':177C 'username-key':176C 'valu':112C,126C 'version':202C 'without':172C 'x':7A,39B,109C,165C 'x-forwarded-for':6A,38B,108C,164C","nicknames":[],"mitigations":[],"who_affected":"Deployments of the pgEdge Postgres MCP Server that use the HTTP transport with authentication enabled are exposed; the published nginx configuration appends X-Forwarded-For, which makes the issue reachable without operator misconfiguration. Stdio-only or unauthenticated deployments are not described as affected by the sources.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":[],"ptokens":[],"labels":["aitooling","httptransport","mcp","medium","nginx","pgedge","postgres"],"campaign_type":null,"search_a":"'-125321':16A,19A '-2026':15A,18A 'cve':14A,17A 'defeat':10A 'forward':8A 'limit':13A 'login':11A 'mcp':3A 'pgedg':1A 'postgr':2A 'rate':12A 'server':4A 'spoof':5A 'x':7A 'x-forwarded-for':6A","search_b":"'address':62B 'ai':21B 'ai-tool':20B 'anoth':69B 'attack':56B 'attempt':73B 'bypass':64B 'caller':44B 'exhaust':68B 'forg':60B 'forward':40B 'header':42B 'http':24B,52B 'http-transport':23B 'leftmost':37B 'limit':48B 'login':49B,65B,72B 'mcp':26B,33B 'nginx':27B 'pgedg':28B,31B 'postgr':29B,32B 'rate':47B 'rate-limit':46B 'rotat':58B 'server':34B 'throttl':66B 'tool':22B 'transport':25B,53B 'trust':35B 'unauthent':55B 'user':70B 'x':39B 'x-forwarded-for':38B","search_c":"'0':196C '1.1.0':92C,203C 'account':179C 'address':116C,139C,148C,186C 'allow':133C 'anoth':145C 'append':160C 'assert':144C 'authent':100C 'bucket':155C 'caller':106C,136C 'caller-suppli':105C 'client':89C,115C,185C 'compat':88C 'configur':159C 'consum':150C 'context':86C 'control':193C 'databas':83C 'default':189C 'deploy':93C 'disabl':190C 'enabl':78C,101C 'evad':141C 'expos':94C 'extractipaddress':121C 'fix':200C 'forward':110C,166C 'http':97C 'internal/auth/middleware.go':123C 'internal/auth/rate_limiter.go':132C 'isallow':128C 'issu':170C,198C 'key':178C 'leftmost':104C 'limit':120C,154C 'lockout':180C 'login':118C 'make':168C 'maxfailedattemptsbeforelockout':195C 'mcp':76C 'misconfigur':175C 'model':85C 'nginx':158C 'nondefault':96C 'oper':174C 'pgedg':74C 'postgr':75C 'postgresql':82C 'prior':90C 'protocol':87C 'publish':157C 'queri':80C 'rate':119C 'rather':161C 'reachabl':171C 'recordfailedattempt':130C 'replac':163C 'rotat':138C 'separ':192C 'server':77C 'ship':188C 'sql':79C 'suppli':107C,124C 'throttl':142C 'transport':98C 'unauthent':135C 'use':102C,183C 'user':146C,152C 'usernam':177C 'username-key':176C 'valu':112C,126C 'version':202C 'without':172C 'x':109C,165C 'x-forwarded-for':108C,164C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-09-03T12:42:20+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L","cvss_by":"security-advisories@github.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-125321","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-125321","severity":null,"published_at":"2026-11-10T18:17:33+00:00","modified_at":"2026-11-10T18:17:33+00:00","first_seen_at":"2026-11-10T18:22:55+00:00","fetched_at":"2026-11-10T18:22:55+00:00","note":null}],"documents":[{"id":116900,"url":"https://github.com/pgEdge/pgedge-postgres-mcp/commit/6a19e46a240b9f4661a4a253811948dd75c4077e","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":116901,"url":"https://github.com/pgEdge/pgedge-postgres-mcp/security/advisories/GHSA-v347-v3w7-7fq9","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-09-03T12:42:20+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}