{"id":"CVE-2026-113667","kind":"vulnerability","aliases":["CVE-2026-113667","GHSA-44qr-rrjg-2cqq"],"related":[],"title":"ApostropheCMS: CAPTCHA response token not URL-encoded","description":"**Summary**\nForm and login CAPTCHA verification interpolate the user-supplied widget token unencoded into the server-side verification URL/body, allowing a crafted token to inject query parameters into the reCAPTCHA/hCaptcha verify request.\n\n**Details**\n- `packages/form/lib/recaptcha.js:39` — `recaptchaUri = 'https://www.google.com/recaptcha/api/siteverify?secret=${recaptchaSecret}&response=${input.recaptcha}'`\n- `packages/login-recaptcha/index.js:44` — same pattern for login\n- `packages/login-hcaptcha/index.js:47` — `body: 'response=${token}&secret=${secret}'`\n\n**PoC**\n```\ninput.recaptcha = 'attacker_token&secret=INJECTED_SECRET&something=1'\n→ resulting verify URL:\n   https://www.google.com/recaptcha/api/siteverify?secret=<real>&response=attacker_token&secret=INJECTED_SECRET&something=1\n# (replicated exactly from recaptcha.js:39)\n```\n\n**Impact**\nLow: a crafted token smuggles extra `key=value` pairs (`secret`, extra `response`) into the outbound verify call, forcing verification failures (DoS of the captcha gate and of captcha-gated login/form flows) and enabling automated bypass probing; no secret exfiltration.\n\n**Remediation** — Build the verify request with `URL` + `searchParams` (or `encodeURIComponent` on both `secret` and `response`), and validate the token against `^[A-Za-z0-9._-]{1,2048}$` before use.","summary":"The ApostropheCMS form and login CAPTCHA modules put the user-supplied CAPTCHA token into the server-side verify request without URL-encoding it. A crafted token can inject extra query parameters into the reCAPTCHA or hCaptcha verification call, which can force verification failures and enable automated bypass probing.","severity":"medium","cvss":5.3,"epss":0.003530000103637576,"exploited":false,"exploited_at":null,"products":[{"name":"@apostrophecms/form","fixed":["1.5.5"],"affected":"< 1.5.5","ecosystem":"npm"},{"name":"@apostrophecms/login-recaptcha","fixed":["1.2.1"],"affected":"< 1.2.1","ecosystem":"npm"},{"name":"@apostrophecms/login-hcaptcha","fixed":["1.3.0"],"affected":"< 1.3.0","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["apostrophecms","cwe-116","next.js","node","package","self-hosted"],"not_affected_if":["fixed-version-installed","no-captcha-configured"],"how_to_check":"Check installed versions: npm ls @apostrophecms/form @apostrophecms/login-recaptcha @apostrophecms/login-hcaptcha\nFlagged if @apostrophecms/form is below 1.5.5, login-recaptcha below 1.2.1, or login-hcaptcha below 1.3.0.","fix":"Upgrade @apostrophecms/form to 1.5.5, @apostrophecms/login-recaptcha to 1.2.1, and @apostrophecms/login-hcaptcha to 1.3.0.\nSource remediation suggests encoding the secret and response values or building the request with URL searchParams.","status":"open","published_at":"2026-10-20T18:05:35+00:00","first_seen_at":"2026-10-23T19:11:32+00:00","triaged_at":"2026-10-23T20:13:36+00:00","updated_at":"2026-10-23T21:57:21+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-23T20:13:36Z","model":"claude-haiku-5-5","output":{"fix":"Upgrade @apostrophecms/form to 1.5.5, @apostrophecms/login-recaptcha to 1.2.1, and @apostrophecms/login-hcaptcha to 1.3.0.\nSource remediation suggests encoding the secret and response values or building the request with URL searchParams.","summary":"The ApostropheCMS form and login CAPTCHA modules put the user-supplied CAPTCHA token into the server-side verify request without URL-encoding it. A crafted token can inject extra query parameters into the reCAPTCHA or hCaptcha verification call, which can force verification failures and enable automated bypass probing.","category":"package","who_cares":["apostrophecms","node","next.js","self-hosted"],"confidence":0.8,"analyst_note":"","how_to_check":"Check installed versions: npm ls @apostrophecms/form @apostrophecms/login-recaptcha @apostrophecms/login-hcaptcha\nFlagged if @apostrophecms/form is below 1.5.5, login-recaptcha below 1.2.1, or login-hcaptcha below 1.3.0.\nunknown","needs_analyst":false,"not_affected_if":["no-captcha-configured","fixed-version-installed"],"severity_if_unknown":"medium"},"cost_usd":0.00048,"input_tokens":2590,"output_tokens":442,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-113667':11A,19A '-116':25B '-2026':10A,18A '/recaptcha/api/siteverify?secret=':154C '/recaptcha/api/siteverify?secret=$':123C '1':148C,162C,233C '2048':234C '2cqq':16A '39':119C '44':128C '44qr':14A '47':134C '9':232C 'a-za-z0':228C 'allow':104C 'apostrophecm':1A,23B,33B 'apostrophecms/form':20A 'apostrophecms/login-hcaptcha':22A 'apostrophecms/login-recaptcha':21A 'attack':142C,156C 'autom':80B,202C 'bodi':135C 'build':209C 'bypass':81B,203C 'call':72B,184C 'captcha':2A,37B,44B,87C,191C,196C 'captcha-g':195C 'craft':59B,106C,170C 'cve':9A,17A 'cwe':24B 'detail':117C 'dos':188C 'enabl':79B,201C 'encod':8A,56B 'encodeuricompon':217C 'exact':164C 'exfiltr':207C 'extra':63B,173C,178C 'failur':77B,187C 'flow':199C 'forc':75B,185C 'form':34B,84C 'gate':192C,197C 'ghsa':13A 'ghsa-44qr-rrjg-2cqq':12A 'hcaptcha':70B 'host':31B 'impact':167C 'inject':62B,109C,145C,159C 'input.recaptcha':126C,141C 'interpol':89C 'key':174C 'login':36B,86C,132C 'login/form':198C 'low':168C 'modul':38B 'next.js':26B 'node':27B 'outbound':182C 'packag':28B 'packages/form/lib/recaptcha.js':118C 'packages/login-hcaptcha/index.js':133C 'packages/login-recaptcha/index.js':127C 'pair':176C 'paramet':65B,111C 'pattern':130C 'poc':140C 'probe':82B,204C 'put':39B 'queri':64B,110C 'recaptcha':68B 'recaptcha.js:39':166C 'recaptcha/hcaptcha':114C 'recaptchasecret':124C 'recaptchauri':120C 'remedi':208C 'replic':163C 'request':52B,116C,212C 'respons':3A,125C,136C,155C,179C,222C 'result':149C 'rrjg':15A 'searchparam':215C 'secret':138C,139C,144C,146C,158C,160C,177C,206C,220C 'self':30B 'self-host':29B 'server':49B,100C 'server-sid':48B,99C 'side':50B,101C 'smuggl':172C 'someth':147C,161C 'summari':83C 'suppli':43B,93C 'token':4A,45B,60B,95C,107C,137C,143C,157C,171C,226C 'unencod':96C 'url':7A,55B,151C,214C 'url-encod':6A,54B 'url/body':103C 'use':236C 'user':42B,92C 'user-suppli':41B,91C 'valid':224C 'valu':175C 'verif':71B,76B,88C,102C,186C 'verifi':51B,115C,150C,183C,211C 'widget':94C 'without':53B 'www.google.com':122C,153C 'www.google.com/recaptcha/api/siteverify?secret=':152C 'www.google.com/recaptcha/api/siteverify?secret=$':121C 'z0':231C 'za':230C","nicknames":[],"mitigations":[],"who_affected":null,"tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-20T18:05:35+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","cvss_by":"security-advisories@github.com","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-44qr-rrjg-2cqq","url":"https://github.com/advisories/GHSA-44qr-rrjg-2cqq","severity":"medium","published_at":"2026-10-20T18:05:35+00:00","modified_at":"2026-10-20T18:05:36+00:00","first_seen_at":"2026-10-23T19:11:32+00:00","fetched_at":"2026-10-23T19:11:32+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-113667","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-113667","severity":null,"published_at":"2026-10-20T18:17:20+00:00","modified_at":"2026-10-21T16:17:24+00:00","first_seen_at":"2026-10-23T21:57:21+00:00","fetched_at":"2026-10-23T22:28:58+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}