/**
* Check Security Tool
* Security-focused validation for Magento code.
*/
import { INSECURE_FUNCTIONS } from '../knowledge/index.js';
export interface SecurityIssue {
severity: 'critical' | 'high' | 'medium';
line?: number;
message: string;
rule: string;
recommendation: string;
}
export interface SecurityResult {
secure: boolean;
summary: {
critical: number;
high: number;
medium: number;
};
issues: {
critical: SecurityIssue[];
high: SecurityIssue[];
medium: SecurityIssue[];
};
recommendations: string[];
}
/**
* Check code for security issues
*/
export function checkSecurity(code: string): SecurityResult {
const issues: {
critical: SecurityIssue[];
high: SecurityIssue[];
medium: SecurityIssue[];
} = {
critical: [],
high: [],
medium: []
};
const lines = code.split('\n');
// CRITICAL: Check for insecure functions
for (const [func, info] of Object.entries(INSECURE_FUNCTIONS)) {
const regex = new RegExp(`\\b${func}\\s*\\(`, 'gi');
lines.forEach((line, index) => {
if (regex.test(line)) {
issues.critical.push({
severity: 'critical',
line: index + 1,
message: `Insecure function '${func}' detected: ${info.reason}`,
rule: 'Magento2.Security.InsecureFunction',
recommendation: info.replacement
? `Use ${info.replacement} instead`
: 'Remove this function call entirely'
});
}
});
}
// CRITICAL: Check for eval
lines.forEach((line, index) => {
if (/\beval\s*\(/i.test(line)) {
issues.critical.push({
severity: 'critical',
line: index + 1,
message: 'eval() function detected - critical security vulnerability',
rule: 'Squiz.PHP.Eval',
recommendation: 'Never use eval(). Refactor to avoid dynamic code execution.'
});
}
});
// CRITICAL: Check for backticks (shell execution)
lines.forEach((line, index) => {
if (/`[^`]+`/.test(line) && !line.trim().startsWith('//') && !line.trim().startsWith('*')) {
issues.critical.push({
severity: 'critical',
line: index + 1,
message: 'Backtick operator detected - executes shell commands',
rule: 'Magento2.Security.LanguageConstruct',
recommendation: 'Remove backtick operator. Use Magento\\Framework\\Shell if shell access is needed.'
});
}
});
// HIGH: Check for unescaped output in templates
if (code.includes('<?=') || code.includes('<?php echo')) {
const echoPattern = /<\?=\s*([^?]+)\?>|<\?php\s+echo\s+([^;]+);/gi;
let match;
while ((match = echoPattern.exec(code)) !== null) {
const output = match[1] || match[2];
if (!/escape|@noEscape|getJsLayout|count\s*\(/i.test(output)) {
const lineNum = code.substring(0, match.index).split('\n').length;
issues.high.push({
severity: 'high',
line: lineNum,
message: 'Potentially unescaped output - XSS vulnerability risk',
rule: 'Magento2.Security.XssTemplate',
recommendation: 'Use $escaper->escapeHtml(), escapeUrl(), or escapeJs()'
});
}
}
}
// HIGH: Check for raw SQL queries
lines.forEach((line, index) => {
if (!line.trim().startsWith('//') && !line.trim().startsWith('*')) {
if (/\$\w+\s*->\s*query\s*\(/i.test(line)) {
issues.high.push({
severity: 'high',
line: index + 1,
message: 'Direct database query detected - SQL injection risk',
rule: 'Magento2.SQL.RawQuery',
recommendation: 'Use repositories, collections, or prepared statements'
});
}
if (/\$\w+\s*\.\s*['"].*SELECT.*FROM/i.test(line)) {
issues.high.push({
severity: 'high',
line: index + 1,
message: 'SQL query string concatenation detected - SQL injection risk',
rule: 'Magento2.SQL.RawQuery',
recommendation: 'Use query builder with parameter binding'
});
}
}
});
// HIGH: Check for superglobal usage
const superglobals = ['$_GET', '$_POST', '$_REQUEST', '$_COOKIE', '$_SERVER', '$_FILES', '$_SESSION'];
for (const sg of superglobals) {
lines.forEach((line, index) => {
if (line.includes(sg)) {
issues.high.push({
severity: 'high',
line: index + 1,
message: `Direct superglobal ${sg} access detected`,
rule: 'Magento2.Security.Superglobal',
recommendation: 'Use Magento request object: $this->getRequest()->getParam()'
});
}
});
}
// MEDIUM: Check for include/require with variables
lines.forEach((line, index) => {
if (/\b(include|require|include_once|require_once)\s*\(\s*\$/.test(line)) {
issues.medium.push({
severity: 'medium',
line: index + 1,
message: 'Dynamic file inclusion detected - potential LFI vulnerability',
rule: 'Magento2.Security.IncludeFile',
recommendation: 'Avoid dynamic paths in include/require. Use autoloading.'
});
}
});
// MEDIUM: Check for preg_replace with 'e' modifier
lines.forEach((line, index) => {
if (/preg_replace\s*\(\s*['"].*\/.*e['"]/i.test(line)) {
issues.medium.push({
severity: 'medium',
line: index + 1,
message: 'preg_replace with /e modifier detected - code execution risk',
rule: 'Magento2.Strings.ExecutableRegEx',
recommendation: 'Use preg_replace_callback() instead'
});
}
});
// MEDIUM: Check for ObjectManager usage
lines.forEach((line, index) => {
if (/ObjectManager\s*::\s*getInstance/i.test(line)) {
issues.medium.push({
severity: 'medium',
line: index + 1,
message: 'Direct ObjectManager usage bypasses dependency injection',
rule: 'Magento2.Classes.DiscouragedDependencies',
recommendation: 'Use constructor dependency injection instead'
});
}
});
// Generate recommendations
const recommendations: string[] = [];
if (issues.critical.length > 0) {
recommendations.push('URGENT: Remove all insecure functions immediately');
}
if (issues.high.some(i => i.rule.includes('XssTemplate'))) {
recommendations.push('Escape all output using $escaper->escapeHtml() or appropriate escape method');
}
if (issues.high.some(i => i.rule.includes('SQL'))) {
recommendations.push('Replace raw SQL with repositories, collections, or query builder');
}
if (issues.high.some(i => i.rule.includes('Superglobal'))) {
recommendations.push('Use Magento request object instead of superglobals');
}
if (issues.medium.length > 0) {
recommendations.push('Review and address medium-severity issues for defense in depth');
}
if (recommendations.length === 0) {
recommendations.push('No security issues detected. Continue following Magento security best practices.');
}
return {
secure: issues.critical.length === 0 && issues.high.length === 0,
summary: {
critical: issues.critical.length,
high: issues.high.length,
medium: issues.medium.length
},
issues,
recommendations
};
}