Skip to content

SNOW-3417310 fix SQL injection in snow cortex complete/translate#2993

Draft
sfc-gh-olorek wants to merge 1 commit into
mainfrom
proactive/SNOW-3417310-cortex-sqli
Draft

SNOW-3417310 fix SQL injection in snow cortex complete/translate#2993
sfc-gh-olorek wants to merge 1 commit into
mainfrom
proactive/SNOW-3417310-cortex-sqli

Conversation

@sfc-gh-olorek
Copy link
Copy Markdown
Contributor

@sfc-gh-olorek sfc-gh-olorek commented May 8, 2026

Pre-review checklist

  • I've confirmed that instructions included in README.md are still correct after my changes in the codebase.
  • I've added or updated automated unit tests to verify correctness of my new code.
  • I've added or updated integration tests to verify correctness of my new code.
  • I've confirmed that my changes are working by executing CLI's commands manually on MacOS.
  • I've confirmed that my changes are working by executing CLI's commands manually on Windows.
  • I've confirmed that my changes are up-to-date with the target branch.
  • I've described my changes in the release notes.
  • I've described my changes in the section below.
  • I've described my changes in the documentation.

Changes description

CortexManager builds its SQL with Python f-strings and sends it through execute_stream, which tokenizes the text on ;. Three arguments were interpolated without any escaping:

  • snow cortex complete --backend sql --model <value> (both the text-prompt and PARSE_JSON branches in CortexManager.complete)
  • snow cortex translate --from <value>
  • snow cortex translate --to <value>

Because a single quote inside any of those values closes the surrounding SQL string literal, a caller could smuggle arbitrary SQL into the session. Example:

snow cortex complete "prompt" --backend sql --model "evil'; SELECT 1; --"

would emit SELECT SNOWFLAKE.CORTEX.COMPLETE('evil'; SELECT 1; --', 'prompt') AS CORTEX_RESULT; and the injected SELECT 1 would execute under the user's session.

The text/source-document/question arguments on the same call sites already went through CortexManager._escape_input. This change routes the model and language arguments through the same helper (with str(...) to cover the NewType wrappers), so single quotes and backslashes are escaped consistently across all five interpolated values.

Tests

Added three unit tests in tests/cortex/test_cortex_commands.py that pass a '; SELECT 1; -- payload through --model, --to, and --from respectively and assert the emitted SQL escapes the quote. Full tests/cortex/test_cortex_commands.py suite (21 tests) passes locally.

Jira: SNOW-3417310

The --model argument of `snow cortex complete --backend sql` and the
--from / --to arguments of `snow cortex translate` were interpolated
verbatim into the generated SELECT SNOWFLAKE.CORTEX.* SQL. A single
quote in the value closed the string literal, and because the query is
sent through execute_stream the trailing characters were parsed as
additional statements, letting a caller smuggle arbitrary SQL into the
session (e.g. --model "evil'; SELECT 1; --").

Apply the existing _escape_input helper to these three arguments as
well so any single quote or backslash is escaped before it hits the
SQL text. Added unit tests covering each parameter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant