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.
57 lines • 2.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const rule = {
meta: {
id: 'VITE001',
category: 'security',
severity: 'high',
message: 'Environment variable without VITE_ prefix may expose secrets to client',
fix: 'Rename to VITE_{varName} in .env if safe to expose, or keep server-side only',
helpUri: 'https://vitejs.dev/guide/env-and-mode.html#env-variables',
impact: 'Exposed secrets in client bundles can be extracted by anyone viewing your JavaScript, leading to API abuse or unauthorized access.'
},
impl: {
detect: (content, file, lines) => {
const results = [];
// Pattern: import.meta.env.SOMETHING (not prefixed with VITE_)
const envPattern = /import\.meta\.env\.([A-Z_][A-Z0-9_]*)/g;
let match;
while ((match = envPattern.exec(content)) !== null) {
const varName = match[1];
// Skip if it's a VITE_ prefixed var (those are meant for client)
if (varName.startsWith('VITE_'))
continue;
// Skip common Vite built-ins
if (['MODE', 'DEV', 'PROD', 'SSR', 'BASE_URL'].includes(varName))
continue;
const beforeMatch = content.substring(0, match.index);
const lineNumber = beforeMatch.split('\n').length;
results.push({
line: lineNumber,
match: match[0],
confidence: 0.92
});
}
// Also check for process.env in Vite context (wrong, won't work)
const processEnvPattern = /process\.env\.([A-Z_][A-Z0-9_]*)/g;
while ((match = processEnvPattern.exec(content)) !== null) {
const beforeMatch = content.substring(0, match.index);
const lineNumber = beforeMatch.split('\n').length;
const _line = lines[lineNumber - 1];
// Only flag if this is clearly client-side code (not in /api/ or server files)
const isClientSide = !/(\/api\/|\.server\.|server\/)/.test(file);
if (isClientSide) {
results.push({
line: lineNumber,
match: match[0],
confidence: 0.88
});
}
}
return results;
},
fileTypes: ['js', 'jsx', 'ts', 'tsx', 'svelte', 'astro']
}
};
exports.default = rule;
//# sourceMappingURL=VITE001.js.map