Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Secureheaders Laravel Package

aidantwoods/secureheaders

SecureHeaders is a PHP library for adding security headers to HTTP responses. It helps configure CSP, HSTS, X-Frame-Options, Referrer-Policy, and related headers with sensible defaults and a fluent API, making it easier to harden web apps against common browser-side attacks.

Deep Wiki
Context7

Getting Started

Install via Composer and verify the resolved version meets your PHP constraint (this package predates PHP 8, so test on your runtime before committing):

composer require aidantwoods/secureheaders

Look first at the README quickstart and the examples/ directory — the library exposes two entry points: a "just send headers" procedural flow and a PSR-7 flow. For a legacy or front-controller app, the minimal first use case is three lines at the very top of public/index.php, before any output:

use Aidantwoods\SecureHeaders\SecureHeaders;

$headers = new SecureHeaders();
$headers->errorReporting(true);   // dev only — surfaces invalid/conflicting config
$headers->strictMode();           // opinionated defaults: CSP, HSTS, nosniff, frame options, referrer policy
$headers->apply();                // compute final header set
$headers->output();               // emit via header()

If you're on PSR-7 (Slim, Laminas, Laravel via a bridge), skip output() and hand the library a response instead:

$response = $headers->applyTo($response); // returns the response with headers applied

The core objects you'll touch day-to-day are SecureHeaders (policy builder), Header (immutable name/value pair), and — for framework work — whatever PSR-7 ResponseInterface you already produce. Inspect what the library decided before sending with $headers->getHeaders(), which returns an array of Header objects; this is the single best debugging affordance in the package.

Implementation Patterns

Framework middleware. In Laravel, wrap the library in a global or web-group middleware so every response is covered:

public function handle($request, Closure $next)
{
    $response = $next($request);

    $headers = new SecureHeaders();
    $headers->errorReporting(app()->environment(['local', 'testing']));
    $headers->strictMode();
    $headers->addHeader('Permissions-Policy', 'geolocation=(), camera=(), microphone=()');

    return $headers->applyTo($response);
}

Because PSR-7 responses are immutable, always reassign the return value — do not rely on in-place mutation.

Layered policies. Start from strictMode() for the global baseline, then add or remove specific directives per route group. Admin panels, API routes, and public marketing pages rarely want the same CSP. Keep a small helper that clones the base config and applies overrides so you don't re‑implement the defaults per controller.

Custom CSP with nonces. strictMode() will block inline scripts and styles, which is the correct posture but will break most existing templates. Migrate by generating a per-request nonce, adding it to the script-src/style-src directives via addHeader(), and threading the same value into the rendered <script nonce="..."> tags. This requires the nonce to be generated before the header is finalized and before the body is rendered — usually meaning the middleware seeds a request attribute that the view layer reads. Pages using nonces must not be full-page cached without varying on them.

Report-only rollout. For staging, add Content-Security-Policy-Report-Only with a report-uri/report-to directive alongside (or instead of) the enforcing header. This lets you discover the inline scripts and third-party origins you missed before users do, and it's the cheapest way to tune a policy on a mature app.

Testing. In PHPUnit, assert against getHeaders() rather than header() (which is a no-op under CLI). A one-line helper that maps Header objects to name: value strings makes snapshot assertions trivial and catches accidental directive regressions when someone edits the global config.

Cookie handling. Where the package rewrites Set-Cookie to add SameSite, it can only see headers that exist at the time it runs. Set all cookies before the middleware applies, or set the attribute manually with setcookie() options — mixing the two is a common source of inconsistency.

Gotchas and Tips

  • Maintenance status is the headline risk. The last tagged release is 2017, so it predates COOP, COEP, Permissions-Policy, and the frame-ancestors/report-to modernizations. It still works, but treat it as a stable-but-frozen dependency: pin the version, don't expect fixes for new browsers, and plan to add newer headers yourself via addHeader(). Audit against PHP 8.x and PSR-7 v1 vs v2 before upgrading your stack.
  • apply() then output() is not optional. Calling output() without apply() (or the reverse in the wrong order) ships an empty or stale header set. If headers suddenly vanish, this ordering is the first thing to check.
  • Output buffering. output() calls PHP's header(), which silently fails once the body has started. In legacy apps, ensure ob_start() is active or that the middleware runs early enough. The same applies to whitespace or a UTF‑8 BOM in an included file — the classic "headers already sent" trap.
  • errorReporting(true) throws/warns in production. Wire it to environment detection only; leave it off in prod so a bad directive logs rather than a 500.
  • Strict mode will break your pages on day one. Expect a CSP debugging session: load the site, watch the browser console, and iterate. Deploy report-only first if you can't afford the outage window.
  • HSTS is sticky. Never emit Strict-Transport-Security for a host you serve over plain HTTP in development — browsers will pin https://localhost and refuse to let you back in. Gate it on environment, not just on strictMode().
  • Duplicated headers. If the middleware runs twice (nested groups, queued jobs hitting HTTP views, or a manual call plus the middleware), you'll get stacked Content-Security-Policy values that combine into something stricter than intended. Use forceHeader()/removeHeader() deliberately when overriding a value set elsewhere.
  • CSP and X-Frame-Options can disagree. Modern browsers prefer frame-ancestors; keep the two consistent or you'll get confusing embedding behavior that varies by browser.
  • Extension point for the gaps. addHeader, removeHeader, and forceHeader are the intended escape hatches for anything the library doesn't model natively — that's where COOP, COEP, Cross-Origin-Resource-Policy, and Permissions-Policy belong. Wrap them in your own config so they travel with the library's output and get tested together.
  • Verify outside the app. curl -I https://staging.example.com is the ground truth; framework middleware ordering, proxy header rewriting, and CDN overrides can all undo what the library computed, and none of that shows up in getHeaders().
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle