blaspsoft/blasp
Advanced profanity filtering for Laravel with driver-based detection (regex/pattern/phonetic/pipeline), multi-language support, severity scoring (0–100), masking strategies, validation rules, middleware, Eloquent model integration, events, and test fakes.
\p{Cf} format characters (zero-width spaces, invisible separators) from input before processing, so profanity like fuck (with U+2063) is correctly detected* as a universal letter substitution so censored profanity like f*g, s**t, f**k is detected\x01 instead of * for internal masking during detection loop to prevent re-matching masked textpreg_replace returning null on malformed UTF-8 inputA ground-up rewrite with a driver-based architecture, severity scoring, and deep Laravel integration.
regex (obfuscation/substitution detection), pattern (fast exact matching), phonetic (sound-alike evasion via metaphone + Levenshtein), and pipeline (chain multiple drivers together). Extend with custom drivers.*, #), grawlix (!@#$%), or a custom callback.Blaspable trait auto-sanitizes or rejects profanity on model save, with withoutBlaspChecking() for bypassing.CheckProfanity middleware to reject or sanitize profane request fields with configurable severity and field filtering.blasp_check rule with language support.[@clean](https://github.com/clean)($text) for output sanitization.Str::isProfane(), Str::cleanProfanity(), and Stringable equivalents.ProfanityDetected, ContentBlocked, ModelProfanityDetected.Blasp::fake() for test doubles with assertions.Blaspsoft\Blasp\Laravel\ merged into Blaspsoft\Blasp\. Update any direct class references.ServiceProvider → BlaspServiceProvider (auto-discovery handles this).config/config.php → config/blasp.php. Re-publish with php artisan vendor:publish --tag="blasp-config".check() now returns a Result object with isOffensive(), clean(), score(), severity(), count(), words(), uniqueWords(). Previous methods like hasProfanity(), getCleanString(), getProfanitiesCount() are removed.space, spacious, aerospace, workspace were incorrectly flagged because the profanity spac matched as a substring. Instead of adding more words to the false positives list, a systematic check now automatically skips pure alphabetic profanity matches embedded inside larger regular words.spac, fuck, ass)sp@c, f-u-c-k, a$$)fucks, fucker, fuckings)cuntfuck, fuckingshitcuntfuck)ccuunntt, fuuuck)space, spacious, aerospace, cocktails, class, etc.)Closes #32
"an alert" no longer flags "anal""has 5 faces" no longer flags "ass"The fix distinguishes between intentional obfuscation (like "[@ss](https://github.com/ss)" which contains letters + special characters) and accidental word combinations (like "an al" which contains only letters).
isSpanningWordBoundary() logic to check if standalone portions contain both letters AND non-letter charactersfix: detect partial spacing profanity obfuscation - Profanity obfuscation using partial spacing is now correctly detected:
"s hit" → detected as "shit""f uck" → detected as "fuck""t wat" → detected as "twat""fu c k" → detected as "fuck""tw a t" → detected as "twat"fix: convert byte offset to character offset for multibyte support - Fixed boundary checks to work correctly with multibyte characters (accented letters in French, German, etc.)
The isSpanningWordBoundary() method was refactored to check surrounding context instead of relying on heuristics about single-character parts. This ensures partial spacing obfuscation is detected while still preventing false positives like "This musicals hit".
Full Changelog: https://github.com/Blaspsoft/blasp/compare/v3.1.6...v3.1.7
/u (PCRE_UTF8) flag to generated profanity regex patterns, preventing multi-byte UTF-8 characters (e.g. ê, é) from being matched byte-by-byte and causing false positives on words like "tête" and "aré".check() entry point to sanitize non-UTF-8 strings before regex matching, preventing silent preg_match failures.Blasp::check() now accepts ?string and returns a clean result for empty or null input instead of throwing an exception.false_positives list covering substrings: ass, tit, cum, nig, rap, nob.6ec3e80f-...-144a2ef5800b were incorrectly flagged because 800b mapped to boob via character substitutions. Added an isInsideHexToken() guard that skips matches inside UUIDs, MD5/SHA hashes, and other long hex strings while leaving normal profanity detection intact.preg_replace with a single-pass character walker that prevents circular substitutions (e.g., French c→k and k→c) from producing malformed regex. Multi-char substitution values now use alternation instead of character classes. Language-specific substitutions are properly merged again.f u c k i n g is now correctly detected as profanityThe isSpanningWordBoundary() method was incorrectly rejecting intentional obfuscation where characters are separated by spaces. The fix distinguishes between:
$result = Blasp::check('This is f u c k 1 n g awesome!');
$result->hasProfanity; // true ✅
Full Changelog: https://github.com/Blaspsoft/blasp/compare/v3.1.0...v3.1.1
You can now specify a custom cache driver for Blasp, which is particularly useful for environments like Laravel Vapor where the default cache driver (DynamoDB) has size limits that can be exceeded when caching profanity expressions.
Set via config:
// config/blasp.php
'cache_driver' => env('BLASP_CACHE_DRIVER'),
Or via environment variable:
BLASP_CACHE_DRIVER=redis
This feature was originally proposed by @dimzeta in #25 and has been adapted for Blasp v3.0 architecture.
Full Changelog: https://github.com/Blaspsoft/blasp/compare/v3.0.0...v3.1.0
Blasp v3.0.0 introduces comprehensive multi-language support and a completely refactored architecture for improved performance and extensibility.
maskWith() method for customizable censoring characterscomposer require blaspsoft/blasp
use Blasp\Facades\Blasp;
// English (default)
$hasProfanity = Blasp::check('some text');
$cleanText = Blasp::clean('some text');
// Multi-language support
$hasProfanity = Blasp::language('spanish')->check('texto aquí');
$cleanText = Blasp::language('french')->clean('texte ici');
// Custom mask characters
$masked = Blasp::maskWith('❌')->clean('bad words here');
This is a major release with breaking changes from v2.x:
Please review the documentation for migration details.
configure method in BlaspService class by removing unnecessary null parameterModified src/BlaspService.php:
BlaspService configurationThis update is fully backwards compatible with v2.0.0. No changes are required in existing implementations.
configure() method for custom profanity and false positive listsphp artisan blasp:clear command to clear cacheYou can now specify custom profanity and false positive lists which override the default config:
$blasp = Blasp::configure(
profanities: $your_custom_list ,
falsePositives: $your_custom_false_positives
)->check($text);
The configuration file now supports:
If you're upgrading from v1.x, you'll need to:
configure() method for custom listsThis patch release focuses on resolving bugs and improving regex handling for better profanity detection accuracy.
a$$) were not correctly masked due to special character handling in regex.afuckb).v1.2.x.How can I help you explore Laravel packages today?