Skip to content
Report library
Purpose / Other

Laravel Specialist Skill Security Audit

What the author says it does (original text)

Build and configure Laravel 10+ applications, including creating Eloquent models and relationships, implementing Sanctum authentication, configuring Horizon queues, designing RESTful APIs with API resources, and building reactive interfaces with Livewire. Use when creating Laravel models, setting up queue workers, implementing Sanctum auth flows, building Livewire components, optimising Eloquent q

Independent security check

Do not install or run it yet

Files checked
6
Risks found
5
Could it run dangerous commands?Looks for programs run straight after downloading, remote control of your computer, and hidden commands.Risks found: 1
Medium risk

Validation step processes one real job from the configured queue

Source references: 3
What we found

The Skill lists queue:work --once as an implementation checkpoint. This is not a read-only inspection: it reserves and executes one queued job. Application jobs may send email, call external APIs, publish content, charge services, or change database records.

Why this matters

If the project points to a production Redis, SQS, or database queue, routine code verification could prematurely execute a real business task, alter data, or contact users.

This is an active validation instruction, not a read-only status check: queue:work --once consumes and executes one job from the configured queue. The Skill's own job template changes a post's status and publication time, so even one run can alter the database; project-specific jobs may have other side effects. The risk arises only if the agent runs this checkpoint while the queue is nonempty. Users can restrict it to an isolated test environment or require confirmation of the connection, queue, and pending job first.

SKILL.md:250In the instructionsOpen original file
Run these at each workflow stage to confirm correctness before proceeding:| Stage | Command | Expected Result ||-------|---------|-----------------|| After migration | `php artisan migrate:status` | All migrations show `Ran` || After routing | `php artisan route:list --path=api` | New routes appear with correct verbs || After job dispatch | `php artisan queue:work --once` | Job processes without exception || After implementation | `php artisan test --coverage` | >85% coverage, 0 failures || Before PR | `./vendor/bin/pint --test` | PSR-12 linting passes |
Show 2 other places
references/queues.md:268In the instructionsOpen original file
# Process one jobphp artisan queue:work --once
SKILL.md:199In the instructionsOpen original file
    public function handle(): void    {        $this->post->update([            'status'       => PostStatus::Published,            'published_at' => now(),        ]);    }
Could it expose your files or keys?Looks for uploads of files containing passwords or keys, and keys written directly in the code.Risks found: 2
Medium risk

Failed-queue guide includes a global flush command without confirmation or environment scoping

Source references: 2
What we found

The reference supplies php artisan queue:flush, which removes all failed jobs, without requiring listing, export, backup, or environment confirmation. Failed-job records are commonly needed for retries, incident diagnosis, and audit history.

Why this matters

If run in the wrong environment, all failed-job records may be removed, preventing recovery of important work and erasing context needed to investigate failures.

The failed-jobs section explicitly provides queue:flush as the command to flush failed jobs. It removes all records from the application's configured failed-job store, while the surrounding guidance has no environment restriction, backup, listing, or confirmation step; those records may still be needed for retries and incident analysis. It is a reference snippet and does not run merely by installing the Skill, but an agent handling failed queues may use it. Users can forbid it in production or require listing and export before execution.

references/queues.md:238In the instructionsOpen original file
// Retry all failed jobsphp artisan queue:retry all// Flush failed jobsphp artisan queue:flush// Prune failed jobsphp artisan queue:prune-failed --hours=48
Show 1 other places
references/queues.md:232In the instructionsOpen original file
## Failed Jobs```php// Retry failed jobphp artisan queue:retry <job-id>// Retry all failed jobsphp artisan queue:retry all// Flush failed jobsphp artisan queue:flush// Prune failed jobsphp artisan queue:prune-failed --hours=48
Medium risk

Queue error templates may persist sensitive exception content in logs

Source references: 3
What we found

The templates log complete exception messages, and the monitoring example passes the exception object itself to the logger. Exceptions can contain request bodies, database values, remote responses, connection details, or tokens; the templates apply no redaction or field restrictions.

Why this matters

Sensitive data could enter application logs or external logging platforms, increasing the number of people who can access it, its retention period, and the scope of a later disclosure.

Two reusable templates write exception details to logs: one records the full getMessage(), and the monitoring example records the exception object. If an exception contains request data, database values, remote responses, or connection details, that material could enter persistent logs and become visible to log readers or external logging services. The source does not prove secrets are present or logs are exported, but the exposure path is plausible. Users can ask for allowlisted fields, redaction, and environment-controlled exception detail.

