{"id":"CVE-2026-123870","kind":"vulnerability","aliases":["CVE-2026-123870"],"related":[],"title":"otterdog webapp: unsigned GitHub webhooks let attackers run Python code","description":"The otterdog webapp evaluates a format-string built from the incoming GitHub webhook JSON body using Python's eval(). When the GITHUB_WEBHOOK_SECRET configuration value is unset or empty (the code default is None), the HMAC signature check is skipped entirely, allowing an unauthenticated network client to reach the eval() sink with attacker-controlled input and execute arbitrary Python on the webapp host.","summary":"The otterdog webapp builds a format string from incoming GitHub webhook JSON and evaluates it with Python's eval(). When GITHUB_WEBHOOK_SECRET is unset or empty, the signature check is skipped, so an unauthenticated network client can execute arbitrary Python on the host.","severity":"critical","cvss":9.5,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"otterdog-webapp","fixed":[],"affected":">= 0.9.0, < 1.3.2 (advisory also says current main)","ecosystem":"vendor"}],"ecosystems":[],"tags":["github-webhooks","other","otterdog","python","self-hosted"],"not_affected_if":["endpoint-not-exposed","pypi-package-only","webhook-secret-set"],"how_to_check":"- Check whether the webapp's environment sets GITHUB_WEBHOOK_SECRET to a non-empty value; unset or empty means exposed.\n- Confirm you run the otterdog webapp (from the repository/container), not just the PyPI otterdog package, which the advisory says is not affected.\n- Compare your version with the advisory's affected range (>= 0.9.0, < 1.3.2) and check whether your build includes commit bbc9e3c.","fix":"Commit bbc9e3c on eclipse-csi/otterdog makes GITHUB_WEBHOOK_SECRET mandatory (startup fails if unset or empty) and replaces the eval() filter with callables. The advisory lists 1.3.3 as patched but also says no fix is on the default branch; no release containing the commit is confirmed. Until you can confirm a release, set a non-empty GITHUB_WEBHOOK_SECRET (matching the GitHub webhook secret) or do not expose the endpoint.","status":"open","published_at":"2026-11-09T09:16:58+00:00","first_seen_at":"2026-11-09T09:25:32+00:00","triaged_at":"2026-11-09T09:26:13+00:00","updated_at":"2026-11-09T09:27:43+00:00","category":"other","confidence":0.7,"triage":{"at":"2026-11-09T09:26:13Z","model":"claude-haiku-5-5","output":{"fix":"unknown","reach":"network","title":"otterdog webapp: unsigned GitHub webhooks let attackers run Python code","impact":"high","summary":"The otterdog webapp builds a format string from incoming GitHub webhook JSON and evaluates it with Python's eval(). When GITHUB_WEBHOOK_SECRET is unset or empty, the signature check is skipped, so an unauthenticated network client can execute arbitrary Python on the host.","audience":"developers","category":"other","nicknames":[],"who_cares":["otterdog","python","github-webhooks","self-hosted"],"confidence":0.7,"fix_status":"unknown","needs_auth":"no","worst_case":"Attacker runs arbitrary Python code on the webapp host","analyst_note":"Find the fixed otterdog version and confirm default config via the linked patch and NVD entry (https://nvd.nist.gov/vuln/detail/CVE-2026-123870).","how_to_check":"- Check whether the webapp's environment sets `GITHUB_WEBHOOK_SECRET` to a non-empty value.\n- Confirm which otterdog version is deployed and compare it with the fixed version in the linked patch.","plain_action":"","product_name":"otterdog","needs_analyst":true,"not_affected_if":["webhook-secret-set","endpoint-not-exposed"],"who_is_affected":"Teams that run the otterdog webapp and receive GitHub webhooks at it. Exposure depends on whether GITHUB_WEBHOOK_SECRET is unset or empty, since that disables the HMAC check. Deployments that set a strong secret, or that do not expose the webhook endpoint to the network, are less exposed; the sources do not state fixed versions.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"critical"},"cost_usd":0.000785,"input_tokens":4625,"output_tokens":646,"severity_before":"critical"},"analyst_status":"done","analyst_note":"Find the fixed otterdog version and confirm default config via the linked patch and NVD entry (https://nvd.nist.gov/vuln/detail/CVE-2026-123870).","search":"'-123870':13A,16A '-2026':12A,15A 'allow':116C 'arbitrari':68B,133C 'attack':7A,128C 'attacker-control':127C 'bodi':88C 'build':32B 'built':81C 'check':58B,112C 'client':65B,120C 'code':10A,105C 'configur':98C 'control':129C 'cve':11A,14A 'default':106C 'empti':55B,103C 'entir':115C 'eval':47B,92C,124C 'evalu':42B,76C 'execut':67B,132C 'format':34B,79C 'format-str':78C 'github':4A,21B,38B,49B,85C,95C 'github-webhook':20B 'hmac':110C 'host':28B,72B,138C 'incom':37B,84C 'input':130C 'json':40B,87C 'let':6A 'network':64B,119C 'none':108C 'otterdog':1A,18A,24B,30B,74C 'otterdog-webapp':17A 'python':9A,25B,45B,69B,90C,134C 'reach':122C 'run':8A 'secret':51B,97C 'self':27B 'self-host':26B 'signatur':57B,111C 'sink':125C 'skip':60B,114C 'string':35B,80C 'unauthent':63B,118C 'unset':53B,101C 'unsign':3A 'use':89C 'valu':99C 'webapp':2A,19A,31B,75C,137C 'webhook':5A,22B,39B,50B,86C,96C","nicknames":[],"mitigations":[],"who_affected":"Teams that self-host the otterdog webapp (eclipse-csi/otterdog) and receive GitHub webhooks at it. It is exploitable when GITHUB_WEBHOOK_SECRET is unset or empty, which skips signature checking and lets an unauthenticated client reach eval() through the webhook's action field. The advisory says the PyPI otterdog package is not affected because the webapp is excluded from the wheel. Deployments with a non-empty secret, or without a network-reachable webhook endpoint, can skip it.","tier":"B","verified":{"how_to_check":{"at":"2026-11-09T09:27:43Z","by":"analyst","doc":"https://github.com/eclipse-csi/otterdog/commit/bbc9e3ced3665f09fc4632f11b5867524eda7f72","run_id":2263}},"analyst_revisit_at":null,"fix_status":"none","audience":"developers","plain_action":null,"pkeys":["otterdogwebapp"],"ptokens":["otterdog","webapp"],"labels":["critical","githubwebhooks","other","otterdog","python","selfhosted"],"campaign_type":null,"search_a":"'-123870':13A,16A '-2026':12A,15A 'attack':7A 'code':10A 'cve':11A,14A 'github':4A 'let':6A 'otterdog':1A,18A 'otterdog-webapp':17A 'python':9A 'run':8A 'unsign':3A 'webapp':2A,19A 'webhook':5A","search_b":"'arbitrari':68B 'build':32B 'check':58B 'client':65B 'empti':55B 'eval':47B 'evalu':42B 'execut':67B 'format':34B 'github':21B,38B,49B 'github-webhook':20B 'host':28B,72B 'incom':37B 'json':40B 'network':64B 'otterdog':24B,30B 'python':25B,45B,69B 'secret':51B 'self':27B 'self-host':26B 'signatur':57B 'skip':60B 'string':35B 'unauthent':63B 'unset':53B 'webapp':31B 'webhook':22B,39B,50B","search_c":"'allow':116C 'arbitrari':133C 'attack':128C 'attacker-control':127C 'bodi':88C 'built':81C 'check':112C 'client':120C 'code':105C 'configur':98C 'control':129C 'default':106C 'empti':103C 'entir':115C 'eval':92C,124C 'evalu':76C 'execut':132C 'format':79C 'format-str':78C 'github':85C,95C 'hmac':110C 'host':138C 'incom':84C 'input':130C 'json':87C 'network':119C 'none':108C 'otterdog':74C 'python':90C,134C 'reach':122C 'secret':97C 'signatur':111C 'sink':125C 'skip':114C 'string':80C 'unauthent':118C 'unset':101C 'use':89C 'valu':99C 'webapp':75C,137C 'webhook':86C,96C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-09T09:00:41+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/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":"emo@eclipse.org","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-123870","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-123870","severity":null,"published_at":"2026-11-09T09:16:58+00:00","modified_at":"2026-11-09T09:16:58+00:00","first_seen_at":"2026-11-09T09:25:32+00:00","fetched_at":"2026-11-09T09:25:32+00:00","note":null},{"source":"analyst","external_id":"CVE-2026-123870:2263","url":null,"severity":null,"published_at":"2026-11-09T09:27:43+00:00","modified_at":"2026-11-09T09:27:43+00:00","first_seen_at":"2026-11-09T09:27:43+00:00","fetched_at":"2026-11-09T09:27:43+00:00","note":"Read GHSA-32xf-7j44-xq72 and fix commit bbc9e3c via WebFetch (web-cli out of Exa credits, so no posts search). Advisory is inconsistent: lists patched 1.3.3 and affected <1.3.2 but also says unpatched on default branch. Commit makes secret mandatory and drops eval. No release tag confirmed, so fix not verified."}],"documents":[{"id":106700,"url":"https://github.com/eclipse-csi/otterdog/commit/bbc9e3ced3665f09fc4632f11b5867524eda7f72","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":106701,"url":"https://github.com/eclipse-csi/otterdog/security/advisories/GHSA-32xf-7j44-xq72","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-11-09T09:00:41+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"}