@vulcn/engine 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +227 -0
- package/dist/index.cjs +724 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +546 -0
- package/dist/index.d.ts +546 -0
- package/dist/index.js +683 -0
- package/dist/index.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../session.ts","../browser.ts","../recorder.ts","../payloads.ts","../runner.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { parse, stringify } from \"yaml\";\n\n// Step types\nexport const StepSchema = z.discriminatedUnion(\"type\", [\n z.object({\n id: z.string(),\n type: z.literal(\"navigate\"),\n url: z.string(),\n timestamp: z.number(),\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"click\"),\n selector: z.string(),\n position: z.object({ x: z.number(), y: z.number() }).optional(),\n timestamp: z.number(),\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"input\"),\n selector: z.string(),\n value: z.string(),\n injectable: z.boolean().optional().default(true),\n timestamp: z.number(),\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"keypress\"),\n key: z.string(),\n modifiers: z.array(z.string()).optional(),\n timestamp: z.number(),\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"scroll\"),\n selector: z.string().optional(),\n position: z.object({ x: z.number(), y: z.number() }),\n timestamp: z.number(),\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"wait\"),\n duration: z.number(),\n timestamp: z.number(),\n }),\n]);\n\nexport type Step = z.infer<typeof StepSchema>;\n\n// Session schema\nexport const SessionSchema = z.object({\n version: z.string().default(\"1\"),\n name: z.string(),\n recordedAt: z.string(),\n browser: z.enum([\"chromium\", \"firefox\", \"webkit\"]).default(\"chromium\"),\n viewport: z.object({\n width: z.number(),\n height: z.number(),\n }),\n startUrl: z.string(),\n steps: z.array(StepSchema),\n});\n\nexport type Session = z.infer<typeof SessionSchema>;\n\n/**\n * Create a new session object\n */\nexport function createSession(options: {\n name: string;\n startUrl: string;\n browser?: \"chromium\" | \"firefox\" | \"webkit\";\n viewport?: { width: number; height: number };\n}): Session {\n return {\n version: \"1\",\n name: options.name,\n recordedAt: new Date().toISOString(),\n browser: options.browser ?? \"chromium\",\n viewport: options.viewport ?? { width: 1280, height: 720 },\n startUrl: options.startUrl,\n steps: [],\n };\n}\n\n/**\n * Parse a session from YAML string\n */\nexport function parseSession(yaml: string): Session {\n const data = parse(yaml);\n return SessionSchema.parse(data);\n}\n\n/**\n * Serialize a session to YAML string\n */\nexport function serializeSession(session: Session): string {\n return stringify(session, { lineWidth: 0 });\n}\n","import { chromium, firefox, webkit, type Browser } from \"playwright\";\nimport { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { BrowserType } from \"./types\";\n\nconst execAsync = promisify(exec);\n\nexport interface LaunchOptions {\n browser?: BrowserType;\n headless?: boolean;\n}\n\nexport interface BrowserLaunchResult {\n browser: Browser;\n channel?: string;\n}\n\nexport class BrowserNotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BrowserNotFoundError\";\n }\n}\n\n/**\n * Launch a browser with smart fallback:\n * 1. Try system Chrome/Edge first (zero-install experience)\n * 2. Fall back to Playwright's bundled browsers\n */\nexport async function launchBrowser(\n options: LaunchOptions = {},\n): Promise<BrowserLaunchResult> {\n const browserType = options.browser ?? \"chromium\";\n const headless = options.headless ?? false;\n\n // For Chromium, try system browsers first\n if (browserType === \"chromium\") {\n // Try system Chrome\n try {\n const browser = await chromium.launch({\n channel: \"chrome\",\n headless,\n });\n return { browser, channel: \"chrome\" };\n } catch {\n // Chrome not available\n }\n\n // Try system Edge\n try {\n const browser = await chromium.launch({\n channel: \"msedge\",\n headless,\n });\n return { browser, channel: \"msedge\" };\n } catch {\n // Edge not available\n }\n\n // Fall back to Playwright's bundled Chromium\n try {\n const browser = await chromium.launch({ headless });\n return { browser, channel: \"chromium\" };\n } catch {\n throw new BrowserNotFoundError(\n \"No Chromium browser found. Install Chrome or run: vulcn install chromium\",\n );\n }\n }\n\n // Firefox\n if (browserType === \"firefox\") {\n try {\n const browser = await firefox.launch({ headless });\n return { browser, channel: \"firefox\" };\n } catch {\n throw new BrowserNotFoundError(\n \"Firefox not found. Run: vulcn install firefox\",\n );\n }\n }\n\n // WebKit\n if (browserType === \"webkit\") {\n try {\n const browser = await webkit.launch({ headless });\n return { browser, channel: \"webkit\" };\n } catch {\n throw new BrowserNotFoundError(\n \"WebKit not found. Run: vulcn install webkit\",\n );\n }\n }\n\n throw new BrowserNotFoundError(`Unknown browser type: ${browserType}`);\n}\n\n/**\n * Install Playwright browsers\n */\nexport async function installBrowsers(\n browsers: BrowserType[] = [\"chromium\"],\n): Promise<void> {\n const browserArg = browsers.join(\" \");\n await execAsync(`npx playwright install ${browserArg}`);\n}\n\n/**\n * Check which browsers are available\n */\nexport async function checkBrowsers(): Promise<{\n systemChrome: boolean;\n systemEdge: boolean;\n playwrightChromium: boolean;\n playwrightFirefox: boolean;\n playwrightWebkit: boolean;\n}> {\n const results = {\n systemChrome: false,\n systemEdge: false,\n playwrightChromium: false,\n playwrightFirefox: false,\n playwrightWebkit: false,\n };\n\n // Check system Chrome\n try {\n const browser = await chromium.launch({\n channel: \"chrome\",\n headless: true,\n });\n await browser.close();\n results.systemChrome = true;\n } catch {\n // Not available\n }\n\n // Check system Edge\n try {\n const browser = await chromium.launch({\n channel: \"msedge\",\n headless: true,\n });\n await browser.close();\n results.systemEdge = true;\n } catch {\n // Not available\n }\n\n // Check Playwright Chromium\n try {\n const browser = await chromium.launch({ headless: true });\n await browser.close();\n results.playwrightChromium = true;\n } catch {\n // Not installed\n }\n\n // Check Playwright Firefox\n try {\n const browser = await firefox.launch({ headless: true });\n await browser.close();\n results.playwrightFirefox = true;\n } catch {\n // Not installed\n }\n\n // Check Playwright WebKit\n try {\n const browser = await webkit.launch({ headless: true });\n await browser.close();\n results.playwrightWebkit = true;\n } catch {\n // Not installed\n }\n\n return results;\n}\n","import { Page } from \"playwright\";\nimport { createSession, type Session, type Step } from \"./session\";\nimport { launchBrowser } from \"./browser\";\nimport type { RecorderOptions } from \"./types\";\n\n/**\n * Active recording session handle\n */\nexport interface RecordingSession {\n /** Stop recording and return the session */\n stop(): Promise<Session>;\n /** Get current recorded steps */\n getSteps(): Step[];\n /** Get the Playwright page (for advanced use) */\n getPage(): Page;\n}\n\n/**\n * Recorder - captures browser interactions as a replayable session\n */\nexport class Recorder {\n /**\n * Start a new recording session\n * Opens a browser window for the user to interact with\n */\n static async start(\n startUrl: string,\n options: RecorderOptions = {},\n ): Promise<RecordingSession> {\n const browserType = options.browser ?? \"chromium\";\n const viewport = options.viewport ?? { width: 1280, height: 720 };\n const headless = options.headless ?? false;\n\n // Launch browser with smart fallback (system Chrome first)\n const { browser } = await launchBrowser({\n browser: browserType,\n headless,\n });\n const context = await browser.newContext({ viewport });\n const page = await context.newPage();\n\n // Navigate to start URL\n await page.goto(startUrl);\n\n // Create session\n const session = createSession({\n name: `Recording ${new Date().toISOString()}`,\n startUrl,\n browser: browserType,\n viewport,\n });\n\n // Track recording start time\n const startTime = Date.now();\n const steps: Step[] = [];\n let stepCounter = 0;\n\n const generateStepId = () => {\n stepCounter++;\n return `step_${String(stepCounter).padStart(3, \"0\")}`;\n };\n\n // Add initial navigation step\n steps.push({\n id: generateStepId(),\n type: \"navigate\",\n url: startUrl,\n timestamp: 0,\n });\n\n // Attach event listeners\n Recorder.attachListeners(page, steps, startTime, generateStepId);\n\n return {\n async stop() {\n session.steps = steps;\n await browser.close();\n return session;\n },\n getSteps() {\n return [...steps];\n },\n getPage() {\n return page;\n },\n };\n }\n\n private static attachListeners(\n page: Page,\n steps: Step[],\n startTime: number,\n generateStepId: () => string,\n ) {\n const getTimestamp = () => Date.now() - startTime;\n\n // Track navigation\n page.on(\"framenavigated\", (frame) => {\n if (frame === page.mainFrame()) {\n const url = frame.url();\n // Avoid duplicate nav steps for initial load\n const lastStep = steps[steps.length - 1];\n if (\n steps.length > 0 &&\n lastStep.type === \"navigate\" &&\n lastStep.url === url\n ) {\n return;\n }\n steps.push({\n id: generateStepId(),\n type: \"navigate\",\n url,\n timestamp: getTimestamp(),\n });\n }\n });\n\n // Expose recording function to browser\n page.exposeFunction(\n \"__vulcn_record\",\n (event: { type: string; data: Record<string, unknown> }) => {\n const timestamp = getTimestamp();\n\n switch (event.type) {\n case \"click\": {\n const data = event.data as {\n selector: string;\n x: number;\n y: number;\n };\n steps.push({\n id: generateStepId(),\n type: \"click\",\n selector: data.selector,\n position: { x: data.x, y: data.y },\n timestamp,\n });\n break;\n }\n case \"input\": {\n const data = event.data as {\n selector: string;\n value: string;\n inputType: string | null;\n injectable: boolean;\n };\n steps.push({\n id: generateStepId(),\n type: \"input\",\n selector: data.selector,\n value: data.value,\n injectable: data.injectable,\n timestamp,\n });\n break;\n }\n case \"keypress\": {\n const data = event.data as { key: string; modifiers?: string[] };\n steps.push({\n id: generateStepId(),\n type: \"keypress\",\n key: data.key,\n modifiers: data.modifiers,\n timestamp,\n });\n break;\n }\n }\n },\n );\n\n // Inject recording script into every frame\n page.on(\"load\", async () => {\n await Recorder.injectRecordingScript(page);\n });\n\n // Inject into initial page\n Recorder.injectRecordingScript(page);\n }\n\n private static async injectRecordingScript(page: Page) {\n await page.evaluate(`\n (function() {\n if (window.__vulcn_injected) return;\n window.__vulcn_injected = true;\n\n var textInputTypes = ['text', 'password', 'email', 'search', 'url', 'tel', 'number'];\n\n function getSelector(el) {\n if (el.id) {\n return '#' + CSS.escape(el.id);\n }\n if (el.name) {\n var tag = el.tagName.toLowerCase();\n var nameSelector = tag + '[name=\"' + el.name + '\"]';\n if (document.querySelectorAll(nameSelector).length === 1) {\n return nameSelector;\n }\n }\n if (el.dataset && el.dataset.testid) {\n return '[data-testid=\"' + el.dataset.testid + '\"]';\n }\n if (el.tagName === 'INPUT' && el.type && el.name) {\n var inputSelector = 'input[type=\"' + el.type + '\"][name=\"' + el.name + '\"]';\n if (document.querySelectorAll(inputSelector).length === 1) {\n return inputSelector;\n }\n }\n if (el.className && typeof el.className === 'string') {\n var classes = el.className.trim().split(/\\\\s+/).filter(function(c) { return c.length > 0; });\n if (classes.length > 0) {\n var classSelector = el.tagName.toLowerCase() + '.' + classes.map(function(c) { return CSS.escape(c); }).join('.');\n if (document.querySelectorAll(classSelector).length === 1) {\n return classSelector;\n }\n }\n }\n var path = [];\n var current = el;\n while (current && current !== document.body) {\n var tag = current.tagName.toLowerCase();\n var parent = current.parentElement;\n if (parent) {\n var siblings = Array.from(parent.children).filter(function(c) { return c.tagName === current.tagName; });\n if (siblings.length > 1) {\n var index = siblings.indexOf(current) + 1;\n tag = tag + ':nth-of-type(' + index + ')';\n }\n }\n path.unshift(tag);\n current = parent;\n }\n return path.join(' > ');\n }\n\n function getInputType(el) {\n if (el.tagName === 'INPUT') return el.type || 'text';\n if (el.tagName === 'TEXTAREA') return 'textarea';\n if (el.tagName === 'SELECT') return 'select';\n return null;\n }\n\n function isTextInjectable(el) {\n var inputType = getInputType(el);\n if (!inputType) return false;\n if (inputType === 'textarea') return true;\n if (inputType === 'select') return false;\n return textInputTypes.indexOf(inputType) !== -1;\n }\n\n document.addEventListener('click', function(e) {\n var target = e.target;\n window.__vulcn_record({\n type: 'click',\n data: {\n selector: getSelector(target),\n x: e.clientX,\n y: e.clientY\n }\n });\n }, true);\n\n document.addEventListener('change', function(e) {\n var target = e.target;\n if ('value' in target) {\n var inputType = getInputType(target);\n window.__vulcn_record({\n type: 'input',\n data: {\n selector: getSelector(target),\n value: target.value,\n inputType: inputType,\n injectable: isTextInjectable(target)\n }\n });\n }\n }, true);\n\n document.addEventListener('keydown', function(e) {\n if (e.ctrlKey || e.metaKey || e.altKey) {\n var modifiers = [];\n if (e.ctrlKey) modifiers.push('ctrl');\n if (e.metaKey) modifiers.push('meta');\n if (e.altKey) modifiers.push('alt');\n if (e.shiftKey) modifiers.push('shift');\n\n window.__vulcn_record({\n type: 'keypress',\n data: {\n key: e.key,\n modifiers: modifiers\n }\n });\n }\n }, true);\n })();\n `);\n }\n}\n","/**\n * Built-in security payloads\n */\n\nexport type PayloadCategory = \"xss\" | \"sqli\" | \"ssrf\" | \"path-traversal\";\nexport type PayloadName =\n | \"xss-basic\"\n | \"xss-event\"\n | \"xss-svg\"\n | \"sqli-basic\"\n | \"sqli-error\"\n | \"sqli-blind\";\n\nexport interface Payload {\n name: PayloadName;\n category: PayloadCategory;\n payloads: string[];\n detectPatterns: RegExp[];\n description: string;\n}\n\nexport const BUILTIN_PAYLOADS: Record<PayloadName, Payload> = {\n \"xss-basic\": {\n name: \"xss-basic\",\n category: \"xss\",\n description: \"Basic XSS payloads with script tags and event handlers\",\n payloads: [\n '<script>alert(\"XSS\")</script>',\n '<img src=x onerror=alert(\"XSS\")>',\n '\"><script>alert(\"XSS\")</script>',\n \"javascript:alert('XSS')\",\n '<svg onload=alert(\"XSS\")>',\n ],\n detectPatterns: [\n /<script[^>]*>alert\\(/i,\n /onerror\\s*=\\s*alert\\(/i,\n /onload\\s*=\\s*alert\\(/i,\n /javascript:alert\\(/i,\n ],\n },\n \"xss-event\": {\n name: \"xss-event\",\n category: \"xss\",\n description: \"XSS via event handlers\",\n payloads: [\n '\" onfocus=\"alert(1)\" autofocus=\"',\n \"' onmouseover='alert(1)'\",\n '<body onload=alert(\"XSS\")>',\n \"<input onfocus=alert(1) autofocus>\",\n \"<marquee onstart=alert(1)>\",\n ],\n detectPatterns: [\n /onfocus\\s*=\\s*[\"']?alert/i,\n /onmouseover\\s*=\\s*[\"']?alert/i,\n /onload\\s*=\\s*[\"']?alert/i,\n /onstart\\s*=\\s*[\"']?alert/i,\n ],\n },\n \"xss-svg\": {\n name: \"xss-svg\",\n category: \"xss\",\n description: \"XSS via SVG elements\",\n payloads: [\n '<svg/onload=alert(\"XSS\")>',\n \"<svg><script>alert(1)</script></svg>\",\n \"<svg><animate onbegin=alert(1)>\",\n \"<svg><set onbegin=alert(1)>\",\n ],\n detectPatterns: [\n /<svg[^>]*onload\\s*=/i,\n /<svg[^>]*>.*<script>/i,\n /onbegin\\s*=\\s*alert/i,\n ],\n },\n \"sqli-basic\": {\n name: \"sqli-basic\",\n category: \"sqli\",\n description: \"Basic SQL injection payloads\",\n payloads: [\n \"' OR '1'='1\",\n \"' OR '1'='1' --\",\n \"1' OR '1'='1\",\n \"admin'--\",\n \"' UNION SELECT NULL--\",\n ],\n detectPatterns: [\n /sql.*syntax/i,\n /mysql.*error/i,\n /ORA-\\d{5}/i,\n /pg_query/i,\n /sqlite.*error/i,\n /unclosed.*quotation/i,\n ],\n },\n \"sqli-error\": {\n name: \"sqli-error\",\n category: \"sqli\",\n description: \"SQL injection payloads to trigger errors\",\n payloads: [\"'\", \"''\", \"`\", '\"', \"')\", \"'\\\"\", \"1' AND '1'='2\", \"1 AND 1=2\"],\n detectPatterns: [\n /sql.*syntax/i,\n /mysql.*error/i,\n /ORA-\\d{5}/i,\n /postgresql.*error/i,\n /sqlite.*error/i,\n /quoted.*string.*properly.*terminated/i,\n ],\n },\n \"sqli-blind\": {\n name: \"sqli-blind\",\n category: \"sqli\",\n description: \"Blind SQL injection payloads\",\n payloads: [\n \"1' AND SLEEP(5)--\",\n \"1; WAITFOR DELAY '0:0:5'--\",\n \"1' AND (SELECT COUNT(*) FROM information_schema.tables)>0--\",\n ],\n detectPatterns: [\n // Blind SQLi is detected by timing, not content\n ],\n },\n};\n\n/**\n * Get payloads by name\n */\nexport function getPayload(name: PayloadName): Payload | undefined {\n return BUILTIN_PAYLOADS[name];\n}\n\n/**\n * Get all payload names\n */\nexport function getPayloadNames(): PayloadName[] {\n return Object.keys(BUILTIN_PAYLOADS) as PayloadName[];\n}\n\n/**\n * Get payloads by category\n */\nexport function getPayloadsByCategory(category: PayloadCategory): Payload[] {\n return Object.values(BUILTIN_PAYLOADS).filter((p) => p.category === category);\n}\n","import type { Page } from \"playwright\";\nimport { launchBrowser } from \"./browser\";\nimport { BUILTIN_PAYLOADS, type PayloadName } from \"./payloads\";\nimport type { Session, Step } from \"./session\";\nimport type { Finding, RunResult, RunnerOptions } from \"./types\";\n\n/**\n * Runner - replays sessions with security payloads\n */\nexport class Runner {\n /**\n * Execute a session with security payloads\n */\n static async execute(\n session: Session,\n payloadNames: PayloadName[],\n options: RunnerOptions = {},\n ): Promise<RunResult> {\n const browserType = options.browser ?? session.browser ?? \"chromium\";\n const headless = options.headless ?? true;\n const startTime = Date.now();\n\n const findings: Finding[] = [];\n const errors: string[] = [];\n let payloadsTested = 0;\n\n // Launch browser\n const { browser } = await launchBrowser({\n browser: browserType,\n headless,\n });\n const context = await browser.newContext({ viewport: session.viewport });\n const page = await context.newPage();\n\n try {\n // Find injectable steps\n const injectableSteps = session.steps.filter(\n (step): step is Step & { type: \"input\" } =>\n step.type === \"input\" && step.injectable !== false,\n );\n\n // Get all payloads\n const allPayloads: { name: PayloadName; value: string }[] = [];\n for (const name of payloadNames) {\n const payload = BUILTIN_PAYLOADS[name];\n if (payload) {\n for (const value of payload.payloads) {\n allPayloads.push({ name, value });\n }\n }\n }\n\n // For each injectable step, test with each payload\n for (const injectableStep of injectableSteps) {\n for (const payload of allPayloads) {\n try {\n // Replay session up to this step with payload injected\n const finding = await Runner.replayWithPayload(\n page,\n session,\n injectableStep,\n payload.name,\n payload.value,\n );\n\n if (finding) {\n findings.push(finding);\n options.onFinding?.(finding);\n }\n\n payloadsTested++;\n } catch (err) {\n errors.push(`${injectableStep.id}: ${String(err)}`);\n }\n }\n }\n } finally {\n await browser.close();\n }\n\n return {\n findings,\n stepsExecuted: session.steps.length,\n payloadsTested,\n duration: Date.now() - startTime,\n errors,\n };\n }\n\n private static async replayWithPayload(\n page: Page,\n session: Session,\n targetStep: Step & { type: \"input\" },\n payloadName: PayloadName,\n payloadValue: string,\n ): Promise<Finding | undefined> {\n // Navigate to start\n await page.goto(session.startUrl);\n\n // Replay steps\n for (const step of session.steps) {\n if (step.type === \"navigate\") {\n await page.goto(step.url);\n } else if (step.type === \"click\") {\n await page.click(step.selector, { timeout: 5000 });\n } else if (step.type === \"input\") {\n // Inject payload for target step\n const value = step.id === targetStep.id ? payloadValue : step.value;\n await page.fill(step.selector, value, { timeout: 5000 });\n } else if (step.type === \"keypress\") {\n const modifiers = step.modifiers ?? [];\n for (const mod of modifiers) {\n await page.keyboard.down(mod as \"Control\" | \"Shift\" | \"Alt\" | \"Meta\");\n }\n await page.keyboard.press(step.key);\n for (const mod of modifiers.reverse()) {\n await page.keyboard.up(mod as \"Control\" | \"Shift\" | \"Alt\" | \"Meta\");\n }\n }\n\n // If we just filled the target step, check for reflection\n if (step.id === targetStep.id) {\n const finding = await Runner.checkForVulnerability(\n page,\n targetStep,\n payloadName,\n payloadValue,\n );\n if (finding) {\n return finding;\n }\n }\n }\n\n return undefined;\n }\n\n private static async checkForVulnerability(\n page: Page,\n step: Step & { type: \"input\" },\n payloadName: PayloadName,\n payloadValue: string,\n ): Promise<Finding | undefined> {\n const payload = BUILTIN_PAYLOADS[payloadName];\n if (!payload) return undefined;\n\n // Get page content\n const content = await page.content();\n\n // Check for reflection patterns\n for (const pattern of payload.detectPatterns) {\n if (pattern.test(content)) {\n return {\n type: payload.category,\n severity: payload.category === \"xss\" ? \"high\" : \"critical\",\n title: `${payload.category.toUpperCase()} vulnerability detected`,\n description: `Payload was reflected in page content`,\n stepId: step.id,\n payload: payloadValue,\n url: page.url(),\n evidence: content.match(pattern)?.[0],\n };\n }\n }\n\n // Check if payload appears verbatim (potential XSS)\n if (content.includes(payloadValue)) {\n return {\n type: payload.category,\n severity: \"medium\",\n title: `Potential ${payload.category.toUpperCase()} - payload reflection`,\n description: `Payload was reflected in page without encoding`,\n stepId: step.id,\n payload: payloadValue,\n url: page.url(),\n };\n }\n\n return undefined;\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vulcn/engine",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Security testing engine - Browser recording and payload injection for vulnerability detection",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"dev": "tsup --watch",
|
|
25
|
+
"clean": "rm -rf dist CHANGELOG.md LICENSE README.md",
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
27
|
+
"prepack": "cp ../CHANGELOG.md ../LICENSE ../README.md .",
|
|
28
|
+
"postpack": "rm -f CHANGELOG.md LICENSE README.md",
|
|
29
|
+
"prepublishOnly": "npm run build"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"vulcn",
|
|
33
|
+
"security",
|
|
34
|
+
"testing",
|
|
35
|
+
"recorder",
|
|
36
|
+
"playwright",
|
|
37
|
+
"browser",
|
|
38
|
+
"automation",
|
|
39
|
+
"xss",
|
|
40
|
+
"sql-injection",
|
|
41
|
+
"penetration-testing"
|
|
42
|
+
],
|
|
43
|
+
"author": "rawlab",
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/rawlab-dev/vulcn.git",
|
|
48
|
+
"directory": "src"
|
|
49
|
+
},
|
|
50
|
+
"homepage": "https://rawlab.dev/vulcn",
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/rawlab-dev/vulcn/issues"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18.0.0"
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"playwright": "^1.50.0",
|
|
62
|
+
"yaml": "^2.7.0",
|
|
63
|
+
"zod": "^3.24.0"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"typescript": "^5.7.0",
|
|
67
|
+
"tsup": "^8.4.0",
|
|
68
|
+
"@types/node": "^22.0.0"
|
|
69
|
+
}
|
|
70
|
+
}
|