SKILL.md:207In the instructionsOpen original file
    public function failed(\Throwable $e): void    {        // Log or notify — never silently swallow failures        logger()->error('PublishPost failed', ['post' => $this->post->id, 'error' => $e->getMessage()]);    }
Show 2 other places
references/queues.md:355In the instructionsOpen original file
    Queue::failing(function (JobFailed $event) {        // Called when job fails        \Log::error('Job failed', [            'job' => $event->job->resolveName(),            'exception' => $event->exception,        ]);    });
references/queues.md:40In the instructionsOpen original file
    public function failed(\Throwable $exception): void    {        // Handle job failure        \Log::error('Post processing failed', [            'post_id' => $this->post->id,            'error' => $exception->getMessage(),        ]);    }
Could it delete files or keep running?Looks for broad file deletion, disk overwrites, and programs set to start automatically.No risks found
Could it bypass safety checks?Looks for skipped website security checks, excessive file access, or actions that skip your approval.Risks found: 2
High risk

API template lets any authenticated user update or delete another user's posts

Source references: 3
What we found

The routes require only Sanctum authentication. The controller's update and destroy methods directly mutate the route-bound Post without invoking a policy, Gate, or ownership check. This conflicts with the supplied test expectation that users cannot update another user's post.

Why this matters

If copied as supplied, any ordinary account could alter or delete posts whose IDs it can discover or guess, causing content tampering or data loss.

The API example authenticates users with Sanctum but passes any route-bound Post directly to update and destroy without a policy, Gate, or ownership check. If used as a starting template, an authenticated user who can identify another post could modify or delete it. The testing guide expects a 403 for updating another user's post, but the shown controller does not implement that rule. Users can ask the author to demonstrate explicit Policy/Gate checks on every write operation.

references/routing.md:52In the instructionsOpen original file
    // Protected routes    Route::middleware('auth:sanctum')->group(function () {        Route::post('/posts', [PostController::class, 'store']);        Route::put('/posts/{post}', [PostController::class, 'update']);        Route::delete('/posts/{post}', [PostController::class, 'destroy']);    });});
Show 2 other places
references/routing.md:104In the instructionsOpen original file
    public function update(UpdatePostRequest $request, Post $post)    {        $post->update($request->validated());        return new PostResource($post);    }    public function destroy(Post $post)    {        $post->delete();        return response()->noContent();    }}
references/testing.md:94In the instructionsOpen original file
    public function test_user_cannot_update_others_post(): void    {        $user = User::factory()->create();        $otherUser = User::factory()->create();        $post = Post::factory()->create(['user_id' => $otherUser->id]);        $response = $this->actingAs($user)->put("/api/posts/{$post->id}", [            'title' => 'Updated Title',        ]);        $response->assertStatus(403);    }
High risk

Livewire templates expose edit and delete operations without object-level authorization

Source references: 5
What we found

The form accepts a Post and directly updates it in save; another public component method finds and deletes a post using a client-supplied ID. Neither operation calls authorize when it performs the mutation. Livewire public methods and state can be invoked through browser requests, so client parameters are not trusted.

Why this matters

Users who can reach these components may substitute a post or ID to edit, retag, attach an uploaded image to, or delete records they do not own.

The Livewire form accepts a route-supplied Post and updates it directly in save; the delete method also looks up and deletes a post using a browser-supplied ID. Neither operation performs object-level authorization. A separate authorization example appears later, but it does not automatically protect these earlier components. If copied as shown, users able to invoke the component could edit or delete posts they do not own. Users can ask that authorization be integrated into every complete mutating template and tested with unauthorized IDs.

references/livewire.md:141In the instructionsOpen original file
    public function mount(?Post $post = null): void    {        if ($post) {            $this->post = $post;            $this->title = $post->title;            $this->content = $post->content;            $this->tags = $post->tags->pluck('id')->toArray();        }    }
Show 4 other places
references/livewire.md:156In the instructionsOpen original file
    public function save(): void    {        $validated = $this->validate();        if ($this->post) {            $this->post->update($validated);            $message = 'Post updated successfully!';        } else {            $this->post = Post::create($validated);            $message = 'Post created successfully!';        }        if ($this->image) {            $this->post->update([                'image_path' => $this->image->store('posts', 'public'),            ]);        }        $this->post->tags()->sync($this->tags);
references/livewire.md:305In the instructionsOpen original file
// Emit eventclass PostList extends Component{    public function deletePost($postId): void    {        Post::find($postId)->delete();        $this->emit('postDeleted', $postId);    }}
references/livewire.md:307In the instructionsOpen original file
{    public function deletePost($postId): void    {        Post::find($postId)->delete();        $this->emit('postDeleted', $postId);    }}
references/livewire.md:464In the instructionsOpen original file
    public function mount(Post $post): void    {        $this->authorize('update', $post);        $this->post = $post;    }    public function save(): void    {        $this->authorize('update', $this->post);        // Save logic
Could it mislead the AI or hide text?Checks the skill instructions for requests to ignore you, influence the report, or hide text in invisible characters.No risks found
Could it change links or payment recipients without asking?Looks for forced referral or payment changes combined with instructions to hide the change.No risks found

Inside this skill

6 instruction sections

The Skill mainly generates Laravel application code and directs the agent to run Artisan commands for migrations, routes, and tests. Those commands act on the environment configured by the current Laravel project.

View source
SKILL.md:22In the instructionsOpen original file
1. **Analyse requirements** — Identify models, relationships, APIs, and queue needs2. **Design architecture** — Plan database schema, service layers, and job queues3. **Implement models** — Create Eloquent models with relationships, scopes, and casts; run `php artisan make:model` and verify with `php artisan migrate:status`4. **Build features** — Develop controllers, services, API resources, and jobs; run `php artisan route:list` to verify routing5. **Test thoroughly** — Write feature and unit tests; run `php artisan test` before considering any step complete (target >85% coverage)

The main file says to use its code templates as the starting point for every implementation. Authorization, deletion, logging, and queue examples in the references may therefore be copied into user projects rather than merely read.

View source
SKILL.md:62In the instructionsOpen original file
## Code TemplatesUse these as starting points for every implementation.

The Skill explicitly requires input validation, protection of sensitive data, and permission-related tests, showing that basic security controls are part of its stated intent; some supplied templates do not apply them consistently.

View source
SKILL.md:52In the instructionsOpen original file
### MUST NOT DO- Use raw queries without protection (SQL injection)- Skip eager loading (causes N+1 problems)- Store sensitive data unencrypted- Mix business logic in controllers- Hardcode configuration values- Skip validation on user input- Use deprecated Laravel features
references/testing.md:94In the instructionsOpen original file
    public function test_user_cannot_update_others_post(): void    {        $user = User::factory()->create();        $otherUser = User::factory()->create();        $post = Post::factory()->create(['user_id' => $otherUser->id]);        $response = $this->actingAs($user)->put("/api/posts/{$post->id}", [            'title' => 'Updated Title',        ]);        $response->assertStatus(403);    }
Start here · InstructionsSKILL.md
laravel-specialist
Lines connect the instruction file to its sections, not an observed execution order. Select a section to read the source.

File reference map

References: 5
Files making referencesReferenced content
Lines show actual file references, not execution order. Select a node to highlight its connections and inspect the files and source locations. Dashed lines include files that still need locating.
Files and check records6 files

Coverage and gaps

Content covered in each file

These are the source ranges included in this check, not a guarantee that every issue has been resolved.

  • SKILL.mdFull text included
  • references/eloquent.mdFull text included
  • references/livewire.mdFull text included
  • references/queues.mdFull text included
  • references/routing.mdFull text included
  • references/testing.mdFull text included

This report is for the version above. We read the available code and instructions without running the skill or checking extra packages it installs. This is not a promise of safety: a different version or setup may behave differently.

  • SKILL.mdInstructions
  • references/eloquent.mdSupporting file
  • references/livewire.mdSupporting file
  • references/queues.mdSupporting file
  • references/routing.mdSupporting file
  • references/testing.mdSupporting file

Operations mentioned in code and instructions

Connect to websites
SKILL.md:6In the instructionsOpen original file
metadata:  author: https://github.com/Jeffallan  version: "1.1.0"
SKILL.md:264In the instructionsOpen original file
[Documentation](https://jeffallan.github.io/claude-skills/skills/backend/laravel-specialist/)
references/routing.md:356In the instructionsOpen original file
    'allowed_methods' => ['*'],    'allowed_origins' => ['http://localhost:3000'],    'allowed_headers' => ['*'],
Run commands
references/queues.md:261In the instructionsOpen original file
```bash# Start worker
references/routing.md:321In the instructionsOpen original file
```bash# Generate route cache
references/testing.md:483In the instructionsOpen original file
```bash# Run all tests
Read keys or account settings
references/routing.md:360In the instructionsOpen original file
    'max_age' => 0,    'supports_credentials' => true,];
Lines read
2,440
File checksum (to compare versions)
bdbf24e14d77e5ed4cb1ae8395fb4b5e6446061b7ff2684bdb38ce81b1c085bd