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.

46 lines 2.21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const rule = { meta: { id: 'LOVABLE006', category: 'security', severity: 'medium', message: 'Supabase storage access without proper validation', fix: 'Add file size/type validation and ensure storage RLS policies are configured', helpUri: 'https://supabase.com/docs/guides/storage/security/access-control', impact: 'Unvalidated file uploads can lead to storage abuse, malware hosting, or unauthorized data access.' }, impl: { detect: (content, file, lines) => { const results = []; // Pattern: .storage.from() calls (allow whitespace/newlines between .storage and .from) const storagePattern = /\.storage\s*\.\s*from\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/gi; let match; while ((match = storagePattern.exec(content)) !== null) { const bucketName = match[1]; const beforeMatch = content.substring(0, match.index); const lineNumber = beforeMatch.split('\n').length; // Check if it's a public bucket without validation const isPublicBucket = /public/i.test(bucketName); // Look for file validation nearby (within 10 lines before and after) const startCheck = Math.max(0, lineNumber - 10); const endCheck = Math.min(lines.length, lineNumber + 10); const contextLines = lines.slice(startCheck, endCheck); const hasValidation = contextLines.some(l => /\.size|maxSize|fileSize|MAX_FILE_SIZE/i.test(l) || /\.type|mime|content-type|allowed.*types/i.test(l) || /validate/i.test(l)); if (isPublicBucket || !hasValidation) { results.push({ line: lineNumber, match: match[0], confidence: 0.80 }); } } return results; }, fileTypes: ['js', 'jsx', 'ts', 'tsx'] } }; exports.default = rule; //# sourceMappingURL=LOVABLE006.js.map