UNPKG

ubon

Version:

Security scanner for AI-generated apps (Cursor, Lovable, Windsurf, v0). Catches hardcoded secrets, prompt injection, hallucinated imports, Server Actions / Edge runtime mistakes, and the vibe-coded vulnerabilities traditional linters miss.

98 lines 3.74 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.toSarif = toSarif; const rules_1 = require("../rules"); const redact_1 = require("./redact"); const package_json_1 = __importDefault(require("../../package.json")); const crypto_1 = require("crypto"); function synthesizeFingerprint(r) { return (0, crypto_1.createHash)('sha1') .update([r.ruleId, r.file || '', r.line || 0, r.match || r.message].join('|')) .digest('hex') .slice(0, 16); } function toSarif(results, _repoRoot) { const rulesMap = new Map(); const sarifResults = results.map((r) => { if (!rulesMap.has(r.ruleId)) { const meta = rules_1.RULES[r.ruleId]; rulesMap.set(r.ruleId, { id: r.ruleId, name: r.ruleId, shortDescription: { text: r.message.slice(0, 64) }, fullDescription: { text: r.message }, properties: { category: r.category, severity: r.severity, confidence: r.confidence, }, defaultConfiguration: { level: r.type === 'error' ? 'error' : r.type === 'warning' ? 'warning' : 'note', }, help: { text: r.fix || (meta?.fix || '') }, helpUri: meta?.helpUri, }); } const level = r.type === 'error' ? 'error' : r.type === 'warning' ? 'warning' : 'note'; return { ruleId: r.ruleId, level, message: { text: r.message }, locations: r.file ? [ { physicalLocation: { artifactLocation: { uri: normalizePath(r.file) }, region: r.range ? { startLine: r.range.startLine, startColumn: r.range.startColumn, endLine: r.range.endLine, endColumn: r.range.endColumn, } : r.line ? { startLine: r.line } : undefined, }, }, ] : [], properties: { category: r.category, severity: r.severity, confidence: r.confidence, fingerprint: r.fingerprint, match: (0, redact_1.redact)(r.match), fix: r.fix, }, partialFingerprints: { "ubon/fingerprint": r.fingerprint || synthesizeFingerprint(r) }, }; }); const sarif = { $schema: 'https://json.schemastore.org/sarif-2.1.0.json', version: '2.1.0', runs: [ { tool: { driver: { name: 'ubon', // @ts-ignore version is allowed in SARIF driver version: package_json_1.default.version, informationUri: 'https://github.com/luisfer/ubon', rules: Array.from(rulesMap.values()), }, }, results: sarifResults, }, ], }; return sarif; } function normalizePath(p) { // Keep relative paths for SARIF consumers return p.replace(/\\/g, '/'); } //# sourceMappingURL=sarif.js.map