import flatted from 'flatted'; import type { IWorkflowBase } from 'n8n-workflow'; import { nanoid } from 'nanoid'; import { workflow, trigger, node } from '../../../../../@n8n/workflow-sdk/src'; import { N8N_AUTH_COOKIE } from '../../../config/constants'; import { test, expect } from '../../../fixtures/base'; const TRIGGER_NAME = 'Manual Trigger'; const CODE_NODE_NAME = 'HTML Binary Producer'; /** * Creates a workflow with a Code node that produces HTML binary data * WITHOUT a fileName (the XSS attack vector from ADO-4922). * * The HTML contains a script that sets document.title to a known marker. * If the browser renders the HTML inline and executes the script, * the title change proves same-origin JavaScript execution. */ function createHtmlBinaryWorkflow(): IWorkflowBase { const manualTrigger = trigger({ type: 'n8n-nodes-base.manualTrigger', version: 1, config: { name: TRIGGER_NAME, parameters: {}, }, }); const codeNode = node({ type: 'n8n-nodes-base.code', version: 1, config: { name: CODE_NODE_NAME, parameters: { mode: 'runOnceForAllItems', // The script sets document.title to a marker we can detect. // Passing undefined as filePath means no fileName in metadata, // which causes the server to skip Content-Disposition: attachment. jsCode: ` const html = '