Bug 2487231 (CVE-2026-53474)

Summary: CVE-2026-53474 migration-planner: Second-Order SQL Injection via RVTools Upload
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security DevOps Team <prodsec-dev>
Status: NEW --- QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedKeywords: Security
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in migration-planner. A remote authenticated attacker could exploit this vulnerability by uploading a specially crafted RVTools .xlsx file. Due to improper input sanitization, malicious SQL embedded within a spreadsheet cell is executed when cluster names are processed. This SQL Injection allows for arbitrary file reading on the system, potentially exposing sensitive information such as Kubernetes service account tokens and other credentials, which could lead to a full compromise of the SaaS environment.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-06-09 18:31:13 UTC
Repository: migration-planner  
Priority: High  
Location: pkg/duckdb_parser/inventory_builder.go:65 → pkg/duckdb_parser/builder.go

Description:  
Users upload RVTools .xlsx exports which DuckDB ingests safely. The inventory builder then runs SELECT DISTINCT "Cluster" FROM vinfo to enumerate cluster names and feeds each returned string back into ~27 query templates via text/template - unescaped, inside single quotes. A spreadsheet cell like x' UNION SELECT read_text('/var/run/secrets/kubernetes.io/serviceaccount/token') -- becomes executable SQL on the second pass.

Security Impact:  

DuckDB worker runs in-process inside planner-api pod without sandbox

DuckDB's read_text()/read_blob() enable arbitrary file read on pod

Can access Kubernetes service-account token, Postgres credentials, agent-JWT signing key

Single tenant's xlsx upload escalates to full SaaS compromise

Fix Suggestion:  
Apply existing escapeSQLString() helper (already used for ClusterFeaturesQuery) to every string field of queryParams before template execution. Patch covers all 27 call sites in builder.go. Long-term: prefer DuckDB prepared statements over text/template. See patches/f007.patch.