security-review-mcp-tool
Version:
Servidor MCP para revisão de segurança de código
395 lines (387 loc) • 15.8 kB
JavaScript
/**
* Módulo responsável pela análise de segurança de código.
* Implementa verificações para identificar vulnerabilidades comuns.
*/
/**
* Padrões de vulnerabilidades a serem detectados em diferentes linguagens
*/
const PADROES_VULNERABILIDADES = {
global: {
// Vulnerabilidades genéricas em qualquer linguagem
senhasHardcoded: [
/password\s*=\s*['"][^'"]+['"]/i,
/senha\s*=\s*['"][^'"]+['"]/i,
/api[_-]?key\s*=\s*['"][^'"]+['"]/i,
/secret\s*=\s*['"][^'"]+['"]/i
],
comentariosSensitivos: [
/\/\/\s*TODO\s*:/i,
/\/\/\s*FIXME\s*:/i,
/\/\*\s*TODO\s*:/i,
/\/\*\s*FIXME\s*:/i,
/<!--\s*TODO\s*:/i
]
},
javascript: {
injecaoSQL: [
/\bexec\s*\(\s*["'`][^"'`]*\$\{/i,
/\bquery\s*\(\s*["'`][^"'`]*\$\{/i
],
xss: [
/innerHTML\s*=/i,
/document\.write\s*\(/i
],
eval: [
/\beval\s*\(/i,
/new\s+Function\s*\(/i,
/setTimeout\s*\(\s*['"`]/i,
/setInterval\s*\(\s*['"`]/i
],
prototype: [
/\.__proto__/i,
/\.prototype\./i
]
},
typescript: {
// TypeScript herda os padrões de JavaScript
typeAny: [
/:\s*any/i
],
unsafeAssertion: [
/as\s+any/i,
/\!\w+/i // Non-null assertion
]
},
php: {
injecaoSQL: [
/mysql_query\s*\(\s*['"]/i,
/\$_GET|\$_POST|\$_REQUEST/i
],
execucaoComando: [
/\bexec\s*\(/i,
/\bshell_exec\s*\(/i,
/\bsystem\s*\(/i,
/\bpassthru\s*\(/i,
/\beval\s*\(/i
]
},
python: {
execucaoComando: [
/\bexec\s*\(/i,
/\beval\s*\(/i,
/\bos\.system\s*\(/i,
/\bos\.popen\s*\(/i,
/\bsubprocess\.call\s*\(/i,
/\bsubprocess\.Popen\s*\(/i
],
injecaoSQL: [
/\bcursor\.execute\s*\([^,)]*\+/i,
/\bcursor\.executemany\s*\([^,)]*\+/i
],
pickle: [
/\bpickle\.loads\s*\(/i,
/\bunpickle\s*\(/i
]
},
java: {
injecaoSQL: [
/executeQuery\s*\([^)]*\+/i,
/executeUpdate\s*\([^)]*\+/i,
/prepareStatement\s*\([^)]*\+/i
],
execucaoComando: [
/Runtime\.getRuntime\(\)\.exec\s*\(/i,
/ProcessBuilder\s*\(/i
],
serialization: [
/Serializable/i,
/readObject\s*\(/i,
/writeObject\s*\(/i
]
},
csharp: {
injecaoSQL: [
/SqlCommand\s*\([^)]*\+/i,
/ExecuteReader\s*\(/i,
/ExecuteNonQuery\s*\(/i
],
deserializacao: [
/BinaryFormatter\.Deserialize/i,
/JsonConvert\.DeserializeObject/i,
/XmlSerializer\.Deserialize/i
],
processStart: [
/Process\.Start\s*\(/i,
/ProcessStartInfo/i
]
}
};
/**
* Recomendações para mitigar vulnerabilidades detectadas
*/
const RECOMENDACOES = {
senhasHardcoded: "Nunca armazene senhas ou chaves API diretamente no código. Use variáveis de ambiente ou um serviço seguro de gerenciamento de segredos.",
comentariosSensitivos: "Remova comentários TODO/FIXME antes de enviar código para produção, especialmente se contiverem informações sensíveis.",
injecaoSQL: "Use consultas parametrizadas ou ORM para prevenir injeção SQL. Nunca concatene strings diretamente em consultas SQL.",
xss: "Use métodos seguros como textContent em vez de innerHTML. Considere frameworks que escapam automaticamente ou bibliotecas de sanitização como DOMPurify.",
eval: "Evite usar eval() ou construções similares. Busque alternativas mais seguras e específicas para a funcionalidade desejada.",
prototype: "Manipulações de prototype podem introduzir vulnerabilidades. Considere abordagens mais seguras como Object.create ou classes ES6.",
typeAny: "Evite o tipo 'any' em TypeScript. Use tipos mais específicos ou 'unknown' seguido de type guards apropriados.",
unsafeAssertion: "Evite asserções de tipo inseguras (as any) e operadores de não-nulidade (!). Use verificações de tipo apropriadas.",
execucaoComando: "Evite executar comandos do sistema operacional. Se necessário, valide rigorosamente todas as entradas e use listas de permissão.",
pickle: "Evite desserializar dados não confiáveis com pickle. Use formatos como JSON com validação adequada.",
serialization: "Implemente verificações de segurança ao desserializar dados, como filtragem de classes permitidas.",
deserializacao: "Implemente validações rigorosas antes da desserialização. Use formatos mais seguros quando possível.",
processStart: "Valide rigorosamente todas as entradas antes de iniciar processos. Evite usar entrada do usuário como parte do comando."
};
/**
* Analisa código em busca de vulnerabilidades de segurança
*
* @param codigo - O código fonte a ser analisado
* @param linguagem - A linguagem de programação (opcional)
* @param nivelDetalhe - O nível de detalhe da análise
* @returns Uma string formatada com os resultados da análise
*/
export async function analisarSegurancaCodigo(codigo, linguagem, nivelDetalhe = "medio") {
// Determinar linguagem baseado no conteúdo se não for fornecida
const linguagemDetectada = linguagem?.toLowerCase() || detectarLinguagem(codigo);
// Coletar vulnerabilidades
const vulnerabilidades = detectarVulnerabilidades(codigo, linguagemDetectada);
// Formatar resultados de acordo com o nível de detalhe solicitado
return formatarResultadoAnalise(vulnerabilidades, linguagemDetectada, nivelDetalhe);
}
/**
* Tenta detectar a linguagem de programação do código
*/
function detectarLinguagem(codigo) {
// Detecção simplificada baseada em padrões comuns
if (codigo.includes("import React") || codigo.includes("useState") || /function\s+\w+\s*\(/.test(codigo)) {
return "javascript";
}
else if (codigo.includes(": string") || codigo.includes(": number") || codigo.includes("interface ")) {
return "typescript";
}
else if (codigo.includes("<?php") || codigo.includes("$_GET") || codigo.includes("$_POST")) {
return "php";
}
else if (codigo.includes("def ") || codigo.includes("import ") && !codigo.includes(";")) {
return "python";
}
else if (codigo.includes("public class") || codigo.includes("private void")) {
return "java";
}
else if (codigo.includes("public static void") || codigo.includes("namespace ")) {
return "csharp";
}
return "desconhecida";
}
/**
* Detecta vulnerabilidades no código com base nos padrões definidos
*/
function detectarVulnerabilidades(codigo, linguagem) {
const resultado = {};
const linhas = codigo.split('\n');
// Verificar padrões globais aplicáveis a qualquer linguagem
for (const [categoria, padroes] of Object.entries(PADROES_VULNERABILIDADES.global)) {
resultado[categoria] = [];
for (const padrao of padroes) {
linhas.forEach((linha, indice) => {
if (padrao.test(linha)) {
resultado[categoria].push({
linha: indice + 1,
trecho: linha.trim()
});
}
});
}
if (resultado[categoria].length === 0) {
delete resultado[categoria];
}
}
// Verificar padrões específicos da linguagem
if (linguagem !== "desconhecida" && PADROES_VULNERABILIDADES[linguagem]) {
for (const [categoria, padroes] of Object.entries(PADROES_VULNERABILIDADES[linguagem])) {
resultado[categoria] = [];
for (const padrao of padroes) {
linhas.forEach((linha, indice) => {
if (padrao.test(linha)) {
resultado[categoria].push({
linha: indice + 1,
trecho: linha.trim()
});
}
});
}
if (resultado[categoria].length === 0) {
delete resultado[categoria];
}
}
}
// Verificar padrões JavaScript em TypeScript também
if (linguagem === "typescript") {
for (const [categoria, padroes] of Object.entries(PADROES_VULNERABILIDADES.javascript)) {
resultado[categoria] = resultado[categoria] || [];
for (const padrao of padroes) {
linhas.forEach((linha, indice) => {
if (padrao.test(linha)) {
resultado[categoria].push({
linha: indice + 1,
trecho: linha.trim()
});
}
});
}
if (resultado[categoria].length === 0) {
delete resultado[categoria];
}
}
}
return resultado;
}
/**
* Formata os resultados da análise de acordo com o nível de detalhe
*/
function formatarResultadoAnalise(vulnerabilidades, linguagem, nivelDetalhe) {
const categorias = Object.keys(vulnerabilidades);
if (categorias.length === 0) {
return "✅ Nenhuma vulnerabilidade óbvia detectada no código analisado.";
}
let resultado = `# Relatório de Segurança para Código ${linguagem !== "desconhecida" ? linguagem.toUpperCase() : ""}\n\n`;
// Resumo
resultado += `## Resumo\n\n`;
resultado += `🔍 Linguagem detectada: ${linguagem !== "desconhecida" ? linguagem.toUpperCase() : "Não identificada"}\n`;
resultado += `⚠️ Total de categorias de vulnerabilidades: ${categorias.length}\n`;
const totalOcorrencias = categorias.reduce((total, categoria) => total + vulnerabilidades[categoria].length, 0);
resultado += `🚨 Total de ocorrências detectadas: ${totalOcorrencias}\n\n`;
// Vulnerabilidades por categoria
resultado += `## Vulnerabilidades Detectadas\n\n`;
categorias.forEach(categoria => {
const ocorrencias = vulnerabilidades[categoria];
resultado += `### ${formatarCategoria(categoria)} (${ocorrencias.length} ocorrências)\n\n`;
// Adicionar recomendação
if (RECOMENDACOES[categoria]) {
resultado += `**Recomendação:** ${RECOMENDACOES[categoria]}\n\n`;
}
// Se o nível for diferente de "baixo", adicionar detalhes das ocorrências
if (nivelDetalhe !== "baixo") {
resultado += `**Ocorrências:**\n\n`;
ocorrencias.forEach(({ linha, trecho }) => {
resultado += `- Linha ${linha}: \`${trecho}\`\n`;
});
resultado += "\n";
}
// Se o nível for "alto", adicionar exemplos de código corrigido para algumas categorias comuns
if (nivelDetalhe === "alto") {
const codigoCorrigido = gerarExemploCorrigido(categoria, linguagem);
if (codigoCorrigido) {
resultado += `**Exemplo de código corrigido:**\n\n\`\`\`${linguagem}\n${codigoCorrigido}\n\`\`\`\n\n`;
}
}
});
// Recursos adicionais
if (nivelDetalhe === "alto") {
resultado += `## Recursos Adicionais\n\n`;
resultado += `- [OWASP Top Ten](https://owasp.org/www-project-top-ten/)\n`;
resultado += `- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)\n`;
if (linguagem === "javascript" || linguagem === "typescript") {
resultado += `- [NodeJS Security Best Practices](https://github.com/goldbergyoni/nodebestpractices#6-security-best-practices)\n`;
}
else if (linguagem === "python") {
resultado += `- [Python Security Best Practices](https://python-security.readthedocs.io/)\n`;
}
else if (linguagem === "php") {
resultado += `- [PHP Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/PHP_Security_Cheat_Sheet.html)\n`;
}
}
return resultado;
}
/**
* Formata o nome da categoria para exibição
*/
function formatarCategoria(categoria) {
switch (categoria) {
case "senhasHardcoded": return "Senhas Hardcoded";
case "comentariosSensitivos": return "Comentários Sensíveis";
case "injecaoSQL": return "Injeção SQL";
case "xss": return "Cross-Site Scripting (XSS)";
case "eval": return "Uso de eval() ou Similar";
case "prototype": return "Manipulação Insegura de Prototype";
case "typeAny": return "Uso de 'any' em TypeScript";
case "unsafeAssertion": return "Asserções de Tipo Inseguras";
case "execucaoComando": return "Execução de Comandos do Sistema";
case "pickle": return "Uso Inseguro de Pickle";
case "serialization": return "Serialização/Desserialização Insegura";
case "deserializacao": return "Desserialização Insegura";
case "processStart": return "Inicialização de Processos Insegura";
default: return categoria.charAt(0).toUpperCase() + categoria.slice(1);
}
}
/**
* Gera exemplos de código corrigido para categorias comuns
*/
function gerarExemploCorrigido(categoria, linguagem) {
if (categoria === "injecaoSQL") {
if (linguagem === "javascript" || linguagem === "typescript") {
return `// Código vulnerável:
const query = "SELECT * FROM usuarios WHERE nome = '" + nome + "'";
// Código corrigido (usando prepared statements):
const query = "SELECT * FROM usuarios WHERE nome = ?";
db.query(query, [nome]);`;
}
else if (linguagem === "python") {
return `# Código vulnerável:
cursor.execute("SELECT * FROM usuarios WHERE nome = '" + nome + "'")
# Código corrigido:
cursor.execute("SELECT * FROM usuarios WHERE nome = %s", (nome,))`;
}
else if (linguagem === "php") {
return `// Código vulnerável:
$query = "SELECT * FROM usuarios WHERE nome = '" . $nome . "'";
// Código corrigido:
$stmt = $pdo->prepare("SELECT * FROM usuarios WHERE nome = ?");
$stmt->execute([$nome]);`;
}
}
else if (categoria === "xss") {
if (linguagem === "javascript" || linguagem === "typescript") {
return `// Código vulnerável:
element.innerHTML = userInput;
// Código corrigido:
element.textContent = userInput;
// Ou, se precisar de HTML:
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);`;
}
}
else if (categoria === "senhasHardcoded") {
if (linguagem === "javascript" || linguagem === "typescript") {
return `// Código vulnerável:
const API_KEY = "1234567890abcdef";
// Código corrigido:
const API_KEY = process.env.API_KEY;`;
}
else if (linguagem === "python") {
return `# Código vulnerável:
API_KEY = "1234567890abcdef"
# Código corrigido:
import os
API_KEY = os.environ.get("API_KEY")`;
}
}
else if (categoria === "eval") {
if (linguagem === "javascript" || linguagem === "typescript") {
return `// Código vulnerável:
eval(userInput);
// Código corrigido:
// Evite eval completamente. Por exemplo, para converter JSON:
try {
const data = JSON.parse(userInput);
// Use data
} catch (error) {
// Trate erros de parsing
}`;
}
}
return null;
}
//# sourceMappingURL=security-analyzer.js.map