UNPKG

security-review-mcp-tool

Version:

Servidor MCP para revisão de segurança de código

395 lines (387 loc) 15.8 kB
/** * 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