Skip to content
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

TaintedSql false positives for prepared PDO statements #10047

Closed
cgocast opened this issue Jul 25, 2023 · 6 comments · Fixed by #10048
Closed

TaintedSql false positives for prepared PDO statements #10047

cgocast opened this issue Jul 25, 2023 · 6 comments · Fixed by #10048

Comments

@cgocast
Copy link
Contributor

cgocast commented Jul 25, 2023

The PHP documentation for PDO::prepare() states

Also, calling PDO::prepare() and PDOStatement::execute() helps to prevent SQL injection attacks by eliminating the need to manually quote and escape the parameters.

Therefore, the following code sample should not raise TaintedSql:

<?php

function deleteBindedUserId(PDO $pdo): void {
    $userId = $_POST['userid'];
    $stmt = $pdo->prepare("delete from users where user_id = :userid");
    $stmt->bindParam(':user_id', $userId);
    $stmt->execute();
}

function deleteConcatenedUserId(PDO $pdo): void {
    $userId = $_POST['userid'];
    $stmt = $pdo->prepare("delete from users where user_id = " . $userId);
    $stmt->execute();
}
@psalm-github-bot
Copy link

Hey @cgocast, can you reproduce the issue on https://psalm.dev ?

@danog
Copy link
Collaborator

danog commented Jul 25, 2023

function deleteConcatenedUserId(PDO $pdo): void {
    $userId = $_POST['userid'];
    $stmt = $pdo->prepare("delete from users where user_id = " . $userId);
    $stmt->execute();
}

This code should very much raise a TaintedSql issue :)

The first one however shouldn't, correct.

@cgocast
Copy link
Contributor Author

cgocast commented Jul 25, 2023

@danog Both code are very similar. I do not understand why the second one should raises a TaintedSql while the second should not. Please, can you give me a more detailed explanation ?

@danog
Copy link
Collaborator

danog commented Jul 25, 2023

Psalm is simply warning about the fact that using prepare() does not automagically escape the SQL you pass it: prepare() does not prevent SQL injection if you just concatenate a user-provided string to the query you pass it, you must pass it a prepared statement and separately specify the parameters to execute/bind them to avoid SQL injection.

@cgocast cgocast closed this as completed Aug 16, 2023
@weirdan
Copy link
Collaborator

weirdan commented Aug 16, 2023

The first one however shouldn't, correct.

@cgocast
Copy link
Contributor Author

cgocast commented Aug 16, 2023

This was fixed by PR #10048

@weirdan weirdan closed this as completed Aug 16, 2023
@weirdan weirdan linked a pull request Aug 16, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants