Date 2026-06-20. Target: Flowise v3.1.2 (huntr AI/ML lane). Outcome: REFUTED an XSS candidate at the live-PoC gate before any submission.
A fleet agent + my static read flagged unauth stored XSS via Flowise /api/v1/attachments (upload html) + /api/v1/get-upload-file (serve). The serve controller:
if (download) res.setHeader('Content-Disposition', contentDisposition(fileName, { type: 'attachment' }))
else res.setHeader('Content-Disposition', contentDisposition(fileName)) // <-- claimed "inline"
The agent read the else branch as serving INLINE (sniffable -> XSS). Live test on v3.1.2 showed BOTH branches return Content-Disposition: attachment. The content-disposition npm package defaults type to 'attachment' when not passed. So the file always DOWNLOADS, never renders -> no XSS, regardless of the (genuinely) missing Content-Type / nosniff.
contentDisposition(name) (the npm content-disposition lib) defaults to attachment, NOT inline. Do not read a bare contentDisposition(fileName) as an inline/sniffable serve. Same for many frameworks' file helpers that default to attachment. A stored-XSS-via-upload claim REQUIRES the serve path to actually render inline - verify the ACTUAL emitted Content-Disposition header, never infer it from a helper call.The upload-validator IS consistency-only (no magic bytes) and html/svg ARE allowlisted - so the upload half held. The finding died entirely at the serve header. If a future Flowise version (or a different app) serves uploaded files inline with no nosniff, the chain would be live - this remains a real pattern to check elsewhere, just not exploitable in Flowise where the serve forces attachment.