{"id":"CVE-2026-54349","kind":"vulnerability","aliases":["CVE-2026-54349"],"related":[],"title":"Chartbrew: unauthenticated SQL injection via public chart URL filters","description":"Chartbrew is an open-source web application that can connect directly to databases and APIs and use the data to create charts. Prior to 5.2.1, SQL dashboard-variable substitution used attacker-controlled JavaScript replacement strings unsafely across SQL connectors and separately failed to escape backslashes for MySQL and MariaDB quoted contexts. The vulnerable surface is public and embedded dashboard/chart requests that call applyMysqlOrPostgresVariables. An unauthenticated user sends crafted URL filter values to a public or embedded chart backed by a stored SQL query. Replacement-string dollar sequences can alter SQL independently of the database engine, while MySQL and MariaDB backslash handling provides a second quoted-string escape path. The target must expose a public or embedded chart using URL-controlled variables in a SQL query; only the backslash branch is specific to MySQL and MariaDB. Injected SQL can read, modify, or delete data available to the configured database account. This issue is fixed in version 5.2.1.","summary":"Chartbrew, a web app that builds charts from databases and APIs, mishandles URL filter values in SQL dashboard variables before version 5.2.1. An unauthenticated visitor to a public or embedded chart can inject SQL and read, modify, or delete data the configured database account can reach.","severity":"critical","cvss":9.8,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["chartbrew","mariadb","mysql","package","postgresql","self-hosted","sql"],"not_affected_if":["auth-required","no-embedded-charts","no-public-charts","static-variables"],"how_to_check":"- Check the installed Chartbrew version and confirm whether it is below `5.2.1`.\n- Look for public or embedded dashboards and charts whose stored SQL query uses dashboard variables filled from URL parameters.","fix":"- Upgrade Chartbrew to `5.2.1` or later.","status":"open","published_at":"2026-11-06T21:17:08+00:00","first_seen_at":"2026-11-06T21:45:07+00:00","triaged_at":"2026-11-06T21:46:26+00:00","updated_at":"2026-11-06T21:46:26+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-06T21:46:26Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade Chartbrew to `5.2.1` or later.","reach":"internet","title":"Chartbrew: unauthenticated SQL injection via public chart URL filters","impact":"high","summary":"Chartbrew, a web app that builds charts from databases and APIs, mishandles URL filter values in SQL dashboard variables before version 5.2.1. An unauthenticated visitor to a public or embedded chart can inject SQL and read, modify, or delete data the configured database account can reach.","audience":"businesses","category":"package","nicknames":[],"who_cares":["chartbrew","self-hosted","sql","mysql","mariadb","postgresql"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"Attacker reads, changes, or deletes database data via injected SQL.","analyst_note":"","how_to_check":"- Check the installed Chartbrew version and confirm whether it is below `5.2.1`.\n- Look for public or embedded dashboards and charts whose stored SQL query uses dashboard variables filled from URL parameters.\n- unknown","plain_action":"","needs_analyst":false,"not_affected_if":["no-public-charts","no-embedded-charts","auth-required","static-variables"],"who_is_affected":"Teams that self-host Chartbrew and expose public or embedded charts whose SQL queries use URL-controlled dashboard variables are exposed. Instances with no public or embedded charts, or with only hard-coded query variables, are not affected by the described path. Only the MySQL and MariaDB backslash branch is specific to those databases; the replacement-string flaw applies across SQL connectors.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"critical"},"cost_usd":0.000754,"input_tokens":4505,"output_tokens":607,"severity_before":"critical"},"analyst_status":null,"analyst_note":null,"search":"'-2026':11A,14A '-54349':12A,15A '5.2.1':46B,96C,232C 'account':68B,225C 'across':110C 'alter':163C 'api':35B,86C 'app':28B 'applic':78C 'applymysqlorpostgresvari':136C 'attack':104C 'attacker-control':103C 'avail':220C 'back':151C 'backslash':118C,174C,204C 'branch':205C 'build':30B 'call':135C 'chart':7A,31B,55B,93C,150C,192C 'chartbrew':1A,16B,25B,71C 'configur':66B,223C 'connect':81C 'connector':112C 'context':124C 'control':105C,196C 'craft':141C 'creat':92C 'cve':10A,13A 'dashboard':42B,99C 'dashboard-vari':98C 'dashboard/chart':132C 'data':64B,90C,219C 'databas':33B,67B,84C,168C,224C 'delet':63B,218C 'direct':82C 'dollar':160C 'embed':54B,131C,149C,191C 'engin':169C 'escap':117C,182C 'expos':187C 'fail':115C 'filter':9A,38B,143C 'fix':229C 'handl':175C 'host':23B 'independ':165C 'inject':4A,57B,212C 'issu':227C 'javascript':106C 'mariadb':17B,122C,173C,211C 'mishandl':36B 'modifi':61B,216C 'must':186C 'mysql':18B,120C,171C,209C 'open':75C 'open-sourc':74C 'packag':19B 'path':183C 'postgresql':20B 'prior':94C 'provid':176C 'public':6A,52B,129C,147C,189C 'queri':156C,201C 'quot':123C,180C 'quoted-str':179C 'reach':70B 'read':60B,215C 'replac':107C,158C 'replacement-str':157C 'request':133C 'second':178C 'self':22B 'self-host':21B 'send':140C 'separ':114C 'sequenc':161C 'sourc':76C 'specif':207C 'sql':3A,24B,41B,58B,97C,111C,155C,164C,200C,213C 'store':154C 'string':108C,159C,181C 'substitut':101C 'surfac':127C 'target':185C 'unauthent':2A,48B,138C 'unsaf':109C 'url':8A,37B,142C,195C 'url-control':194C 'use':88C,102C,193C 'user':139C 'valu':39B,144C 'variabl':43B,100C,197C 'version':45B,231C 'via':5A 'visitor':49B 'vulner':126C 'web':27B,77C","nicknames":[],"mitigations":[],"who_affected":"Teams that self-host Chartbrew and expose public or embedded charts whose SQL queries use URL-controlled dashboard variables are exposed. Instances with no public or embedded charts, or with only hard-coded query variables, are not affected by the described path. Only the MySQL and MariaDB backslash branch is specific to those databases; the replacement-string flaw applies across SQL connectors.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"pkeys":[],"ptokens":[],"labels":["chartbrew","critical","mariadb","mysql","package","postgresql","selfhosted","sql"],"campaign_type":null,"search_a":"'-2026':11A,14A '-54349':12A,15A 'chart':7A 'chartbrew':1A 'cve':10A,13A 'filter':9A 'inject':4A 'public':6A 'sql':3A 'unauthent':2A 'url':8A 'via':5A","search_b":"'5.2.1':46B 'account':68B 'api':35B 'app':28B 'build':30B 'chart':31B,55B 'chartbrew':16B,25B 'configur':66B 'dashboard':42B 'data':64B 'databas':33B,67B 'delet':63B 'embed':54B 'filter':38B 'host':23B 'inject':57B 'mariadb':17B 'mishandl':36B 'modifi':61B 'mysql':18B 'packag':19B 'postgresql':20B 'public':52B 'reach':70B 'read':60B 'self':22B 'self-host':21B 'sql':24B,41B,58B 'unauthent':48B 'url':37B 'valu':39B 'variabl':43B 'version':45B 'visitor':49B 'web':27B","search_c":"'5.2.1':96C,232C 'account':225C 'across':110C 'alter':163C 'api':86C 'applic':78C 'applymysqlorpostgresvari':136C 'attack':104C 'attacker-control':103C 'avail':220C 'back':151C 'backslash':118C,174C,204C 'branch':205C 'call':135C 'chart':93C,150C,192C 'chartbrew':71C 'configur':223C 'connect':81C 'connector':112C 'context':124C 'control':105C,196C 'craft':141C 'creat':92C 'dashboard':99C 'dashboard-vari':98C 'dashboard/chart':132C 'data':90C,219C 'databas':84C,168C,224C 'delet':218C 'direct':82C 'dollar':160C 'embed':131C,149C,191C 'engin':169C 'escap':117C,182C 'expos':187C 'fail':115C 'filter':143C 'fix':229C 'handl':175C 'independ':165C 'inject':212C 'issu':227C 'javascript':106C 'mariadb':122C,173C,211C 'modifi':216C 'must':186C 'mysql':120C,171C,209C 'open':75C 'open-sourc':74C 'path':183C 'prior':94C 'provid':176C 'public':129C,147C,189C 'queri':156C,201C 'quot':123C,180C 'quoted-str':179C 'read':215C 'replac':107C,158C 'replacement-str':157C 'request':133C 'second':178C 'send':140C 'separ':114C 'sequenc':161C 'sourc':76C 'specif':207C 'sql':97C,111C,155C,164C,200C,213C 'store':154C 'string':108C,159C,181C 'substitut':101C 'surfac':127C 'target':185C 'unauthent':138C 'unsaf':109C 'url':142C,195C 'url-control':194C 'use':88C,102C,193C 'user':139C 'valu':144C 'variabl':100C,197C 'version':231C 'vulner':126C 'web':77C","first_public_at":"2026-07-06T06:42:04+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","cvss_by":"security-advisories@github.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-54349","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-54349","severity":null,"published_at":"2026-11-06T21:17:08+00:00","modified_at":"2026-11-06T21:17:09+00:00","first_seen_at":"2026-11-06T21:45:07+00:00","fetched_at":"2026-11-06T21:45:07+00:00","note":null}],"documents":[{"id":90309,"url":"https://github.com/chartbrew/chartbrew/commit/f93d31ac586091f72a7eb97d89fa3b4db271bd24","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":90310,"url":"https://github.com/chartbrew/chartbrew/releases/tag/v5.2.1","title":"Release notes: github.com","kind":"release","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release notes: github.com"},{"id":90311,"url":"https://github.com/chartbrew/chartbrew/security/advisories/GHSA-4wj7-9gq7-mrr2","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-07-06T06:42:04+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"}],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}