All skills
asyrafhussin avatar

/laravel-owasp-security

@ac26821

OWASP Top 10 security audit and secure coding guidelines for Laravel + React/Inertia.js applications. Use when auditing for vulnerabilities ("run OWASP audit", "security review", "check my app security") or writing secure Laravel code involving auth, payments, file uploads, or API design. Triggers on security-related tasks, payment handling, authentication, or any request to audit a Laravel codebase.

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/laravel-owasp-security

This session only. Nothing lands on disk.

rulessec-broken-access-control.md

≈1.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Prevent Broken Access Control

Impact: CRITICAL (Prevents unauthorized access to other users' data and privileged actions)

Why It Matters

  • Risk: Attackers access other users' records, perform admin actions, or read sensitive data by manipulating IDs or bypassing role checks
  • Impact: Full data breach, privilege escalation, unauthorized transactions
  • OWASP: A01:2021 — the most common critical vulnerability across web applications

Incorrect

<?php

// ❌ No ownership check — any authenticated user can view any payment
class PaymentController extends Controller
{
    public function show(int $id)
    {
        $payment = Payment::find($id);  // No ownership check

        return Inertia::render('payments/show', ['payment' => $payment]);
    }
}
<?php

// ❌ Admin route group without role middleware
Route::prefix('admin')->group(function () {
    Route::get('/users', [UserController::class, 'index']);
    Route::delete('/users/{user}', [UserController::class, 'destroy']);
    // Any authenticated user can reach these routes
});
<?php

// ❌ Relying on frontend role check without server-side enforcement
class ReportController extends Controller
{
    public function financial()
    {
        // No middleware — assumes React UI hid the link from non-admins
        $data = Payment::all();

        return Inertia::render('reports/financial', compact('data'));
    }
}

Problems:

  • Any authenticated user can access any record by changing the ID in the URL
  • Role checks only on the frontend are trivially bypassed — users can call routes directly
  • Missing middleware on admin route groups exposes privileged actions to all users

Correct

Always Check Ownership

<?php

declare(strict_types=1);

// ✅ Scope resource to authenticated user
class PaymentController extends Controller
{
    public function show(int $id)
    {
        $payment = Payment::where('user_id', auth()->id())
            ->findOrFail($id);

        return Inertia::render('payments/show', ['payment' => $payment]);
    }
}

Protect Route Groups with Middleware

<?php

// ✅ Role middleware enforced at route level
Route::middleware(['auth', 'role:admin'])->prefix('admin')->name('admin.')->group(function () {
    Route::get('/users', [UserController::class, 'index'])->name('users.index');
    Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('users.destroy');
});

// ✅ Multiple roles allowed
Route::middleware(['auth', 'role:teacher,moderator,admin'])->prefix('manage')->group(function () {
    Route::resource('classes', ClassManagementController::class);
});

Use Gates and Policies

<?php

declare(strict_types=1);

// ✅ Policy — define authorization logic separately
class PaymentPolicy
{
    public function view(User $user, Payment $payment): bool
    {
        return $user->id === $payment->user_id;
    }

    public function update(User $user, Payment $payment): bool
    {
        return $user->id === $payment->user_id
            && $payment->status === 'pending';
    }
}

// ✅ Controller uses Gate/Policy
class PaymentController extends Controller
{
    public function show(Payment $payment)
    {
        $this->authorize('view', $payment);

        return Inertia::render('payments/show', ['payment' => $payment]);
    }
}

Scope All Queries to the Authenticated User

<?php

declare(strict_types=1);

// ✅ Use global scope or always filter by authenticated user
class RegistrationController extends Controller
{
    public function index()
    {
        $registrations = Registration::where('student_id', auth()->id())
            ->with(['class', 'payments'])
            ->latest()
            ->paginate(20);

        return Inertia::render('student/registrations/index', compact('registrations'));
    }
}

Mirror Server-Side Checks — Never Trust Frontend Alone

<?php

declare(strict_types=1);

// ✅ Middleware enforces access — React UI hiding a link is not security
Route::middleware(['auth', 'verified', 'role:admin'])->group(function () {
    Route::get('/admin/reports/financial', [ReportController::class, 'financial']);
});

// React link may be hidden from non-admins — but the route is still protected
// Even if a user manually navigates to the URL, middleware blocks them

Recommended Patterns

Pattern Use Case
->where('user_id', auth()->id())->findOrFail($id) Scope any resource to current user
$this->authorize('action', $model) Policy-based authorization per action
Route::middleware('role:admin') Protect admin route groups
abort_unless($condition, 403) Inline authorization guard
Gate::authorize('action', $model) Gate-based authorization in services

Reference: OWASP Laravel Cheat Sheet

Source: SKILL.md on GitHub

1 warning16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The analyzed skill is a security auditing and secure coding reference toolkit designed specifically for Laravel 13 + React/Inertia.js environments. It operates using standard pattern matching and reference documentation to provide static code reviews without executing external code or performing suspicious administrative operations. No safety violations or malicious behaviors were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    6/14 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at ac26821. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
Other metadata
metadata
{
  "author": "AsyrafHussin",
  "version": "1.0.3",
  "laravelVersion": "13.x",
  "phpVersion": "8.3+"
}

README badge

README badge for asyrafhussin/agent-skills/laravel-owasp-security