{"id":"CVE-2026-115332","kind":"vulnerability","aliases":["CVE-2026-115332"],"related":[],"title":"Lotus: authenticated tenants can inject SQL via subscription filter keys","description":"Lotus through 0.10.2 contains an sql injection vulnerability that allows authenticated organization users to inject SQL by registering crafted subscription_filter_keys that bypass keyword-only validation. Attackers can create subscriptions using the malicious key, which is rendered as an unquoted group-by identifier, to inject SQL into usage aggregation queries against the shared multi-tenant database.","summary":"Lotus (uselotus/lotus) through 0.10.2: any authenticated org user can register a subscription_filter_key that passes an exact-match keyword blacklist. It is rendered as an unquoted group-by identifier in usage aggregation SQL on a shared multi-tenant database. No patched release exists, and the project appears unmaintained.","severity":"high","cvss":8.8,"epss":0.00304,"exploited":false,"exploited_at":null,"products":[{"name":"lotus","fixed":[],"affected":"<= 0.10.2","ecosystem":"github"}],"ecosystems":["github"],"tags":["django","lotus","multi-tenant","other","package","postgresql","self-hosted","sql-injection"],"not_affected_if":["auth-required","managed-hosting"],"how_to_check":"Run pip/docker to see your Lotus version (0.10.2 or earlier = affected, and 0.10.2 is the latest release). Inspect the organization's subscription_filter_keys in the DB (metering_billing_organization) for anything that is not a plain identifier matching ^[A-Za-z_][A-Za-z0-9_]{0,63}$.","fix":"No fixed version published. Mitigate: restrict who can sign up or hold org accounts (disable open registration), run Lotus with a least-privilege, non-superuser DB role, and patch locally by enforcing the allowlist regex ^[A-Za-z_][A-Za-z0-9_]{0,63}$ on subscription_filter_keys and subscription_filters[].property_name, and quoting identifiers in the query templates. Consider migrating off Lotus.","status":"open","published_at":"2026-10-22T11:17:52+00:00","first_seen_at":"2026-10-23T21:57:31+00:00","triaged_at":"2026-10-23T22:32:23+00:00","updated_at":"2026-10-24T07:15:51+00:00","category":"other","confidence":0.8,"triage":{"at":"2026-10-23T22:32:23Z","model":"claude-haiku-5-5","output":{"fix":"unknown","reach":"network","title":"Lotus: authenticated tenants can inject SQL via subscription filter keys","impact":"high","summary":"Lotus through 0.10.2 lets any authenticated organization user register a crafted subscription_filter_key that passes keyword-only validation. That key is placed unquoted into a group-by clause of usage aggregation queries, so the attacker can inject SQL into a shared multi-tenant database.","category":"other","who_cares":["lotus","multi-tenant","self-hosted"],"confidence":0.6,"needs_auth":"yes","worst_case":"Attacker reads or alters other tenants' data in the shared database","analyst_note":"Find the fixed Lotus version and the affected subscription filter code path in the NVD entry or the upstream repository; the sources give no fix version.","how_to_check":"unknown","needs_analyst":true,"not_affected_if":["auth-required"],"user_interaction":"no","needs_special_setup":"unknown","severity_if_unknown":"high"},"cost_usd":0.000473,"input_tokens":2958,"output_tokens":354,"severity_before":"high"},"analyst_status":"done","analyst_note":"Find the fixed Lotus version and the affected subscription filter code path in the NVD entry or the upstream repository; the sources give no fix version.","search":"'-115332':13A,16A '-2026':12A,15A '0.10.2':35B,86C 'aggreg':66B,135C 'allow':93C 'appear':82B 'attack':112C 'authent':2A,37B,94C 'blacklist':53B 'bypass':107C 'contain':87C 'craft':102C 'creat':114C 'cve':11A,14A 'databas':74B,143C 'django':18B 'exact':50B 'exact-match':49B 'exist':78B 'filter':9A,44B,104C 'group':61B,127C 'group-bi':60B,126C 'host':28B 'identifi':63B,129C 'inject':5A,31B,90C,98C,131C 'key':10A,45B,105C,119C 'keyword':52B,109C 'keyword-on':108C 'lotus':1A,17A,19B,32B,84C 'malici':118C 'match':51B 'multi':21B,72B,141C 'multi-ten':20B,71B,140C 'org':38B 'organ':95C 'packag':24B 'pass':47B 'patch':76B 'postgresql':25B 'project':81B 'queri':136C 'regist':41B,101C 'releas':77B 'render':56B,122C 'self':27B 'self-host':26B 'share':70B,139C 'sql':6A,30B,67B,89C,99C,132C 'sql-inject':29B 'subscript':8A,43B,103C,115C 'tenant':3A,22B,73B,142C 'unmaintain':83B 'unquot':59B,125C 'usag':65B,134C 'use':116C 'uselotus/lotus':33B 'user':39B,96C 'valid':111C 'via':7A 'vulner':91C","nicknames":[],"mitigations":[],"who_affected":null,"tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-22T11:17:52+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/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":"disclosure@vulncheck.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-115332","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-115332","severity":null,"published_at":"2026-10-22T11:17:52+00:00","modified_at":"2026-10-22T16:53:20+00:00","first_seen_at":"2026-10-23T21:57:31+00:00","fetched_at":"2026-10-23T22:29:02+00:00","note":null},{"source":"analyst","external_id":"CVE-2026-115332:496","url":null,"severity":null,"published_at":"2026-10-23T23:41:10+00:00","modified_at":"2026-10-23T23:41:10+00:00","first_seen_at":"2026-10-23T23:41:10+00:00","fetched_at":"2026-10-23T23:41:10+00:00","note":"No fixed version exists: latest release is 0.10.2 (affected, Mar 2023) and upstream main's last commit is Feb 2024, so project looks dormant. Root cause from the researcher report (hackmd, code-derived, no runtime PoC) and the 0.10.2 source: model_serializers.py ~L501-520 validates subscription_filter_keys only by exact-match blacklist of 9 SQL keywords, and the keys are interpolated as bare identifiers into group-by in the *_query_templates.py. Sibling CVEs from the same report: CVE-2026-115330 (custom_sql stacked statements) and CVE-2026-115331 (property_name). No exploitation seen; no community posts searched."},{"source":"epss","external_id":"CVE-2026-115332","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-115332","severity":null,"published_at":null,"modified_at":null,"first_seen_at":"2026-10-24T07:15:51+00:00","fetched_at":"2026-10-25T12:38:51+00:00","note":null}],"documents":[{"id":2112,"url":"https://hackmd.io/@leediay/BkUc3WL2Mx","title":"Application Security Assessment Report (VULN-004), leediay","kind":"advisory","source":"analyst","text":"Third-party static audit: VULN-004 Go event-ingestion authenticates by 8-char prefix only; POST /api/track/; status Partially Verified (code-derived, not executed).","published_at":null,"relation":"describes","confidence":null,"note":null},{"id":2113,"url":"https://github.com/uselotus/lotus/blob/0.10.2/backend/metering_billing/serializers/model_serializers.py","title":"Lotus 0.10.2 model_serializers.py (vulnerable validation)","kind":"other","source":"analyst","text":null,"published_at":null,"relation":"describes","confidence":null,"note":null},{"id":2114,"url":"https://www.vulncheck.com/advisories/lotus-through-0.10.2-sql-injection-via-subscription-filter-keys","title":"VulnCheck: Lotus through 0.10.2 SQL Injection via Subscription Filter Keys","kind":"advisory","source":"analyst","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":null},{"id":2115,"url":"https://github.com/uselotus/lotus/releases","title":"uselotus/lotus releases (latest 0.10.2)","kind":"release","source":"analyst","text":"Latest release 0.10.2 (23 Mar). No release notes mention an authn fix.","published_at":null,"relation":"mentions","confidence":null,"note":null}],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}