willdurand/jsonp-callback-validator
Validate JSONP callback names to prevent XSS. JsonpCallbackValidator checks whether a callback like JSONP.callback is safe and rejects malicious function payloads. Use via instance or static validate(), installable via Composer.
Installation:
composer require willdurand/jsonp-callback-validator
Add to composer.json if using Laravel's autoloader (though not required for standalone usage).
First Use Case: Validate JSONP callbacks in API endpoints or middleware to prevent XSS attacks.
use JsonpCallbackValidator;
// In a controller or service
$callback = request()->input('callback'); // e.g., "JSONP.callback"
$isValid = JsonpCallbackValidator::validate($callback);
Where to Look First:
Middleware Integration: Validate callbacks in middleware to sanitize incoming JSONP requests globally.
namespace App\Http\Middleware;
use Closure;
use JsonpCallbackValidator;
class ValidateJsonpCallback
{
public function handle($request, Closure $next)
{
$callback = $request->input('callback');
if ($callback && !JsonpCallbackValidator::validate($callback)) {
abort(400, 'Invalid JSONP callback');
}
return $next($request);
}
}
Register in app/Http/Kernel.php:
protected $middleware = [
\App\Http\Middleware\ValidateJsonpCallback::class,
];
API Response Wrapper: Dynamically wrap responses in JSONP format if a valid callback is provided.
namespace App\Services;
use JsonpCallbackValidator;
class JsonpResponseService
{
public function wrap($data, $callback = null)
{
if ($callback && JsonpCallbackValidator::validate($callback)) {
return "$callback($data)";
}
return $data;
}
}
Form Request Validation:
Extend Laravel's FormRequest to validate JSONP callbacks.
namespace App\Http\Requests;
use JsonpCallbackValidator;
use Illuminate\Foundation\Http\FormRequest;
class JsonpRequest extends FormRequest
{
public function rules()
{
return [
'callback' => 'nullable|string',
];
}
public function passedValidation()
{
if ($this->callback && !JsonpCallbackValidator::validate($this->callback)) {
$this->fail('Invalid JSONP callback');
}
return parent::passedValidation();
}
}
JSONP Endpoint Handling:
callback parameter in API routes.Legacy System Integration:
JsonpController.Testing:
$validator = $this->createMock(JsonpCallbackValidator::class);
$validator->method('validate')->willReturn(true);
Laravel Service Providers: Bind the validator to the container for dependency injection:
$this->app->singleton(JsonpCallbackValidator::class);
Then inject it into controllers/services:
use JsonpCallbackValidator;
public function __construct(private JsonpCallbackValidator $validator) {}
Custom Validation Rules: Create a reusable validation rule:
namespace App\Rules;
use JsonpCallbackValidator;
use Illuminate\Contracts\Validation\Rule;
class ValidJsonpCallback implements Rule
{
public function passes($attribute, $value)
{
return JsonpCallbackValidator::validate($value);
}
public function message()
{
return 'The :attribute must be a valid JSONP callback.';
}
}
Use in FormRequest or manually:
$request->validate(['callback' => ['nullable', new ValidJsonpCallback]]);
False Positives/Negatives:
my.callback.with.dots).$whitelist = ['JSONP.callback', 'myApp.callback'];
$isValid = in_array($callback, $whitelist, true);
Performance:
PHP 8.x Compatibility:
Edge Cases:
null values may not be handled explicitly. Add checks:if (empty($callback)) {
return true; // or false, depending on requirements
}
Invalid Callback Rejections:
(function xss(x){evil()}).Regex Debugging:
Logging:
if (!$validator->validate($callback)) {
\Log::warning("Invalid JSONP callback: $callback");
}
Custom Validation Logic: Extend the validator class to add rules:
namespace App\Services;
use JsonpCallbackValidator as BaseValidator;
class CustomJsonpValidator extends BaseValidator
{
protected function getRegex()
{
return '/^([a-zA-Z_$][a-zA-Z0-9_$]*)(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/';
}
}
Whitelist Integration: Combine with a whitelist for stricter control:
class WhitelistedJsonpValidator
{
private $whitelist;
public function __construct(array $whitelist)
{
$this->whitelist = $whitelist;
}
public function validate($callback)
{
return in_array($callback, $this->whitelist, true) ||
JsonpCallbackValidator::validate($callback);
}
}
Event-Based Validation: Trigger events when callbacks are validated/rejected:
event(new JsonpCallbackValidated($callback));
event(new JsonpCallbackRejected($callback));
How can I help you explore Laravel packages today?