import { maskXmlNonCode, splitLines } from '../../../shared/helpers/index.js';
import { criarOcorrencia } from '../../../types/index.js';
export const detectorXmlSecurity = {
    nome: 'detector-xml-security',
    categoria: 'markup',
    descricao: 'Detecta vulnerabilidades de segurança em XML',
    test: (relPath) => /\.xml$/i.test(relPath),
    aplicar: (src, relPath) => {
        if (!src)
            return [];
        const ocorrencias = [];
        const scan = maskXmlNonCode(src);
        const linhas = splitLines(scan);
        linhas.forEach((linha, index) => {
            const numeroLinha = index + 1;
            if (/<!DOCTYPE\b/i.test(linha)) {
                ocorrencias.push(criarOcorrencia({
                    tipo: 'xml-doctype',
                    nivel: 'aviso',
                    mensagem: 'DOCTYPE detectado - potencial risco XXE',
                    relPath,
                    linha: numeroLinha,
                    sugestao: 'Desabilite DOCTYPE no parser XML'
                }));
                if (/\b(SYSTEM|PUBLIC)\b/i.test(linha)) {
                    ocorrencias.push(criarOcorrencia({
                        tipo: 'xml-external-doctype',
                        nivel: 'erro',
                        mensagem: 'DOCTYPE com entidade externa - risco XXE alto',
                        relPath,
                        linha: numeroLinha,
                        sugestao: 'Remova entidades externas do DOCTYPE'
                    }));
                }
            }
            if (/<!ENTITY\b/i.test(linha)) {
                const hasExternal = /\b(SYSTEM|PUBLIC)\b/i.test(linha);
                ocorrencias.push(criarOcorrencia({
                    tipo: 'xml-entity',
                    nivel: hasExternal ? 'erro' : 'aviso',
                    mensagem: `Entidade XML detectada${hasExternal ? ' externa' : ''}`,
                    relPath,
                    linha: numeroLinha,
                    sugestao: 'Desabilite entidades no parser XML'
                }));
            }
            if (/<\s*(?:xi|xinclude):include\b/i.test(linha)) {
                ocorrencias.push(criarOcorrencia({
                    tipo: 'xml-xinclude',
                    nivel: 'aviso',
                    mensagem: 'XInclude detectado - carregamento externo',
                    relPath,
                    linha: numeroLinha,
                    sugestao: 'Desabilite XInclude se não for necessário'
                }));
            }
            if (/=\s*['"]\s*<!\[CDATA\[[\s\S]*?\]\]>\s*['"]/i.test(linha)) {
                ocorrencias.push(criarOcorrencia({
                    tipo: 'xml-cdata-in-attribute',
                    nivel: 'erro',
                    mensagem: 'CDATA em atributo - XML inválido',
                    relPath,
                    linha: numeroLinha,
                    sugestao: 'CDATA só é válido em conteúdo de elementos'
                }));
            }
        });
        const declaredNs = new Set();
        for (const metrica of scan.matchAll(/xmlns(?::([a-zA-Z_][\w.-]*))?\s*=\s*['"][^'"]*['"]/g)) {
            if (metrica[1])
                declaredNs.add(metrica[1]);
        }
        for (const metrica of scan.matchAll(/([a-zA-Z_][\w.-]*):[a-zA-Z_][\w.-]*/g)) {
            const prefix = metrica[1];
            if (!declaredNs.has(prefix) && prefix !== 'xml' && prefix !== 'xmlns') {
                ocorrencias.push(criarOcorrencia({
                    tipo: 'xml-undeclared-namespace',
                    nivel: 'aviso',
                    mensagem: `Namespace '${prefix}' não declarado`,
                    relPath,
                    linha: 1,
                    sugestao: `Declare xmlns:${prefix}="..."`
                }));
            }
        }
        return ocorrencias;
    }
};
//# sourceMappingURL=detector-xml-security.js.map