| <!--{ | |
| "Title": "Avoiding SQL injection risk" | |
| }--> | |
| You can avoid an SQL injection risk by providing SQL parameter values as `sql` | |
| package function arguments. Many functions in the `sql` package provide | |
| parameters for the SQL statement and for values to be used in that statement's | |
| parameters (others provide a parameter for a prepared statement and parameters). | |
| Code in the following example uses the `?` symbol as a placeholder for the | |
| `id` parameter, which is provided as a function argument: | |
| ``` | |
| // Correct format for executing an SQL statement with parameters. | |
| rows, err := db.Query("SELECT * FROM user WHERE id = ?", id) | |
| ``` | |
| `sql` package functions that perform database operations create prepared | |
| statements from the arguments you supply. At run time, the `sql` package turns | |
| the SQL statement into a prepared statement and sends it along with the | |
| parameter, which is separate. | |
| **Note:** Parameter placeholders vary depending on the DBMS and driver | |
| you're using. For example, [pq driver](https://pkg.go.dev/github.com/lib/pq) | |
| for Postgres accepts a placeholder form such as `$1` instead of `?`. | |
| You might be tempted to use a function from the `fmt` package to assemble the | |
| SQL statement as a string with parameters included – like this: | |
| ``` | |
| // SECURITY RISK! | |
| rows, err := db.Query(fmt.Sprintf("SELECT * FROM user WHERE id = %s", id)) | |
| ``` | |
| This is not secure! When you do this, Go assembles the entire SQL statement, | |
| replacing the `%s` format verb with the parameter value, before sending the | |
| full statement to the DBMS. This poses an | |
| [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) risk because the | |
| code's caller could send an unexpected SQL snippet as the `id` argument. That | |
| snippet could complete the SQL statement in unpredictable ways that are | |
| dangerous to your application. | |
| For example, by passing a certain `%s` value, you might end up with something | |
| like the following, which could return all user records in your database: | |
| ``` | |
| SELECT * FROM user WHERE id = 1 OR 1=1; | |
| ``` |