Skip to content

Fix SQL injection in Schema::findViewNames()#463

Merged
Tigrov merged 5 commits intoyiisoft:masterfrom
darkspock:fix/sql-injection-find-view-names
Apr 21, 2026
Merged

Fix SQL injection in Schema::findViewNames()#463
Tigrov merged 5 commits intoyiisoft:masterfrom
darkspock:fix/sql-injection-find-view-names

Conversation

@darkspock
Copy link
Copy Markdown
Contributor

Summary

Schema::findViewNames() interpolates the $schema parameter directly into a SQL heredoc string:

SELECT table_name FROM information_schema.tables
WHERE table_type = 'VIEW' AND table_schema = '$schema'
order by table_name

This is a SQL injection risk. While $schema typically comes from configuration rather than user input, this is inconsistent with the rest of the codebase where all other methods in this file use either parameterized queries or proper quoting:

  • findTableComment() (line 164): uses :schemaName bound parameter
  • findTableNames() (line 181): uses quoteSimpleTableName()
  • loadTableConstraints(), loadTableIndexes(), etc.: all use :schemaName

Fix

Replace direct string interpolation with a :schemaName bound parameter, consistent with findTableComment() and other methods in the same file.

Before

default => <<<SQL
SELECT table_name FROM information_schema.tables
WHERE table_type = 'VIEW' AND table_schema = '$schema'
order by table_name
SQL,

After

default => <<<SQL
SELECT table_name FROM information_schema.tables
WHERE table_type = 'VIEW' AND table_schema = :schemaName
order by table_name
SQL,

Risk

Very low — this is a direct replacement of string interpolation with parameter binding. The query behavior is identical.

The $schema variable was interpolated directly into the SQL string
in the heredoc, allowing potential SQL injection. While $schema
typically comes from configuration (not user input), this is
inconsistent with the rest of the codebase where all other
Schema methods use parameterized queries (e.g., findTableComment
uses :schemaName, findTableNames uses quoteSimpleTableName).

Replace direct interpolation with a :schemaName bound parameter,
consistent with the pattern used elsewhere in this file.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread src/Schema.php Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.84%. Comparing base (c9898f4) to head (af0212f).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #463      +/-   ##
============================================
+ Coverage     98.73%   98.84%   +0.11%     
- Complexity      255      256       +1     
============================================
  Files            24       24              
  Lines           790      779      -11     
============================================
- Hits            780      770      -10     
+ Misses           10        9       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Member

@Tigrov Tigrov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs line to changelog

Comment thread src/Schema.php Outdated
Comment on lines +190 to +199
SQL,
};

$params = $schema !== '' ? [':schemaName' => $schema] : [];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to combine two identical checks into one.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are different conditions in SQL: table_schema != 'sys' and table_schema = :schemaName.

Copy link
Copy Markdown
Member

@vjik vjik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest refactor code to:

if ($schema === '') {
    $sql = ...
    $params = ...
} else {
    $sql = ...
    $params = ...
}

I think it will be more clear.

@Tigrov
Copy link
Copy Markdown
Member

Tigrov commented Apr 3, 2026

if ($schema === '') {
    $sql = ...
    $params = ...
} else {
    $sql = ...
    $params = ...
}

That's what I meant.

@samdark samdark requested a review from Copilot April 5, 2026 08:46
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a SQL injection risk in the MySQL/MariaDB schema introspection layer by replacing direct string interpolation in Schema::findViewNames() with a bound parameter, aligning the implementation with other schema metadata queries in the same class.

Changes:

  • Replace $schema string interpolation in the information_schema.tables query with a :schemaName bound parameter.
  • Pass bound parameters to createCommand() when a non-empty schema is provided.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Schema.php Outdated
@samdark samdark requested a review from vjik April 5, 2026 08:54
@vjik vjik requested review from Tigrov and samdark April 20, 2026 19:46
@Tigrov Tigrov merged commit ad2e4d5 into yiisoft:master Apr 21, 2026
32 checks passed
@Tigrov
Copy link
Copy Markdown
Member

Tigrov commented Apr 21, 2026

👍

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.

6 participants