vibe-guard
Version:
██ Vibe-Guard Security Scanner - 28 essential security rules to catch vulnerabilities before they catch you! Zero dependencies, instant setup, works everywhere, optimized performance. Detects SQL injection, XSS, exposed secrets, CSRF, CORS issues, contain
439 lines • 19.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AiAgentAccessControlRule = void 0;
const types_1 = require("../types");
class AiAgentAccessControlRule extends types_1.BaseRule {
constructor() {
super(...arguments);
this.name = 'ai-agent-access-control';
this.description = 'Detects insecure AI agent access controls and privilege escalation with context-aware analysis';
this.severity = 'critical';
this.accessControlPatterns = [
// AI Agent with elevated privileges: Tighter patterns!
// Critical severity
{
pattern: /(?:ai[_-]?agent|agent|bot|assistant)\s*[:=]\s*['"`]?(?:admin|root|superuser|sudo)['"`]?/gi,
type: 'Elevated AI Agent Privileges',
confidence: 0.95,
severity: 'critical',
validation: (text) => this.validateElevatedPrivileges(text)
},
// Critical severity
{
pattern: /(?:permissions?|roles?|access)\s*[:=]\s*['"`]?(?:all|full|unlimited|wildcard)['"`]?/gi,
type: 'Unlimited AI Agent Permissions',
confidence: 0.9,
severity: 'critical',
validation: (text) => this.validateUnlimitedPermissions(text)
},
// High severity
// Authentication bypass patterns
{
pattern: /(?:auth|authentication)\s*[:=]\s*['"`]?(?:false|no|0|disabled|off)['"`]?/gi,
type: 'Disabled AI Agent Authentication',
confidence: 0.95,
severity: 'critical',
validation: (text) => this.validateDisabledAuth(text)
},
// High severity
// Missing RBAC for AI agents: More specific
{
pattern: /(?:ai[_-]?agent|agent|bot|assistant)\s*[:=]\s*['"`]?[^'"`]*\b(?:without|no|missing)\s+(?:role|permission|access[_-]?control)['"`]?/gi,
type: 'Missing AI Agent RBAC',
confidence: 0.85,
severity: 'high',
validation: (text) => this.validateMissingRBAC(text)
},
// Critical severity
// AI Agent with persistent elevated access
{
pattern: /(?:ai[_-]?agent|agent|bot|assistant).*?(?:permanent|persistent|always|forever).*?(?:admin|root|elevated)/gi,
type: 'Persistent Elevated AI Access',
confidence: 0.9,
severity: 'critical',
validation: (text) => this.validatePersistentAccess(text)
},
// High severity
// AI Agent bypassing authentication
{
pattern: /(?:ai[_-]?agent|agent|bot|assistant).*?(?:bypass|skip|ignore).*?(?:auth|authentication|login)/gi,
type: 'AI Agent Auth Bypass',
confidence: 0.95,
severity: 'critical',
validation: (text) => this.validateAuthBypass(text)
},
// High severity
// AI Agent with system-level access
{
pattern: /(?:ai[_-]?agent|agent|bot|assistant).*?(?:system|os|kernel|hardware)/gi,
type: 'AI Agent System Access',
confidence: 0.8,
severity: 'high',
validation: (text) => this.validateSystemAccess(text)
},
// High severity
// MCP Server insecure access: Tighter patterns!
{
pattern: /(?:mcp|model[_-]?context[_-]?protocol).*?(?:unrestricted|open|public)/gi,
type: 'Insecure MCP Server Access',
confidence: 0.85,
severity: 'high',
validation: (text) => this.validateInsecureMCP(text)
},
// High severity
{
pattern: /(?:mcp[_-]?server|model[_-]?context[_-]?protocol).*?(?:no[_-]?auth|without[_-]?auth)/gi,
type: 'MCP Server Without Auth',
confidence: 0.9,
severity: 'high',
validation: (text) => this.validateMCPNoAuth(text)
},
// Medium severity
// AI Agent with file system access
{
pattern: /(?:ai[_-]?agent|agent|bot|assistant).*?(?:file|directory|path|fs)/gi,
type: 'AI Agent File System Access',
confidence: 0.75,
severity: 'medium',
validation: (text) => this.validateFileSystemAccess(text)
},
// Medium severity
// AI Agent with network access
{
pattern: /(?:ai[_-]?agent|agent|bot|assistant).*?(?:network|http|https|api|endpoint)/gi,
type: 'AI Agent Network Access',
confidence: 0.7,
severity: 'medium',
validation: (text) => this.validateNetworkAccess(text)
}
];
this.falsePositivePatterns = [
// Development and testing patterns:
/example/i,
/demo/i,
/test/i,
/mock/i,
/sample/i,
/placeholder/i,
/comment/i,
/todo/i,
/fixme/i,
/\/\/.*/i,
/#.*/i,
/\/\*.*\*\//i,
/<!--.*-->/i,
/development/i,
/dev/i,
/staging/i,
/localhost/i,
// Sandbox and safe environments:
/sandbox/i,
/isolated/i,
/contained/i,
/restricted/i,
/safe[_-]?mode/i,
/demo[_-]?mode/i,
/test[_-]?environment/i,
// Documentation and examples:
/documentation/i,
/docs?/i,
/readme/i,
/example[_-]?config/i,
/sample[_-]?config/i,
// Security related patterns (likely safe):
/secure/i,
/protected/i,
/guarded/i,
/monitored/i,
/audited/i,
/logged/i,
/restricted/i
];
}
check(fileContent) {
const issues = [];
const language = this.detectLanguage(fileContent.path);
const framework = this.detectFramework(fileContent.content, language);
const hasAuthChecks = this.hasAuthChecks(fileContent.content);
const isProtectedEnvironment = this.isProtectedEnvironment(fileContent.content);
for (const { pattern, type, confidence, severity, validation } of this.accessControlPatterns) {
const matches = this.findMatches(fileContent.content, pattern);
for (const { match, line, column, lineContent } of matches) {
const matchedText = match[0];
const context = this.analyzeContext(fileContent, line, column, language, framework, hasAuthChecks, isProtectedEnvironment);
// Skips if in safe context
if (this.isSafeContext(context)) {
continue;
}
// Validates the access control issue
if (!validation(matchedText)) {
continue;
}
// Calculates final confidence based on context
const finalConfidence = this.calculateConfidence(confidence, context);
if (finalConfidence >= 0.5) {
issues.push(this.createIssue(fileContent.path, line, column, lineContent, `${severity.toUpperCase()}: ${type} detected (confidence: ${Math.round(finalConfidence * 100)}%): ${this.getLineContext(lineContent, column)}`, this.generateSuggestion(type, context), severity));
}
}
}
return issues;
}
analyzeContext(fileContent, line, column, language, framework, hasAuthChecks, isProtectedEnvironment) {
const lines = fileContent.lines;
const currentLine = lines[line - 1] || '';
const surroundingLines = lines.slice(Math.max(0, line - 3), line + 2);
return {
isInComment: this.isInComment(currentLine, language),
isInString: this.isInString(currentLine, column),
isInTestFile: this.isInTestFile(fileContent.path),
isInDocumentation: this.isInDocumentation(fileContent.path),
isInDevelopment: this.isInDevelopment(surroundingLines),
isInSandbox: this.isInSandbox(surroundingLines),
surroundingCode: surroundingLines.join('\n'),
language,
framework,
hasAuthChecks: hasAuthChecks || false,
isProtectedEnvironment: isProtectedEnvironment || false
};
}
isSafeContext(context) {
if (context.isInComment)
return true;
if (context.isInTestFile)
return true;
if (context.isInDocumentation)
return true;
if (context.isInDevelopment)
return true;
if (context.isInSandbox)
return true;
if (this.falsePositivePatterns.some(pattern => pattern.test(context.surroundingCode))) {
return true;
}
if (context.hasAuthChecks)
return true;
if (context.isProtectedEnvironment)
return true;
return false;
}
detectLanguage(filePath) {
const ext = filePath.split('.').pop()?.toLowerCase();
const languageMap = {
'js': 'javascript',
'jsx': 'javascript',
'ts': 'typescript',
'tsx': 'typescript',
'py': 'python',
'php': 'php',
'rb': 'ruby',
'go': 'go',
'java': 'java',
'cs': 'csharp'
};
return languageMap[ext || ''] || 'unknown';
}
detectFramework(content, language) {
if (language === 'javascript' || language === 'typescript') {
if (content.includes('openai') || content.includes('OpenAI'))
return 'openai';
if (content.includes('anthropic') || content.includes('Anthropic'))
return 'anthropic';
if (content.includes('langchain') || content.includes('LangChain'))
return 'langchain';
if (content.includes('llama') || content.includes('Llama'))
return 'llama';
}
if (language === 'python') {
if (content.includes('openai') || content.includes('OpenAI'))
return 'openai';
if (content.includes('anthropic') || content.includes('Anthropic'))
return 'anthropic';
if (content.includes('langchain') || content.includes('LangChain'))
return 'langchain';
if (content.includes('transformers') || content.includes('Transformers'))
return 'transformers';
}
return undefined;
}
isInComment(line, language) {
const trimmed = line.trim();
if (language === 'javascript' || language === 'typescript') {
return trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*');
}
if (language === 'python') {
return trimmed.startsWith('#');
}
if (language === 'php') {
return trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('#');
}
return false;
}
isInString(line, column) {
const before = line.substring(0, column);
const quotes = (before.match(/['"`]/g) || []).length;
return quotes % 2 === 1;
}
isInTestFile(filePath) {
return filePath.includes('test') || filePath.includes('spec') || filePath.includes('mock');
}
isInDocumentation(filePath) {
const docPatterns = [
/docs?\//i,
/documentation/i,
/examples?/i,
/samples?/i,
/tutorials?/i,
/guides?/i,
/readme/i,
/\.md$/i,
/\.rst$/i,
/\.txt$/i
];
return docPatterns.some(pattern => pattern.test(filePath));
}
isInDevelopment(lines) {
return lines.some(line => line.includes('development') ||
line.includes('dev') ||
line.includes('staging') ||
line.includes('localhost') ||
line.includes('127.0.0.1') ||
line.includes('NODE_ENV') ||
line.includes('DEBUG'));
}
isInSandbox(lines) {
return lines.some(line => line.includes('sandbox') ||
line.includes('isolated') ||
line.includes('contained') ||
line.includes('restricted') ||
line.includes('safe[_-]?mode') ||
line.includes('demo[_-]?mode'));
}
hasAuthChecks(content) {
const authPatterns = [
/auth/i,
/authentication/i,
/authorization/i,
/permission/i,
/role/i,
/access[_-]?control/i,
/rbac/i,
/middleware/i,
/guard/i,
/protect/i,
/secure/i
];
return authPatterns.some(pattern => pattern.test(content));
}
isProtectedEnvironment(content) {
const protectedPatterns = [
/sandbox/i,
/isolated/i,
/contained/i,
/restricted/i,
/monitored/i,
/audited/i,
/logged/i,
/safe/i,
/protected/i
];
return protectedPatterns.some(pattern => pattern.test(content));
}
calculateConfidence(baseConfidence, context) {
let confidence = baseConfidence;
// Adjusts confidence based on context
if (context.hasAuthChecks)
confidence *= 0.6; // Reduces if auth checks present
if (context.isProtectedEnvironment)
confidence *= 0.7; // Reduces if in protected environment
if (context.framework)
confidence *= 1.1; // Increases for known frameworks
return Math.min(confidence, 1.0);
}
// Validation methods for different access control issues!
validateElevatedPrivileges(text) {
const privilegeKeywords = ['admin', 'root', 'superuser', 'sudo'];
return privilegeKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateUnlimitedPermissions(text) {
const unlimitedKeywords = ['all', 'full', 'unlimited', 'wildcard'];
return unlimitedKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateDisabledAuth(text) {
const disabledKeywords = ['false', 'no', '0', 'disabled', 'off'];
return disabledKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateMissingRBAC(text) {
const missingKeywords = ['without', 'no', 'missing'];
const rbacKeywords = ['role', 'permission', 'access[_-]?control'];
return missingKeywords.some(missing => text.toLowerCase().includes(missing)) &&
rbacKeywords.some(rbac => text.toLowerCase().includes(rbac));
}
validatePersistentAccess(text) {
const persistentKeywords = ['permanent', 'persistent', 'always', 'forever'];
const elevatedKeywords = ['admin', 'root', 'elevated'];
return persistentKeywords.some(persistent => text.toLowerCase().includes(persistent)) &&
elevatedKeywords.some(elevated => text.toLowerCase().includes(elevated));
}
validateAuthBypass(text) {
const bypassKeywords = ['bypass', 'skip', 'ignore'];
const authKeywords = ['auth', 'authentication', 'login'];
return bypassKeywords.some(bypass => text.toLowerCase().includes(bypass)) &&
authKeywords.some(auth => text.toLowerCase().includes(auth));
}
validateSystemAccess(text) {
const systemKeywords = ['system', 'os', 'kernel', 'hardware'];
return systemKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateInsecureMCP(text) {
const insecureKeywords = ['unrestricted', 'open', 'public'];
return insecureKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateMCPNoAuth(text) {
const noAuthKeywords = ['no[_-]?auth', 'without[_-]?auth'];
return noAuthKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateFileSystemAccess(text) {
const fsKeywords = ['file', 'directory', 'path', 'fs'];
return fsKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateNetworkAccess(text) {
const networkKeywords = ['network', 'http', 'https', 'api', 'endpoint'];
return networkKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
getLineContext(lineContent, column) {
const start = Math.max(0, column - 20);
const end = Math.min(lineContent.length, column + 20);
return lineContent.substring(start, end).trim();
}
generateSuggestion(type, context) {
const suggestions = {
'Elevated AI Agent Privileges': 'Implement least privilege principle. Use role-based access control (RBAC) and temporary elevated access only when necessary.',
'Unlimited AI Agent Permissions': 'Define specific, limited permissions for AI agents. Use principle of least privilege and granular access controls.',
'Disabled AI Agent Authentication': 'Enable authentication for all AI agents. Use secure authentication mechanisms and never disable auth in production.',
'Missing AI Agent RBAC': 'Implement role-based access control for AI agents. Define specific roles and permissions based on agent capabilities.',
'Persistent Elevated AI Access': 'Use temporary elevated access with time limits. Implement just-in-time access and automatic privilege revocation.',
'AI Agent Auth Bypass': 'Remove any authentication bypass mechanisms. Implement proper authentication and authorization for all AI agent interactions.',
'AI Agent System Access': 'Restrict AI agent access to system resources. Use sandboxing and isolation techniques to limit system access.',
'Insecure MCP Server Access': 'Secure MCP server access with authentication and authorization. Use network isolation and access controls.',
'MCP Server Without Auth': 'Implement authentication for MCP servers. Use secure authentication mechanisms and access controls.',
'AI Agent File System Access': 'Limit AI agent file system access to specific directories. Use read-only access where possible and implement access controls.',
'AI Agent Network Access': 'Restrict AI agent network access to specific endpoints. Use network segmentation and access controls.'
};
let suggestion = suggestions[type] || 'Implement proper access controls for AI agents. Use least privilege principle and secure authentication.';
if (context.framework) {
suggestion += ` For ${context.framework}, consider using framework-specific security features and access control patterns.`;
if (context.framework === 'openai') {
suggestion += ' Use OpenAI API key restrictions and content filtering.';
}
else if (context.framework === 'anthropic') {
suggestion += ' Use Anthropic safety features and content filtering.';
}
else if (context.framework === 'langchain') {
suggestion += ' Use LangChain security features and agent isolation.';
}
}
return suggestion;
}
}
exports.AiAgentAccessControlRule = AiAgentAccessControlRule;
//# sourceMappingURL=ai-agent-access-control.js.map