PHPackages                             alexkramse/laravel-hide-forbidden - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. alexkramse/laravel-hide-forbidden

ActiveLibrary[Security](/categories/security)

alexkramse/laravel-hide-forbidden
=================================

Hide all or selected Laravel 403 Forbidden responses behind 404 Not Found responses.

1.1.0(1mo ago)831MITPHPPHP ^8.1

Since Jul 4Pushed 1mo agoCompare

[ Source](https://github.com/alexkramse/laravel-hide-forbidden)[ Packagist](https://packagist.org/packages/alexkramse/laravel-hide-forbidden)[ RSS](/packages/alexkramse-laravel-hide-forbidden/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (4)Dependencies (5)Versions (2)Used By (0)

Laravel Hide Forbidden
----------------------

[](#laravel-hide-forbidden)

[![Tests](https://camo.githubusercontent.com/d940ad7f0752e2cbe0d63c50dcebf329078807390051c41fe63258f1b5c4e182/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d70617373696e672d627269676874677265656e)](https://camo.githubusercontent.com/d940ad7f0752e2cbe0d63c50dcebf329078807390051c41fe63258f1b5c4e182/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d70617373696e672d627269676874677265656e)[![Stable Version](https://camo.githubusercontent.com/90170b7b0a443a6d9c081307630fdaa91c13f094235bced7bc4185efdbb258af/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f737461626c652d76312e312e302d626c7565)](https://camo.githubusercontent.com/90170b7b0a443a6d9c081307630fdaa91c13f094235bced7bc4185efdbb258af/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f737461626c652d76312e312e302d626c7565)[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)

**Don’t reveal what should stay hidden. 404 is better than 403 when the existence of a resource should remain private.**

Laravel Hide Forbidden improves your application’s security posture by converting selected `403 Forbidden` responses into `404 Not Found`. This helps prevent exposure of sensitive endpoints such as admin panels, tenant resources, private models, or internal APIs.

The idea for this package comes from a security insight shared by Nuno Maduro: *“404 is better than 403”* — emphasizing that security should not leak the existence of protected resources. Thanks to Nuno.

By default, the package is enabled only in production and works via middleware, giving you full control over which routes adopt this behavior without affecting Laravel’s global exception handling.

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10 | 11 | 12 | 13

Version
-------

[](#version)

The current stable package version is `1.1.0`.

Installation
------------

[](#installation)

Install the package:

```
composer require alexkramse/laravel-hide-forbidden
```

Laravel discovers the service provider automatically through Composer package discovery.

Publish the config:

```
php artisan vendor:publish --tag=hide-forbidden-config
```

Usage
-----

[](#usage)

### Route-Level Usage

[](#route-level-usage)

The safest way to use the package is to attach the `hide-forbidden` middleware only to routes where you want forbidden responses hidden:

```
Route::middleware('hide-forbidden')->group(function (): void {
    Route::get('/admin/secret', SecretController::class);
});
```

With the default config, this route-level middleware mode is the only place conversion happens:

```
'enabled' => env('HIDE_FORBIDDEN_ENABLED', env('APP_ENV', 'production') === 'production'),
'mode' => env('HIDE_FORBIDDEN_MODE', 'middleware'),
```

### Global Usage

[](#global-usage)

To hide every matching `403` response in production, switch to `all` mode:

```
// config/hide-forbidden.php
'mode' => 'all',
```

Use `except_routes` and `except_paths` to keep auth, public API, or other routes unchanged.

### Named Route Matching

[](#named-route-matching)

Use `routes` mode when you only want to hide forbidden responses for specific named route groups:

```
'mode' => 'routes',

'only_routes' => [
    'admin.*',
    'teams.members.*',
],
```

Route patterns use Laravel's `routeIs()` matching.

### Path Matching

[](#path-matching)

Use `paths` mode when routes are not named or when URL patterns are clearer:

```
'mode' => 'paths',

'only_paths' => [
    'admin/*',
    'internal/*',
],
```

Path patterns use Laravel request path matching.

### Excluding Auth Routes

[](#excluding-auth-routes)

Authentication routes are excluded by default so login, logout, registration, password reset, email verification, password confirmation, and Sanctum's SPA CSRF cookie endpoint keep their normal behavior:

```
'except_routes' => [
    'login',
    'logout',
    'register',
    'password.*',
    'verification.*',
    'sanctum.csrf-cookie',
],
```

Add your own routes when they should keep returning a real `403`

### JSON Responses

[](#json-responses)

JSON requests receive the configured payload with a `404` status:

```
'api_response' => [
    'message' => 'Not Found',
],
```

Example response:

```
{
    "message": "Not Found"
}
```

### Guard Matching

[](#guard-matching)

By default, all guards are eligible. To convert only when a specific guard is authenticated:

```
'guards' => [
    'admin',
],
```

When `guards` is empty, no guard check is required.

### Logging

[](#logging)

To log every hidden forbidden response:

```
'log_original_403' => true,
```

The log entry includes the route name and path, while the client still receives a `404`.

What Gets Converted
-------------------

[](#what-gets-converted)

By default, the package converts:

- `Illuminate\Auth\Access\AuthorizationException`
- `Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException`
- Any Symfony HTTP exception with status code `403`
- Route middleware responses that already rendered as `403`

Non-forbidden server errors are not converted.

Testing
-------

[](#testing)

```
composer test
```

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance90

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

47d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/42376711?v=4)[Oleksandr Kramarenko](/maintainers/alexkramse)[@alexkramse](https://github.com/alexkramse)

---

Top Contributors

[![alexkramse](https://avatars.githubusercontent.com/u/42376711?v=4)](https://github.com/alexkramse "alexkramse (9 commits)")

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/alexkramse-laravel-hide-forbidden/health.svg)

```
[![Health](https://phpackages.com/badges/alexkramse-laravel-hide-forbidden/health.svg)](https://phpackages.com/packages/alexkramse-laravel-hide-forbidden)
```

###  Alternatives

[statamic-rad-pack/runway

Eloquently manage your database models in Statamic.

137236.2k8](/packages/statamic-rad-pack-runway)[duncanmcclean/statamic-cargo

Comprehensive e-commerce addon for Statamic. Build bespoke e-commerce sites without the complexity.

3622.8k](/packages/duncanmcclean-statamic-cargo)[api-platform/laravel

API Platform support for Laravel

58190.1k21](/packages/api-platform-laravel)[ecotone/laravel

Ecotone for Laravel — CQRS, Event Sourcing, Sagas, Durable Workflows, and Outbox on top of Laravel Queue, via PHP attributes.

21327.3k4](/packages/ecotone-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
