-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix(pandas-gbq): reject backticks in parse_table_id #18156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,6 +53,14 @@ def parse_table_id(table_id: str) -> Union[BigLakeTableId, BigQueryTableId]: | |
| if any(part == "" for part in inner_parts): | ||
| raise ValueError(f"Invalid table ID: {table_id}") | ||
|
|
||
| # The parsed parts are interpolated into backtick-quoted table references in | ||
| # generated SQL (see core/biglake.py and core/sample.py). A backtick can't | ||
| # appear in a real project/dataset/table name, and one here would close the | ||
| # identifier quoting and let the rest of the string run as SQL, so reject it | ||
| # while we're validating the table ID rather than downstream. | ||
| if "`" in table_id: | ||
| raise ValueError(f"Invalid table ID: {table_id}") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit (non-blocking): We could move this before the |
||
|
|
||
| if len(inner_parts) == 1: | ||
| return BigQueryTableId( | ||
| project_id=regex_match.group("project"), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,11 @@ def test_parse_table_id_valid(table_id, expected): | |
| ".my_dataset.my_table", | ||
| "my-project.my_dataset.", | ||
| "my-project..my_table", | ||
| # A backtick would close the identifier quoting in the generated SQL and | ||
| # let the rest of the string run as SQL, so it must be rejected here. | ||
| "my-project.my_dataset.my_table` ORDER BY (SELECT 1) -- ", | ||
| "my-project.my_catalog.my_namespace.evil` UNION ALL SELECT 1 -- ", | ||
| "my-project.my_dataset.`", | ||
|
Comment on lines
+72
to
+74
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In addition to backticks, we should also test that table IDs containing backslashes are rejected, as they can be used to escape the closing backtick in generated SQL. "my-project.my_dataset.my_table` ORDER BY (SELECT 1) -- ",
"my-project.my_catalog.my_namespace.evil` UNION ALL SELECT 1 -- ",
"my-project.my_dataset.`",
"my-project.my_dataset.my_table\\",
"my-project.my_dataset.my_\\table", |
||
| ], | ||
| ) | ||
| def test_parse_table_id_invalid(table_id): | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While rejecting backticks prevents direct closing of the identifier quoting, a backslash (
\) can be used in BigQuery SQL to escape the closing backtick (e.g., ```). If a table ID ends with a backslash, it would escape the closing backtick in the generated SQL, potentially leading to SQL injection or syntax errors if there are subsequent backticks in the query. Since backslashes are not valid characters in BigQuery project, dataset, or table IDs, they should also be rejected here to prevent any escaping-based bypasses.