@boundless-oss/atlas
Version:
Atlas - MCP Server for comprehensive startup project management
755 lines • 27.9 kB
JavaScript
import { randomUUID } from 'crypto';
import { createTool, createSuccessResult, createErrorResult } from '../../core/tool-framework.js';
import { SecurityScanner } from './scanner.js';
import { SecurityManager } from '../../utils/security-manager.js';
// Security scanner and manager instances
let securityScanner;
let securityManager;
/**
* Get security status
*/
const getSecurityStatusTool = createTool({
name: 'get_security_status',
description: 'Get comprehensive security status overview including recent events, policy status, and system health',
category: 'security',
readOnly: true,
inputSchema: {
type: 'object',
properties: {},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
// Initialize managers if needed
if (!securityManager) {
securityManager = SecurityManager.getInstance();
}
const status = await securityManager.getSecurityStatus();
return createSuccessResult({
status,
generatedAt: new Date().toISOString()
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Failed to get security status: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Get security events
*/
const getSecurityEventsTool = createTool({
name: 'get_security_events',
description: 'Retrieve security events and incidents with filtering options',
category: 'security',
readOnly: true,
inputSchema: {
type: 'object',
properties: {
timeRange: {
type: 'string',
enum: ['1h', '24h', '7d', '30d'],
default: '24h',
description: 'Time range for event retrieval'
},
eventTypes: {
type: 'array',
items: {
type: 'string',
enum: ['access_denied', 'approval_required', 'policy_violation', 'suspicious_activity', 'error']
},
description: 'Filter events by type'
},
severity: {
type: 'string',
enum: ['low', 'medium', 'high', 'critical'],
default: 'low',
description: 'Minimum severity level to include'
}
},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityManager) {
securityManager = SecurityManager.getInstance();
}
const events = await securityManager.getSecurityEvents({
timeRange: input.timeRange || '24h',
eventTypes: input.eventTypes,
severity: input.severity || 'low'
});
return createSuccessResult({
timeRange: input.timeRange || '24h',
eventCount: events.length,
events,
generatedAt: new Date().toISOString()
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Failed to get security events: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Configure security policy
*/
const configureSecurityPolicyTool = createTool({
name: 'configure_security_policy',
description: 'Configure security policies including approval requirements, role definitions, and risk thresholds',
category: 'security',
requiresApproval: true,
inputSchema: {
type: 'object',
properties: {
requireApprovalFor: {
type: 'array',
items: { type: 'string' },
description: 'List of operations requiring human approval'
},
roles: {
type: 'object',
additionalProperties: {
type: 'array',
items: { type: 'string' }
},
description: 'Role definitions with permissions'
},
riskThresholds: {
type: 'object',
additionalProperties: { type: 'number' },
description: 'Risk threshold values for different operations'
},
logLevel: {
type: 'string',
enum: ['debug', 'info', 'warn', 'error'],
default: 'info',
description: 'Security logging level'
}
},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityManager) {
securityManager = SecurityManager.getInstance();
}
await securityManager.configureSecurityPolicy({
requireApprovalFor: input.requireApprovalFor || [],
roles: input.roles || {},
riskThresholds: input.riskThresholds || {},
logLevel: input.logLevel || 'info'
});
// Log security event
await context.db.run(`INSERT INTO security_events
(id, event_type, tool_name, user_id, context, risk_level, details, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
randomUUID(),
'policy_change',
'configure_security_policy',
context.userId || 'system',
JSON.stringify({ projectId: context.projectId }),
'high',
JSON.stringify(input),
Date.now()
]);
return createSuccessResult({
configuration: {
requireApprovalFor: input.requireApprovalFor || [],
roles: input.roles || {},
riskThresholds: input.riskThresholds || {},
logLevel: input.logLevel || 'info'
},
updatedAt: new Date().toISOString()
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Failed to configure security policy: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Process security approval
*/
const processSecurityApprovalTool = createTool({
name: 'process_security_approval',
description: 'Process pending security approval requests',
category: 'security',
inputSchema: {
type: 'object',
properties: {
approvalId: {
type: 'string',
description: 'Unique identifier for the approval request',
minLength: 1
},
decision: {
type: 'string',
enum: ['approve', 'deny'],
description: 'Decision for the approval request'
},
reason: {
type: 'string',
description: 'Optional reason for the decision',
maxLength: 1000
}
},
required: ['approvalId', 'decision'],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityManager) {
securityManager = SecurityManager.getInstance();
}
const result = await securityManager.processApproval({
approvalId: input.approvalId,
decision: input.decision,
reason: input.reason
});
// Log security event
await context.db.run(`INSERT INTO security_events
(id, event_type, tool_name, user_id, context, risk_level, details, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
randomUUID(),
'approval_processed',
'process_security_approval',
context.userId || 'system',
JSON.stringify({ projectId: context.projectId, approvalId: input.approvalId }),
'medium',
JSON.stringify({ decision: input.decision, reason: input.reason }),
Date.now()
]);
return createSuccessResult({
approvalId: input.approvalId,
decision: input.decision,
reason: input.reason,
result,
processedAt: new Date().toISOString()
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Failed to process approval: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Perform security scan
*/
const securityScanTool = createTool({
name: 'security_scan',
description: 'Perform comprehensive security scan of the project',
category: 'security',
readOnly: true,
inputSchema: {
type: 'object',
properties: {
scanType: {
type: 'string',
enum: ['quick', 'comprehensive', 'deep'],
default: 'comprehensive',
description: 'Type of security scan to perform'
},
includeFiles: {
type: 'boolean',
default: true,
description: 'Scan source files for security issues'
},
includeDependencies: {
type: 'boolean',
default: true,
description: 'Check dependencies for vulnerabilities'
},
includeSecrets: {
type: 'boolean',
default: true,
description: 'Scan for exposed secrets and credentials'
},
includePermissions: {
type: 'boolean',
default: true,
description: 'Check file permissions and access controls'
},
outputFormat: {
type: 'string',
enum: ['summary', 'detailed', 'json'],
default: 'detailed',
description: 'Format for scan results'
}
},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityScanner) {
const { ConfigManager } = await import('../../config/config-manager.js');
securityScanner = new SecurityScanner(new ConfigManager());
}
const config = {
scanType: input.scanType || 'comprehensive',
includeFiles: input.includeFiles !== false,
includeDependencies: input.includeDependencies !== false,
includeSecrets: input.includeSecrets !== false,
includePermissions: input.includePermissions !== false,
outputFormat: input.outputFormat || 'detailed'
};
const scanResult = await securityScanner.performScan(config);
// Log security event
await context.db.run(`INSERT INTO security_events
(id, event_type, tool_name, user_id, context, risk_level, details, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
randomUUID(),
'security_scan',
'security_scan',
context.userId || 'system',
JSON.stringify({ projectId: context.projectId }),
scanResult.summary.status === 'fail' ? 'high' : 'low',
JSON.stringify({
scanType: input.scanType,
summary: scanResult.summary
}),
Date.now()
]);
return createSuccessResult({
scanResult,
timestamp: new Date().toISOString()
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Security scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Check for secrets
*/
const checkSecretsTool = createTool({
name: 'check_secrets',
description: 'Scan for exposed secrets, API keys, and credentials',
category: 'security',
readOnly: true,
inputSchema: {
type: 'object',
properties: {
scanPath: {
type: 'string',
default: '.',
description: 'Path to scan for secrets'
},
excludePaths: {
type: 'array',
items: { type: 'string' },
default: ['.git', 'node_modules', '.atlas'],
description: 'Paths to exclude from scanning'
},
customPatterns: {
type: 'array',
items: { type: 'string' },
description: 'Custom regex patterns to detect secrets'
}
},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityScanner) {
const { ConfigManager } = await import('../../config/config-manager.js');
securityScanner = new SecurityScanner(new ConfigManager());
}
const secretsFound = await securityScanner.scanForSecrets({
scanPath: input.scanPath || '.',
excludePaths: input.excludePaths || ['.git', 'node_modules', '.atlas'],
customPatterns: input.customPatterns || []
});
// Log security event if secrets found
if (secretsFound.length > 0) {
await context.db.run(`INSERT INTO security_events
(id, event_type, tool_name, user_id, context, risk_level, details, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
randomUUID(),
'secrets_detected',
'check_secrets',
context.userId || 'system',
JSON.stringify({ projectId: context.projectId }),
'critical',
JSON.stringify({
count: secretsFound.length,
types: [...new Set(secretsFound.map((s) => s.type))]
}),
Date.now()
]);
}
return createSuccessResult({
secretsFound,
scanCompleted: true
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Secrets scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Check vulnerabilities
*/
const vulnerabilityCheckTool = createTool({
name: 'vulnerability_check',
description: 'Check dependencies for known vulnerabilities',
category: 'security',
readOnly: true,
inputSchema: {
type: 'object',
properties: {
checkNpm: {
type: 'boolean',
default: true,
description: 'Check npm dependencies'
},
checkYarn: {
type: 'boolean',
default: true,
description: 'Check yarn dependencies'
},
severity: {
type: 'string',
enum: ['low', 'moderate', 'high', 'critical'],
default: 'moderate',
description: 'Minimum severity level to report'
},
autoFix: {
type: 'boolean',
default: false,
description: 'Automatically fix vulnerabilities when possible'
}
},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityScanner) {
const { ConfigManager } = await import('../../config/config-manager.js');
securityScanner = new SecurityScanner(new ConfigManager());
}
const vulnerabilities = await securityScanner.checkVulnerabilities({
checkNpm: input.checkNpm !== false,
checkYarn: input.checkYarn !== false,
severity: input.severity || 'moderate',
autoFix: input.autoFix || false
});
// Log security event if vulnerabilities found
if (vulnerabilities.total > 0) {
await context.db.run(`INSERT INTO security_events
(id, event_type, tool_name, user_id, context, risk_level, details, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
randomUUID(),
'vulnerabilities_detected',
'vulnerability_check',
context.userId || 'system',
JSON.stringify({ projectId: context.projectId }),
vulnerabilities.critical > 0 ? 'critical' : 'high',
JSON.stringify({
total: vulnerabilities.total,
critical: vulnerabilities.critical,
high: vulnerabilities.high,
moderate: vulnerabilities.moderate,
low: vulnerabilities.low
}),
Date.now()
]);
}
return createSuccessResult({
vulnerabilities,
scanCompleted: true
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Vulnerability check failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Setup security configuration
*/
const setupSecurityConfigTool = createTool({
name: 'setup_security_config',
description: 'Configure comprehensive security tools and policies',
category: 'security',
requiresApproval: true,
inputSchema: {
type: 'object',
properties: {
enablePreCommitScans: {
type: 'boolean',
default: true,
description: 'Enable security scans in pre-commit hooks'
},
enableSecretDetection: {
type: 'boolean',
default: true,
description: 'Enable secret detection in CI/CD'
},
enableVulnerabilityChecks: {
type: 'boolean',
default: true,
description: 'Enable dependency vulnerability checks'
},
createSecurityPolicy: {
type: 'boolean',
default: true,
description: 'Create SECURITY.md policy file'
},
setupGitHooks: {
type: 'boolean',
default: true,
description: 'Setup Git hooks for security checks'
}
},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityScanner) {
const { ConfigManager } = await import('../../config/config-manager.js');
securityScanner = new SecurityScanner(new ConfigManager());
}
const setupResult = await securityScanner.setupSecurityConfiguration({
enablePreCommitScans: input.enablePreCommitScans !== false,
enableSecretDetection: input.enableSecretDetection !== false,
enableVulnerabilityChecks: input.enableVulnerabilityChecks !== false,
createSecurityPolicy: input.createSecurityPolicy !== false,
setupGitHooks: input.setupGitHooks !== false
});
// Log security event
await context.db.run(`INSERT INTO security_events
(id, event_type, tool_name, user_id, context, risk_level, details, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
randomUUID(),
'security_setup',
'setup_security_config',
context.userId || 'system',
JSON.stringify({ projectId: context.projectId }),
'medium',
JSON.stringify(input),
Date.now()
]);
return createSuccessResult({
setupResult,
configuration: {
enablePreCommitScans: input.enablePreCommitScans !== false,
enableSecretDetection: input.enableSecretDetection !== false,
enableVulnerabilityChecks: input.enableVulnerabilityChecks !== false,
createSecurityPolicy: input.createSecurityPolicy !== false,
setupGitHooks: input.setupGitHooks !== false
}
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Security setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Generate security report
*/
const generateSecurityReportTool = createTool({
name: 'generate_security_report',
description: 'Generate comprehensive security report for the project',
category: 'security',
readOnly: true,
inputSchema: {
type: 'object',
properties: {
includeOverview: {
type: 'boolean',
default: true,
description: 'Include security overview section'
},
includeDetails: {
type: 'boolean',
default: true,
description: 'Include detailed findings'
},
includeRecommendations: {
type: 'boolean',
default: true,
description: 'Include security recommendations'
},
outputPath: {
type: 'string',
default: 'SECURITY.md',
description: 'Path to save the security report'
}
},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityScanner) {
const { ConfigManager } = await import('../../config/config-manager.js');
securityScanner = new SecurityScanner(new ConfigManager());
}
const report = await securityScanner.generateSecurityReport({
includeOverview: input.includeOverview !== false,
includeDetails: input.includeDetails !== false,
includeRecommendations: input.includeRecommendations !== false
});
// Save report to file
const fsModule = await import('fs');
const pathModule = await import('path');
await fsModule.promises.writeFile(pathModule.join(process.cwd(), input.outputPath || 'SECURITY.md'), report.markdown);
return createSuccessResult({
reportGenerated: true,
outputPath: input.outputPath || 'SECURITY.md',
summary: report.summary
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Report generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Check data access
*/
const checkDataAccessTool = createTool({
name: 'check_data_access',
description: 'Monitor and detect improper access to .atlas/ directory',
category: 'security',
readOnly: true,
inputSchema: {
type: 'object',
properties: {
scanPath: {
type: 'string',
default: '.',
description: 'Path to scan for data access violations'
},
excludePaths: {
type: 'array',
items: { type: 'string' },
default: ['.git', 'node_modules', 'dist', 'build'],
description: 'Paths to exclude from scanning'
},
includeWarnings: {
type: 'boolean',
default: true,
description: 'Include warnings for potential violations'
},
includeSuggestions: {
type: 'boolean',
default: true,
description: 'Include suggestions for proper MCP tool usage'
}
},
required: [],
additionalProperties: false
},
async execute(input, context) {
try {
if (!securityScanner) {
const { ConfigManager } = await import('../../config/config-manager.js');
securityScanner = new SecurityScanner(new ConfigManager());
}
const accessViolations = await securityScanner.checkDataAccess({
scanPath: input.scanPath || '.',
excludePaths: input.excludePaths || ['.git', 'node_modules', 'dist', 'build'],
includeWarnings: input.includeWarnings !== false,
includeSuggestions: input.includeSuggestions !== false
});
// Log security event if violations found
if (accessViolations.length > 0) {
await context.db.run(`INSERT INTO security_events
(id, event_type, tool_name, user_id, context, risk_level, details, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
randomUUID(),
'data_access_violation',
'check_data_access',
context.userId || 'system',
JSON.stringify({ projectId: context.projectId }),
'high',
JSON.stringify({
violationCount: accessViolations.length,
types: [...new Set(accessViolations.map((v) => v.type))]
}),
Date.now()
]);
}
return createSuccessResult({
violations: accessViolations,
scanCompleted: true
});
}
catch (error) {
return createErrorResult({
code: 'EXECUTION_ERROR',
message: `Data access check failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
category: 'execution'
});
}
}
});
/**
* Setup security management tools
*/
export async function setupSecurityTools() {
return {
module: 'security',
tools: [
getSecurityStatusTool,
getSecurityEventsTool,
configureSecurityPolicyTool,
processSecurityApprovalTool,
securityScanTool,
checkSecretsTool,
vulnerabilityCheckTool,
setupSecurityConfigTool,
generateSecurityReportTool,
checkDataAccessTool
]
};
}
//# sourceMappingURL=tools.js.map