Skip to content

SQL Injection Analyzer ​

Analyzer IDCategorySeverityTime To Fix
sql-injection🛡️ SecurityCritical30 minutes

What This Checks ​

This analyzer detects potential SQL injection vulnerabilities in your Laravel application by identifying unsafe SQL query construction patterns:

  • String concatenation in SQL queries (e.g., "WHERE id = " . $id)
  • Variable interpolation in SQL queries (e.g., "WHERE name = '$name'")
  • Missing parameter bindings when user input is present
  • Unsafe usage of DB::raw(), whereRaw(), selectRaw(), and similar methods
  • DB::unprepared() usage (inherently unsafe)
  • Native query functions (mysqli_query, pg_query) with concatenation/interpolation

Two-Tier Detection

The analyzer uses context-aware detection to minimize false positives:

  • Full query methods (DB::select, DB::insert, DB::update, DB::delete, DB::raw) - flags all concatenation/interpolation when no bindings are present. When bindings are provided, only flags concatenation containing direct user input.
  • Fragment methods (whereRaw, orderByRaw, selectRaw, havingRaw) - only flags concatenation/interpolation that contains direct user input ($_GET, $_POST, request(), Request::input(), $request->input(), etc.). Table/column name concatenation is not flagged.

Why It Matters ​

SQL injection is one of the most critical security vulnerabilities (OWASP Top 10 #1) that can lead to:

  • Complete data breach - Attackers can extract entire databases
  • Data manipulation - Unauthorized modification or deletion of records
  • Authentication bypass - Logging in as any user including administrators
  • Privilege escalation - Gaining elevated system permissions
  • Server compromise - In severe cases, complete system takeover

A single SQL injection vulnerability can compromise your entire application, making it critical to detect and fix these issues before deployment.

How to Fix ​

Quick Fix (5 minutes) ​

Replace string concatenation with parameter binding:

Before (❌):

php
use Illuminate\Support\Facades\DB;

public function search($userId)
{
    // Vulnerable: String concatenation
    $results = DB::select(
        "SELECT * FROM users WHERE id = '" . $userId . "'"
    );
}

After (✅):

php
use Illuminate\Support\Facades\DB;

public function search($userId)
{
    // Safe: Parameter binding with placeholders
    $results = DB::select(
        "SELECT * FROM users WHERE id = ?",
        [$userId]
    );
}

Proper Fix (30 minutes) ​

Refactor to use Laravel's Query Builder or Eloquent ORM for automatic protection:

Before (❌):

php
public function searchUsers($name, $status)
{
    // Multiple vulnerabilities
    $query = "SELECT * FROM users WHERE name LIKE '%" . $name . "%'";
    if ($status) {
        $query .= " AND status = '" . $status . "'";
    }
    return DB::select($query);
}

After (✅):

php
public function searchUsers($name, $status)
{
    // Safe: Query Builder handles escaping automatically
    $query = DB::table('users')
        ->where('name', 'like', '%' . $name . '%');

    if ($status) {
        $query->where('status', $status);
    }

    return $query->get();
}

Best Practice (✅✅):

php
public function searchUsers(Request $request)
{
    // Validate input first
    $validated = $request->validate([
        'name' => 'required|string|max:255',
        'status' => 'nullable|in:active,inactive,pending',
    ]);

    // Use Eloquent with validated data
    return User::query()
        ->where('name', 'like', '%' . $validated['name'] . '%')
        ->when($validated['status'] ?? null, function ($query, $status) {
            $query->where('status', $status);
        })
        ->get();
}

ShieldCI Configuration ​

The analyzer can be customized to recognize additional native database functions specific to your application. To configure them, publish the config:

bash
php artisan vendor:publish --tag=shieldci-config

Then in config/shieldci.php:

php
'analyzers' => [
    'security' => [
        'enabled' => true,

        'sql-injection' => [
            // MySQLi query execution functions to check for SQL injection
            // Only functions that execute queries are checked (not prepare/connect/fetch)
            'mysqli_functions' => [
                'mysqli_query',        // Default
                'mysqli_real_query',   // Default
                'mysqli_multi_query',  // Default
                // Add any custom mysqli wrapper functions that execute queries
                'custom_db_query',
            ],

            // PostgreSQL query execution functions to check
            'postgres_functions' => [
                'pg_query',       // Default
                'pg_send_query',  // Default
                // Add any custom pg wrapper functions that execute queries
                'custom_pg_execute',
            ],
        ],
    ],
],

When to Customize

Only customize the function lists if you have custom query execution functions in your codebase.

Important: The analyzer only flags functions when SQL queries have concatenation or interpolation. Safe usage patterns are not flagged:

php
// ✅ NOT flagged - no concatenation
mysqli_query($conn, "SELECT * FROM users WHERE id = 1");

// ❌ FLAGGED - has concatenation
mysqli_query($conn, "SELECT * FROM users WHERE id = " . $userId);

The default lists cover standard MySQLi and PostgreSQL query execution functions. You typically don't need to customize unless you have wrapper functions like custom_execute_query() or legacy_db_run().

References ​