> ## 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: The Trap That Caught Me!
- URL: https://securinglaravel.com/security-tip-the-trap-that-caught-me/
- Published: 2026-09-05T06:00:38.000Z
- Updated: 2026-09-05T06:00:38.000Z
- Description: [Security Tip #135] During a recent pentest, I suddenly got hit with 403s on every request. It wasn't a WAF - it was a clever little trap one of my clients built to catch anyone poking at Livewire. Let me show you how it works. 🤓
- Author: Stephen Rees-Carter
- Tags: Security Tips, Livewire

One of the cool parts of doing [Laravel Security Audits and Penetration Tests](https://valorinsecurity.com/?ref=securinglaravel.com) is seeing how my clients go about solving different problems in their code, and some of their creative security implementations. One such example is a class called `LivewireBotBanner`, which I came across during a recent audit. 

I discovered it by accident when I was attempting to override some Livewire properties that were incorrectly configured. I made a request to a locked property and suddenly hit `403` errors on all requests. I assumed it was a WAF being overly twitchy, rotated my IP address, and got back in. But it didn't feel right, my request shouldn't have looked suspicious - especially not compared to some of the other requests I'd made. 

So I went digging...

I quickly discovered a global middleware called `EnforceBotProtection` which looks for suspicious User-Agents (i.e. `curl`, `wget`, `python`, etc), and that made me smile, but clearly wasn't the cause of my `403` \- Burp's browser (which I use during pentests) isn't that lazy.

I kept digging and saw this line in the middleware:

```php
if (LivewireBotBanner::isBanned($ip)) {
    abort(403, 'Forbidden');
}
```

After digging into `LivewireBotBanner`, I realised it was a class dedicated to identifying and blocking anyone making suspicious requests to Livewire. The global exception handler (`\App\Exceptions\Handler`) was configured to catch two notable Livewire exceptions, and call `LivewireBotBanner::ban()` to do the actual banning:

```php
if (
    $e instanceof ComponentNotFoundException 
    || $e instanceof CannotUpdateLockedPropertyException
) {
    LivewireBotBanner::ban($request, $e);
}
```

Such a simple and elegant trick: `ComponentNotFoundException` is fired when a component that doesn't exist is requested, and `CannotUpdateLockedPropertyException` is fired when the user attempts to change a locked property. Neither of these should happen during normal operation, so they provide strong indications that the user is doing something suspicious.

The automatic response to these exceptions was to block the user by IP address, returning a `403 Forbidden`, which feels like a suitable response when you're confident it will only be hit by someone doing something intentionally suspicious.

That said, there are a couple of caveats I should mention:

1. **This system blocks by IP address**, and it's trivial to rotate your IP if you know what you're doing. In other words, it won't stop a determined attacker. However, you could enhance this protection by introducing a temporary ban on the user account itself - lock them out for 15 minutes, or send an email with an unlock link. The latter serves a dual purpose of notifying the user of suspicious activity, in case of account takeover. (*In defence of my client, they have public Livewire forms where IP is the only unique identifier available.)*
2. **False positives are possible.** A buggy deploy or misconfigured properties could trigger these exceptions, locking out the user. So ensure you've got suitable tests and QA, and an unlock method.
3. **Couple this with logging and alerting**, so your team are notified if users start getting blocked. This serves as both a warning system for an active attack, and an alert if something breaks and legitimate requests are blocked.

**My recommendation** is to explore something like this in your code. When you've got exceptions and errors that should only occur during suspicious activity, having some alerting or active defences in place surrounding these won't cost you much, but may slow down or prevent an attacker from poking at your app further.

🤓

**Full credit for this idea goes to* [***Janos Burkhalter**](https://valuequest.ch/en/about-valuequest/janos-burkhalter/?ref=securinglaravel.com) *at* [**ValueQuest*](https://valuequest.ch/?ref=securinglaravel.com)**, with permission given for me to write about it.*

---

***Found this security tip useful?* 👍**  
[*Subscribe now*](#/portal/signup) *to get weekly* [*Security Tips*](https://securinglaravel.com/tag/tips/) *straight to your inbox - practical, actionable advice to help you build safer apps.*

***Want to go deeper?* 🤓**  
*Upgrade to a* [*Premium Subscription*](#/portal/signup) *for exclusive monthly* [*In Depth articles*](https://securinglaravel.com/tag/in-depth/)*. Your support directly funds my security work in the Laravel community.* 🥰

**Need a second set of eyes on your code?** 
*Book a* [*Laravel Security Audit and Penetration Test*](https://valorinsecurity.com/?ref=securinglaravel.com) *\- or, for something more focused, a lighter-weight* [*Security Review*](https://stephenreescarter.net/laravel-security-reviews/?utm%5Fsource=securinglaravel.com)*.*

*Finally, connect with me on* [*Twitter*](http://twitter.com/valorin?ref=securinglaravel.com)*,* [*Bluesky*](https://bsky.app/profile/valorin.bsky.social?ref=securinglaravel.com)*,* [*phpc.social*](https://phpc.social/@valorin?ref=securinglaravel.com)*, and* [*LinkedIn*](https://www.linkedin.com/in/stephen-rees-carter/?ref=securinglaravel.com)*.*