v4.16.0 adds taint-analysis support for the laravel/ai package: prompt-injection detection plus tracking of LLM output into SQL, shell, and HTML sinks. It also extends MissingView to every view-name-bearing API and ships several new type-narrowing features.
🛡️ laravel/ai support (prompt injection and LLM-output taint)
The plugin now understands laravel/ai (>=0.11.0 <1.0.0, #937). The integration loads only when Composer reports the package installed; apps without it get no extra stubs or handlers. TaintedLlmPrompt is enabled automatically at its normal error level; <findPromptInjection value="false" /> turns off prompt-input findings while keeping model-output findings.
Untrusted data (request input, HTTP responses, tool arguments, retrieved documents) reaching an LLM prompt is reported:
final class SupportAgent
{
use \Laravel\Ai\Promptable;
}
(new SupportAgent())->prompt($request->input('question'));
// 🔴 TaintedLlmPrompt: Detected tainted LLM promptLLM output is treated as a taint source, so it is followed into the existing SQL, shell, file, and HTML sinks:
function run(\Laravel\Ai\Responses\AgentResponse $response): void {
DB::select($response->text);
}
// 🔴 TaintedSql: raw model output interpolated into a queryFeatures
- Extend
MissingViewbeyondview()andFactory::make()toFactory::first()/renderWhen()/renderEach(),response()->view(),Route::view(),MailMessage::view()/markdown(), andassertViewIs()(#1407)Route::view('/welcome', 'welcom'); // 🔴 MissingView: View 'welcom' not found in any of the registered view paths
- Infer
Arr::get()value type from known array shapes, including dot-notation keys and$defaulthandling (#1402)/** @param array{a: int} $data */ $value = Arr::get($data, 'a'); -// before: mixed +// now: int - Narrow userland
Manager::driver()to itscreate*Driver()return type, including the no-argument default-driver form (#1410)final class ShippingManager extends Manager { public function getDefaultDriver(): string { return 'ups'; } public function createUpsDriver(): Shipper { return new UpsShipper(); } } $manager->driver('ups'); // Shipper -$manager->driver(); // was: mixed +$manager->driver(); // now: Shipper - Narrow paginator
getCollection()to a model's custom Eloquent collection (#1408)#[CollectedBy(WorkOrderCollection::class)] class WorkOrder extends Model {} WorkOrder::query()->paginate()->getCollection(); -// before: Eloquent\Collection<int, WorkOrder> +// now: WorkOrderCollection<int, WorkOrder>
Fixes
- 🛡️ Stop reporting
TaintedHtmlforresponse()->make()bodies explicitly served as attachments (#1348)response()->make($csv, 200, ['Content-Disposition' => 'attachment; filename="export.csv"']); -// before: TaintedHtml +// now: no issue — the response is a download, not rendered HTML
- 🛡️ Extend that attachment exemption to variable-held header arrays, interpolated filenames,
new Illuminate\Http\Response(...), and safe literalContent-Typevalues; HTML, XML, SVG, and script types stay reported (#1417) - Infer Sanctum's default
PersonalAccessTokenbinding for models usingHasApiTokenswithout an explicit@useannotation, fixing spuriousMissingTemplateParam(#1425) - Resolve
HasFactorybindings fromnewFactory(), static$factory, and#[UseFactory]without suppressing unrelatedMissingTemplateParamdiagnostics on the model (#1423) - Track Laravel's indirect method references (container-resolved controller actions, command
handle()methods, Eloquent relations) so--find-unused-codestops flagging them as dead (#1422)
Full Changelog: v4.15.7...v4.16.0