Where
-Infinity
0
Severity
9.6
SQL Injection
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N

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.

1 / 2
Source: MITRE
First published (updated )
Severity
7

Repository: migration-planner Priority: High Location: pkg/duckdbparser/inventorybuilder.go:65 → pkg/duckdbparser/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 readtext('/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 readtext()/readblob() 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.

First published (updated )
Severity
6.3
XSS
AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:L/A:N

A flaw was found in migration-planner. Insufficient validation of the AgentStatusUpdate.CredentialUrl field allows an authenticated attacker to store a malicious javascript: URL. When a victim views this URL in the Hybrid Cloud Console, it can lead to Cross-Site Scripting (XSS), enabling script execution in the victim's session and potentially disclosing sensitive information.

1 / 2
Source: MITRE
First published (updated )
Severity
7
XSS

Repository: migration-planner Priority: Medium Location: internal/handlers/validator/rules.go:11

Description: AgentStatusUpdate.CredentialUrl field is tagged validate:"url". go-playground/validator's url rule only checks RFC-3986 well-formedness, so javascript:alert(document.cookie) passes. Value is stored in Postgres and rendered as clickable link in migration-planner-ui-app inside Hybrid Cloud Console .

Security Impact:

Backend persistence gate for stored XSS in Red Hat hybrid-cloud console

Requires agent control alone, but chains with f003→f002 for any authenticated user to plant javascript: URL in another org's source

Script execution in victim's Hybrid Cloud Console session

Fix Suggestion: Parse URL at handler and reject anything whose scheme is not http or https before reaching service layer. UI should also stop rendering this field as raw href, but backend must not store malicious payload. See patches/f001.patch.

First published (updated )
Severity
9.6
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N

A flaw was found in migration-planner. The agent-API middleware processes JSON Web Tokens (JWTs) for authentication, but its UpdateSourceInventory and UpdateAgentStatus handlers fail to validate the sourceid claim within these tokens against the requested source ID. This oversight allows an authenticated attacker with a valid agent token to manipulate data across different tenants, leading to a complete collapse of tenant isolation. This could result in unauthorized overwriting of victim inventory, planting of malicious credential URLs, or corruption of migration assessments.

1 / 2
Source: MITRE
First published (updated )
Severity
7

Repository: migration-planner Priority: High Location: internal/handlers/v1alpha1/agent.go:39

Description: Each agent OVA carries a JWT with a sourceid claim identifying the single source it should manage. The agent-API middleware validates the JWT signature and stores claims in context, but UpdateSourceInventory and UpdateAgentStatus handlers never check these claims. They trust the source ID from the URL path/request body instead. Helper functions auth.AgentFromContext / MustHaveAgent exist but have zero call sites.

Security Impact:

Complete tenant isolation collapse on agent surface

Any valid agent token grants write capability for every tenant's source

Attacker can overwrite victim inventory, plant malicious credentialUrl, or corrupt migration assessments

Chains with f003 for full cross-tenant write from any Hybrid Cloud Console login

Fix Suggestion: Read auth.MustHaveAgent(ctx).SourceID in both handlers and return 403 when it doesn't match the target source. The 403 response types already exist in generated server code. See patches/f002.patch.

First published (updated )
Severity
9.6
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N

A flaw was found in migration-planner. An authenticated attacker could exploit an improper access control vulnerability in the /api/v1/sources/{id}/image-url endpoint. This flaw allows the attacker to bypass an ownership check and obtain presigned S3 URLs for Open Virtual Appliance (OVA) images belonging to other users. Consequently, the attacker can download OVA images containing sensitive information, such as long-lived agent JSON Web Tokens (JWTs) and source configurations, potentially leading to unauthorized access and modification of the victim's source.

1 / 2
Source: MITRE
First published (updated )
Severity
7

Repository: migration-planner Priority: High Location: internal/handlers/v1alpha1/source.go:236

Description: GET /api/v1/sources/{id}/image-url returns presigned S3 URLs for OVA appliances. Unlike sibling endpoints (GetSource/UpdateSource/DeleteSource), this handler skips the user.Organization == source.OrgID ownership check and proceeds directly to URL generation. Any bearer token plus victim's source UUID yields a download link.

Security Impact:

OVA embeds victim's long-lived agent JWT and source configuration

Attacker gains credential to write to victim's source (when combined with f002)

Discloses proxy/network configuration

UUIDv4 entropy is insufficient when UUIDs appear in shared assessments, support tickets, browser history

Fix Suggestion: Fetch the source first, compare user.Username/user.Organization against source.Username/source.OrgID, and return 404 on mismatch (not 403 to avoid existence oracle). Long-term: wrap SourceService in an Authz decorator. See patches/f003.patch.

First published (updated )
Severity
9.1
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H

A flaw was found in migration-planner. An authenticated user can exploit this vulnerability by sending a DELETE request to the /api/v1/sources route, which lacks proper authorization and filtering. This allows for the destruction of all customer data, including sources, agents, and assessments, leading to a critical loss of availability and integrity across the entire SaaS platform.

1 / 2
Source: MITRE
First published (updated )
Severity
7

Repository: migration-planner Priority: High Location: internal/handlers/v1alpha1/source.go:74

Description: DELETE /api/v1/sources route is wired in openapi.yaml and calls sourceSrv.DeleteSources(ctx) with no filter. The service method runs Unscoped().Exec("DELETE FROM sources") against shared Postgres. No admin gate, no org scoping, no confirmation required.

Security Impact:

Any authenticated user can destroy all customers' sources, agents, and assessments

Single curl command causes total data loss across entire SaaS

Critical availability and integrity catastrophe

Fix Suggestion: Immediate: Hard-disable the handler (return 401 with explanatory message). Long-term: Either drop the route from openapi.yaml and delete SourceStore.DeleteAll, or re-implement as org-scoped bulk delete behind explicit edit permission. See patches/f004.patch.

First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203