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

Referrer Spam Blacklist Laravel Package

piwik/referrer-spam-blacklist

A Composer package providing a regularly updated list of referrer spam domains in plain text, plus a small PHP builder that converts it to JSON. Use it to filter fake traffic in analytics, block spam referrers, or feed your own blacklist.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • The package is a data artifact, not a library. It ships a flat, newline-delimited text file of spam referrer hostnames (currently ~10k+ entries, low single-digit MB unzipped) and nothing else: no service provider, no facade, no config, no contracts, no runtime classes worth binding. In a Laravel app it must be treated as a vendored asset, not a framework dependency.
  • This inverts the usual effort profile. The "adopt the package" decision is near-zero cost and near-zero lock-in; the "build a middleware + cache warmup + override list + observability" decision is the actual product decision. Budget 1–2 engineering days for a production-grade wrapper, not the 15 minutes implied by composer require.
  • Good fit for two distinct use cases, which should be scoped separately because their blast radius differs enormously:
    • Analytics hygiene — sanitize/filter the recorded referrer or drop the hit from reporting. Low risk, reversible, no user-visible failure mode.
    • Request-path enforcement — return 404/403 at middleware for matching referrers. High risk (users see it), low durability (trivially evaded).
  • Poor fit for anything requiring adaptive scoring, rate limiting, device fingerprinting, or coordinated-attack defense. The opportunity score of 2.4 is consistent with this: it is a commodity deny-list with thin differentiation. The value is in the curation labor, not the code or the schema.

Integration feasibility

  • Mechanically straightforward on Laravel 9–12 / PHP 8.x / Composer 2. Path is vendor/piwik/referrer-spam-blacklist/referrer-spam-blacklist.txt. Read once, normalize (lowercase, strip port, strip www., handle IDN/punycode), array_flip() into a hash set, then O(1) lookup against parse_url($request->headers->get('referer'), PHP_URL_HOST).
  • Do not parse the file per request. Naive integration is the most likely way this becomes a latency or CPU incident. Load into Laravel's cache (Redis or a compiled PHP array artifact) and warm at deploy time via an Artisan command hooked into the release process.
  • No Laravel package auto-discovery means no accidental global registration — an advantage here, since enforcement must be opt-in per route group.
  • Octane/Swoole compatibility is fine but requires discipline: long-lived workers will hold a stale in-memory set across deploys. Cache must be versioned/invalidated, not just memoized in a static.

Technical risk

  • The security control is weak by construction. The Referer header is attacker-controlled and frequently absent (privacy browsers, Referrer-Policy: no-referrer, stripped cross-origin requests, corporate proxies). Any actor who reads the list can omit or spoof past it. This package catches lazy, opportunistic, off-the-shelf bots — it does not stop a motivated actor, and it must never be positioned internally as "we solved form spam."
  • False-positive exposure is asymmetric. A single bad hostname in a patch release, hard-enforced on the request path, silently breaks a real customer, a partner referral flow, or a paid campaign landing page — and you will hear about it from sales, not from monitoring. Mitigation: ship with log-only/shadow mode first, an application-level allow-list that always wins, and a per-decision log line.
  • Opaque provenance and no SLA. The 4.0.5 release note is literally "Added more spammers to the list." There is no review gate you can inspect before behavior changes, no changelog of which domains were added, and no contractual freshness commitment. You are accepting a vendor-curated black box in exchange for not owning curation.
  • Supply-chain coupling to a routine command. Because content ships in patch releases, a routine composer update silently changes production filtering behavior. That is a governance gap most teams do not have a control for.

Key questions

  1. Is the goal analytics hygiene or user-facing blocking? These are different projects with different risk owners, and conflating them is the most common way this goes wrong.
  2. Do we run Matomo anywhere? If so, the built-in referrer filter already consumes this list and the custom Laravel work may be duplicative.
  3. What is our Referrer-Policy and do we rely on referrer data anywhere legitimate (attribution, partner settlement, affiliate tracking)?
  4. Who reviews list diffs on version bumps, and is that review on a cadence or ad hoc?
  5. What is the fallback if upstream goes dark — repo archived, maintainer steps away, releases stop? Can we fork and self-publish, and have we estimated the curation cost we'd inherit?
  6. Do we have an allow-list/override mechanism and a named owner for false-positive appeals?
  7. Are we instrumenting block decisions (what, why, correlation ID) well enough to answer "did we block a real user" within an hour?

Integration Approach

Stack fit

  • Natural placement is a route-group middleware applied to unauthenticated surfaces only: guest comment/contact forms, open registration, public review and lead-gen submissions. It should not be global middleware — the risk/benefit is wrong for authenticated app traffic.
  • Prefer attribution sanitization over request rejection as the default posture: normalize the referrer, and if the host is on the list, either null the attribution and record a spam_referrer flag on the entity, or reject with a cheap 404. Storing a flag rather than dropping the record preserves the ability to audit and to reverse a bad decision.
  • Supporting components to build (all ours, none supplied by the package):
    • A config file (config/spam-referrer.php) with enabled, mode (log|flag|block), allow_list, and cache TTL.
    • A singleton resolver that reads from cache, not from the vendor file.
    • An Artisan command (spam:referrers:compile) producing a versioned cache key, run as a deploy step.
    • A thin service class wrapping the lookup so it is unit-testable without HTTP.
  • Test strategy: fixture list files (including malformed lines, trailing whitespace, mixed case, IDN entries, entries with paths) plus feature tests asserting log/flag/block modes and allow-list precedence.

