> ## Content Index
> Fetch the complete content index at: https://securinglaravel.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Security Tip: Parameterise your Parameter Names!
- URL: https://securinglaravel.com/security-tip-parameterise-your-parameter-names/
- Published: 2024-09-20T04:50:55.000Z
- Updated: 2024-09-20T04:50:55.000Z
- Description: [Tip #91] aka yet another example for why you should Never Trust User Input!
- Author: Stephen Rees-Carter
- Tags: Security Tips, SQLi

Today's Security Tip comes from a [newly reported vulnerability](https://github.com/navidrome/navidrome/security/advisories/GHSA-58vj-cv5w-v4v6?ref=securinglaravel.com) I saw this morning on Twitter:

[![](https://storage.ghost.io/c/d9/0d/d90de76f-6031-4e2c-85b8-3447a38c4992/content/images/2024/09/image-14.png)](https://x.com/lukejahnke/status/1836972133718929668?ref=securinglaravel.com)

The primary protection we have against [SQL Injection (SQLi)](https://securinglaravel.com/tag/sqli/) is to parameterise user input, to safely inject it into our SQL queries. It's standard practice, something we talk about all the time, and Laravel makes it pretty easy. In fact, I don't see many SQLi vulnerabilities in Laravel apps because Eloquent is so powerful.

💡

**In my experience, the more complicated the query and the more raw SQL you need to write, the higher chance of SQLi.*

Parameterisation is pretty standard practice, and we're all used to writing our queries in Laravel like this:

```php
$projects = Project::where('active', true)
    ->when($request->access_code, fn($query, $accessCode) => 
        $query->where('access_code', $accessCode))
    ->when($request->preview_code, fn($query, $previewCode) => 
        $query->orWhere('preview_code', $previewCode))
    ->where('created_at', '>', now()->subYear())
    ->get();

```

However, something that often gets overlooked is that we don't just need to escape our values... **we also need to escape our parameter names too!**

Consider this code:

```php
$firstKey = collect($request->query())->keys()->first();
$firstValue = $request->query($firstKey);

$projects = Project::where('active', true)
    ->where($firstKey, $firstValue)
    ->where('created_at', '>', now()->subYear())
    ->get();
```

It looks like a simplification to avoid adding more nested `when()` calls, and would handle each of these URLs nicely:

```
https://example.com/projects?access_code=mellon
https://example.com/projects?preview_code=precious
https://example.com/projects?uuid=7da13f1a-b74c-4b3c-aae5-c311fd866894
```

But what if this was provided:

```
https://example.com/projects?id=1
```

The `access_code`, `preview_code`, and `uuid`, would be completely bypassed, allowing access to whatever the first project is. You could then enumerate through each ID...

This is because the **Parameter Name** comes from user input, and is being blindly trusted, and you should **never trust user input.**

When dealing with database names and table columns, **my recommendation** is to use a list of allowed names and only use values within list. These things are rarely, if ever, dynamic, and you should know the structure of your app.

If you do need to inject dynamic parameter names into queries, limit the character set to remove special characters, and strip out sensitive keywords, etc. You need to limit these values as much as possible, as this will introduce risks. *(Don't say I didn't warn you!)*

---

---

**Found this security tip helpful?* Don't forget to* [*subscribe*](https://securinglaravel.com/#/portal/signup) *to receive new* [*Security Tips*](https://securinglaravel.com/tag/tips/) *each week, and upgrade to a* [*premium subscription*](https://securinglaravel.com/#/portal/signup) *to receive monthly* [*In Depth articles*](https://securinglaravel.com/tag/in-depth/)*, or toss a coin in the* [*tip jar*](https://securinglaravel.com/#/portal/support)*.*

*You can follow Stephen on* [*Twitter*](https://twitter.com/valorin?ref=securinglaravel.com)*,* [*Fediverse*](https://phpc.social/@valorin?ref=securinglaravel.com)*,* [*LinkedIn*](https://www.linkedin.com/in/stephen-rees-carter/?ref=securinglaravel.com)*,* [*Pinkary*](https://pinkary.com/@valorin?ref=securinglaravel.com)*,* [*Bluesky*](https://bsky.app/profile/valorin.bsky.social?ref=securinglaravel.com)*, and* [*Threads*](https://www.threads.net/@valorinsrc?ref=securinglaravel.com)*, and reach out if you're looking for a* [*Laravel Security Audit and Penetration Test*](https://stephenreescarter.net/laravel-security-audits-and-pentesting/?utm%5Fsource=securinglaravel.com) *or a budget-friendly* [*Security Review*](https://stephenreescarter.net/laravel-security-reviews/?utm%5Fsource=securinglaravel.com)*.*

*Finally, to learn more about security through a series of interactive challenges, check out Stephen's new course:* [*Practical Laravel Security*](https://practicallaravelsecurity.com/?utm%5Fsource=securinglaravel.com)*.*