Migration path

  • Effectively greenfield — there is no existing state to migrate and no schema change. The only "migration" is behavioral: moving from no filtering to filtering, which should be done in log-only mode for at least one full traffic cycle before enforcement.
  • If Matomo's built-in filter is already in play, decide explicitly whether the Laravel app duplicates it. Duplication is acceptable (different consumers) but should be a stated decision, not drift.

Compatibility

  • Laravel 9–12 and PHP 8.x: no blockers. Composer 2 required by the 4.x line. No framework-version coupling, which is genuinely why the risk here is low.
  • Watch items: Octane long-lived workers (stale set across deploys), read-only container filesystems (cache must be Redis/file-cache, not vendor-relative writes), and CI environments where vendor/ is pruned before deploy (compile the cache artifact before the prune step).

Sequencing

  1. Instrument (shadow mode). Ship the middleware in log mode, no enforcement. Success criterion: we can state spam-referrer hit rate per endpoint and confirm zero legitimate traffic matches.
  2. Protect analytics and attribution. Null the attribution, set the flag. No user-visible change, no way to hurt a real user.
  3. Enforce on the narrowest high-value surface. One or two form endpoints, allow-list live, alerting on 403 rate deltas. Success criterion: no measurable drop in legitimate conversions.
  4. Decide explicitly not to widen. Record the rationale that broader enforcement is a WAF/bot-management purchase, and revisit only if abuse volume or sophistication changes.

Each step should be independently revertible via a config flag. Do not ship 1–3 in one PR.

Operational Impact

Maintenance

  • Low and mostly bounded: the package's own cadence is routine patch releases (~quarterly content refreshes). Your maintenance burden is the wrapper you wrote, plus a review ritual on version bumps.
  • The one non-negotiable ritual: pin the version and review the diff before bumping. Because behavior changes ride in on patch releases, an unreviewed composer update is an unreviewed production filtering change. This is cheap (a line count and a sample of new hosts) and is the entire governance control.
  • Ownership should be named and singular — most likely the team that owns the public forms — with a documented escalation path for false-positive reports. A blocklist with no owner becomes a silent, growing filter nobody can justify.

Support

  • No commercial support, no SLA, no vendor to escalate to. Effectively community-maintained. Acceptable for a deny-list on a low-blast-radius surface; unacceptable if the control ever becomes load-bearing for revenue or compliance.
  • Support burden shifts entirely internal: false-positive tickets, "why was my submission blocked" inquiries, and partner complaints. Each needs a lookup tool and an allow-list change process, or the blocklist becomes an unaccountable rejection mechanism. This is the single most underestimated cost.
  • If the package is used anywhere customer-facing, the allow-list override must be changeable without a deploy.

Scaling

  • Lookup cost is negligible if cached: a hash-set probe against ~10k strings is microseconds. The failure mode is scale-by-omission — the per-request file_get_contents + parse variant costs disk/network I/O and milliseconds on every request, multiplied across the fleet.
  • Cache invalidation across an autoscaled fleet is the real scaling concern. Version the cache key off the package version, warm it during release, and let old keys expire. Do not rely on a TTL alone, or workers will disagree about the list for the TTL window — which produces intermittent, unattributable blocking behavior.
  • List growth is linear and unbounded but harmless: even 10x current size compiles to a few MB of resident set. Not a scaling risk.

Failure modes

Failure Likelihood Impact Mitigation
Cache cold/missing in a new pod Medium Per-request file parse, latency spike Fail-open to "no match"; warm at deploy; alert on cold-cache reads
Bad hostname added upstream, hard-enforced Medium Real user/partner blocked Log-only rollout, allow-list wins, per-decision logs
Upstream repo archived / releases stop Low–Medium List goes stale, silent decay Fork + self-publish fallback; monitor last-release age
Malformed/oversized list line breaks parser Low Missed matches or parse error Defensive parsing, fixture tests, skip-on-error
Long-lived Octane worker holds stale set Medium Inconsistent decisions across workers Versioned cache key, not static memoization
Team treats this as complete anti-spam High Underinvestment, abuse escalation Explicit "baseline, not strategy" statement in the design doc

The most probable real-world failure is not technical — it is organizational: the blocklist gets adopted, works well enough against junk traffic, and quietly becomes the only abuse control, deferring a WAF/bot-management decision until abuse volume has already cost something. Name the escalation trigger up front (e.g., spam submissions exceed N/week or show adaptation) so the deferral is a tracked decision rather than a default.

Ramp-up

  • Engineering: ~1–2 days to a tested wrapper with cache warmup, config, and allow-list; familiarity with the package itself is minutes.
  • Product/ops: ~half a day to define the allow-list process, the false-positive appeal path, and the escalation trigger.
  • Stakeholder alignment: the important conversation is not "should we install this" but "what are we explicitly not doing by installing this." One paragraph in the design doc prevents a year of misaligned expectations.
  • Total time-to-value in shadow mode: under a week. Time-to-safe-enforcement: one full traffic cycle (~2–4 weeks) to build confidence in the false-positive rate.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log