tutanus 0.12.7 → 0.12.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysts/corrections/analyst-quick-fixes.d.ts.map +1 -1
- package/dist/analysts/corrections/analyst-quick-fixes.js +0 -1
- package/dist/analysts/corrections/analyst-quick-fixes.js.map +1 -1
- package/dist/analysts/corrections/analyst-scoring.d.ts.map +1 -1
- package/dist/analysts/corrections/analyst-scoring.js +0 -1
- package/dist/analysts/corrections/analyst-scoring.js.map +1 -1
- package/dist/analysts/github-actions/analysts/analyst-github-actions.d.ts.map +1 -1
- package/dist/analysts/github-actions/analysts/analyst-github-actions.js +1 -1
- package/dist/analysts/github-actions/analysts/analyst-github-actions.js.map +1 -1
- package/dist/analysts/github-actions/detectors/detector-dependencies-vulnerable.d.ts.map +1 -1
- package/dist/analysts/github-actions/detectors/detector-dependencies-vulnerable.js +1 -1
- package/dist/analysts/github-actions/detectors/detector-dependencies-vulnerable.js.map +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.d.ts.map +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js.map +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-security.d.ts.map +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-security.js +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-security.js.map +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.d.ts.map +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js +1 -1
- package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js.map +1 -1
- package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.d.ts.map +1 -1
- package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js +1 -1
- package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js.map +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-performance.d.ts.map +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-performance.js +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-performance.js.map +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-security.d.ts.map +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-security.js +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-security.js.map +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.d.ts.map +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js +1 -1
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js.map +1 -1
- package/dist/analysts/html/analysts/analyst-html.d.ts +2 -4
- package/dist/analysts/html/analysts/analyst-html.d.ts.map +1 -1
- package/dist/analysts/html/analysts/analyst-html.js.map +1 -1
- package/dist/analysts/react/corrections/correction-react.js.map +1 -1
- package/dist/analysts/shell/analysts/analyst-shell.d.ts.map +1 -1
- package/dist/analysts/shell/analysts/analyst-shell.js.map +1 -1
- package/dist/app/github/app/check-run-builder.d.ts +1 -11
- package/dist/app/github/app/check-run-builder.d.ts.map +1 -1
- package/dist/app/github/app/check-run-builder.js.map +1 -1
- package/dist/app/github/app/check-suite-handler.js.map +1 -1
- package/dist/app/github/app/seguranca.d.ts +9 -0
- package/dist/app/github/app/seguranca.d.ts.map +1 -0
- package/dist/app/github/app/seguranca.js +58 -0
- package/dist/app/github/app/seguranca.js.map +1 -0
- package/dist/app/github/app/server.d.ts.map +1 -1
- package/dist/app/github/app/server.js +19 -3
- package/dist/app/github/app/server.js.map +1 -1
- package/dist/app/github/app/workflow-reader.d.ts +1 -14
- package/dist/app/github/app/workflow-reader.d.ts.map +1 -1
- package/dist/app/github/app/workflow-reader.js.map +1 -1
- package/dist/app/github/dashboard/routes.d.ts.map +1 -1
- package/dist/app/github/dashboard/routes.js +15 -8
- package/dist/app/github/dashboard/routes.js.map +1 -1
- package/dist/app/github/push-analysis/report-helpers.d.ts +1 -19
- package/dist/app/github/push-analysis/report-helpers.d.ts.map +1 -1
- package/dist/app/github/push-analysis/report-helpers.js.map +1 -1
- package/dist/core/config/excludes-padrao.d.ts.map +1 -1
- package/dist/core/config/excludes-padrao.js.map +1 -1
- package/dist/core/messages/en/analysts/index.d.ts +1 -1
- package/dist/core/messages/en/analysts/index.d.ts.map +1 -1
- package/dist/core/messages/en/analysts/index.js +1 -1
- package/dist/core/messages/en/analysts/index.js.map +1 -1
- package/dist/core/messages/en/github/github-app-messages.d.ts +3 -0
- package/dist/core/messages/en/github/github-app-messages.d.ts.map +1 -1
- package/dist/core/messages/en/github/github-app-messages.js +3 -0
- package/dist/core/messages/en/github/github-app-messages.js.map +1 -1
- package/dist/core/messages/en/guardian/guardian-messages.d.ts +1 -0
- package/dist/core/messages/en/guardian/guardian-messages.d.ts.map +1 -1
- package/dist/core/messages/en/guardian/guardian-messages.js +1 -0
- package/dist/core/messages/en/guardian/guardian-messages.js.map +1 -1
- package/dist/core/messages/en/reports/report-messages.d.ts.map +1 -1
- package/dist/core/messages/en/reports/report-messages.js.map +1 -1
- package/dist/core/messages/ja/analysts/index.d.ts +1 -1
- package/dist/core/messages/ja/analysts/index.d.ts.map +1 -1
- package/dist/core/messages/ja/analysts/index.js +1 -1
- package/dist/core/messages/ja/analysts/index.js.map +1 -1
- package/dist/core/messages/ja/github/github-app-messages.d.ts +3 -0
- package/dist/core/messages/ja/github/github-app-messages.d.ts.map +1 -1
- package/dist/core/messages/ja/github/github-app-messages.js +3 -0
- package/dist/core/messages/ja/github/github-app-messages.js.map +1 -1
- package/dist/core/messages/ja/guardian/guardian-messages.d.ts +1 -0
- package/dist/core/messages/ja/guardian/guardian-messages.d.ts.map +1 -1
- package/dist/core/messages/ja/guardian/guardian-messages.js +1 -0
- package/dist/core/messages/ja/guardian/guardian-messages.js.map +1 -1
- package/dist/core/messages/ja/reports/report-messages.d.ts.map +1 -1
- package/dist/core/messages/ja/reports/report-messages.js.map +1 -1
- package/dist/core/messages/pt/analysts/index.d.ts +1 -1
- package/dist/core/messages/pt/analysts/index.d.ts.map +1 -1
- package/dist/core/messages/pt/analysts/index.js +1 -1
- package/dist/core/messages/pt/analysts/index.js.map +1 -1
- package/dist/core/messages/pt/github/github-app-messages.d.ts +3 -0
- package/dist/core/messages/pt/github/github-app-messages.d.ts.map +1 -1
- package/dist/core/messages/pt/github/github-app-messages.js +3 -0
- package/dist/core/messages/pt/github/github-app-messages.js.map +1 -1
- package/dist/core/messages/pt/guardian/guardian-messages.d.ts +1 -0
- package/dist/core/messages/pt/guardian/guardian-messages.d.ts.map +1 -1
- package/dist/core/messages/pt/guardian/guardian-messages.js +1 -0
- package/dist/core/messages/pt/guardian/guardian-messages.js.map +1 -1
- package/dist/core/messages/pt/reports/report-messages.d.ts.map +1 -1
- package/dist/core/messages/pt/reports/report-messages.js.map +1 -1
- package/dist/core/messages/zh/analysts/index.d.ts +1 -1
- package/dist/core/messages/zh/analysts/index.d.ts.map +1 -1
- package/dist/core/messages/zh/analysts/index.js +1 -1
- package/dist/core/messages/zh/analysts/index.js.map +1 -1
- package/dist/core/messages/zh/github/github-app-messages.d.ts +3 -0
- package/dist/core/messages/zh/github/github-app-messages.d.ts.map +1 -1
- package/dist/core/messages/zh/github/github-app-messages.js +3 -0
- package/dist/core/messages/zh/github/github-app-messages.js.map +1 -1
- package/dist/core/messages/zh/guardian/guardian-messages.d.ts +1 -0
- package/dist/core/messages/zh/guardian/guardian-messages.d.ts.map +1 -1
- package/dist/core/messages/zh/guardian/guardian-messages.js +1 -0
- package/dist/core/messages/zh/guardian/guardian-messages.js.map +1 -1
- package/dist/core/messages/zh/reports/report-messages.d.ts.map +1 -1
- package/dist/core/messages/zh/reports/report-messages.js.map +1 -1
- package/dist/core/workers/worker-executor.js +1 -1
- package/dist/core/workers/worker-executor.js.map +1 -1
- package/dist/guardian/gpg.d.ts +1 -4
- package/dist/guardian/gpg.d.ts.map +1 -1
- package/dist/guardian/gpg.js +3 -0
- package/dist/guardian/gpg.js.map +1 -1
- package/dist/reports/report-structure.d.ts.map +1 -1
- package/dist/reports/report-structure.js.map +1 -1
- package/dist/shared/persistence/persistence.js.map +1 -1
- package/dist/types/analysts/html.d.ts +4 -0
- package/dist/types/analysts/html.d.ts.map +1 -0
- package/dist/types/analysts/html.js +2 -0
- package/dist/types/analysts/html.js.map +1 -0
- package/dist/types/analysts/index.d.ts +1 -0
- package/dist/types/analysts/index.d.ts.map +1 -1
- package/dist/types/analysts/index.js +1 -0
- package/dist/types/analysts/index.js.map +1 -1
- package/dist/types/github/app.d.ts +42 -0
- package/dist/types/github/app.d.ts.map +1 -1
- package/dist/types/github/app.js.map +1 -1
- package/dist/types/guardian/integrity.d.ts +4 -0
- package/dist/types/guardian/integrity.d.ts.map +1 -1
- package/dist/types/guardian/integrity.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/package.json +3 -1
- package/out/404/index.html +0 -1
- package/out/404.html +0 -1
- package/out/__next.__PAGE__.txt +0 -9
- package/out/__next._full.txt +0 -18
- package/out/__next._head.txt +0 -5
- package/out/__next._index.txt +0 -6
- package/out/__next._tree.txt +0 -3
- package/out/_next/static/chunks/05-c3ty_6dwfk.js +0 -1
- package/out/_next/static/chunks/0cz1d0mv5g_q7.js +0 -1
- package/out/_next/static/chunks/1061ff024jzvu.js +0 -2
- package/out/_next/static/chunks/14mrh2-p_w84d.js +0 -1
- package/out/_next/static/chunks/15orcrkp-_9ct.js +0 -4
- package/out/_next/static/chunks/1jiobya7ette1.js +0 -11
- package/out/_next/static/chunks/1jq4o6yq14o4c.js +0 -31
- package/out/_next/static/chunks/1rxncug86bump.js +0 -1
- package/out/_next/static/chunks/2n-4qa9h44lgj.js +0 -1
- package/out/_next/static/chunks/3n7dm2ojtyzwn.js +0 -1
- package/out/_next/static/chunks/3uta7d_6k863-.css +0 -1
- package/out/_next/static/chunks/turbopack-2xb6mmb6_q43u.js +0 -1
- package/out/_next/static/media/icon-1.008jpsm4iakzh.png +0 -0
- package/out/_next/static/rSwWA0jiTeQUXZXHLMAZ1/_buildManifest.js +0 -11
- package/out/_next/static/rSwWA0jiTeQUXZXHLMAZ1/_clientMiddlewareManifest.js +0 -1
- package/out/_next/static/rSwWA0jiTeQUXZXHLMAZ1/_ssgManifest.js +0 -1
- package/out/_not-found/__next._full.txt +0 -16
- package/out/_not-found/__next._head.txt +0 -5
- package/out/_not-found/__next._index.txt +0 -6
- package/out/_not-found/__next._not-found.__PAGE__.txt +0 -5
- package/out/_not-found/__next._not-found.txt +0 -5
- package/out/_not-found/__next._tree.txt +0 -3
- package/out/_not-found/index.html +0 -1
- package/out/_not-found/index.txt +0 -16
- package/out/changelog/__next._full.txt +0 -573
- package/out/changelog/__next._head.txt +0 -5
- package/out/changelog/__next._index.txt +0 -6
- package/out/changelog/__next._tree.txt +0 -4
- package/out/changelog/__next.changelog.__PAGE__.txt +0 -560
- package/out/changelog/__next.changelog.txt +0 -5
- package/out/changelog/index.html +0 -550
- package/out/changelog/index.txt +0 -573
- package/out/github/dashboard/__next._full.txt +0 -20
- package/out/github/dashboard/__next._head.txt +0 -5
- package/out/github/dashboard/__next._index.txt +0 -6
- package/out/github/dashboard/__next._tree.txt +0 -3
- package/out/github/dashboard/__next.github.dashboard.__PAGE__.txt +0 -9
- package/out/github/dashboard/__next.github.dashboard.txt +0 -4
- package/out/github/dashboard/__next.github.txt +0 -5
- package/out/github/dashboard/index.html +0 -1
- package/out/github/dashboard/index.txt +0 -20
- package/out/index.html +0 -1
- package/out/index.txt +0 -18
- package/out/privacy-policy/__next._full.txt +0 -38
- package/out/privacy-policy/__next._head.txt +0 -5
- package/out/privacy-policy/__next._index.txt +0 -6
- package/out/privacy-policy/__next._tree.txt +0 -4
- package/out/privacy-policy/__next.privacy-policy.__PAGE__.txt +0 -23
- package/out/privacy-policy/__next.privacy-policy.txt +0 -5
- package/out/privacy-policy/index.html +0 -1
- package/out/privacy-policy/index.txt +0 -38
- package/out/terms-of-use/__next._full.txt +0 -37
- package/out/terms-of-use/__next._head.txt +0 -5
- package/out/terms-of-use/__next._index.txt +0 -6
- package/out/terms-of-use/__next._tree.txt +0 -4
- package/out/terms-of-use/__next.terms-of-use.__PAGE__.txt +0 -18
- package/out/terms-of-use/__next.terms-of-use.txt +0 -5
- package/out/terms-of-use/index.html +0 -1
- package/out/terms-of-use/index.txt +0 -37
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector-workflow-trigger-unsafe.js","sourceRoot":"","sources":["../../../../src/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * [BUSCA] Detector de Workflow Triggers Inseguros para GitHub Actions\n *\n * Detecta configurações de trigger perigosas em workflows:\n * - Push em branches protegidos (main, master, release/*) sem proteção\n * - Workflow_dispatch sem restrições\n * - Schedule em branches sensíveis\n * - Triggers amplos demais (push em wildcards)\n */\n\nimport { splitLines } from '@shared/helpers';\nimport { parseDocument } from 'yaml';\n\nimport type { Analista, Ocorrencia } from '@';\nimport { criarOcorrencia } from '@';\nimport { messages } from '@core/messages';\n\nconst BRANCHES_PROTEGIDOS = ['main', 'master', 'production', 'release', 'prod'];\n\n// Actions que modificam o estado do repositório (alta permissão)\nconst DANGEROUS_ACTIONS = ['actions/checkout', 'peter-evans/create-or-update-comment', 'peter-evans/create-pull-request', 'marocchino/sticky-pull-request', 'softprops/action-gh-release', 'ncipollo/release-action', 'docker/build-push-action', 'docker/login-action', 'docker/push-action', 'aws-actions/configure-aws-credentials', 'google-github-actions/auth', 'azure/login', 'hashicorp/vault-action'];\nexport const detectorWorkflowTriggerInseguro: Analista = {\n nome: 'detector-workflow-trigger-inseguro',\n categoria: 'workflows',\n descricao: 'Detecta triggers de workflow potencialmente inseguros',\n test: (relPath: string): boolean => /\\.github\\/workflows\\/.*\\.ya?ml$/i.test(relPath),\n aplicar: (src: string, relPath: string): Ocorrencia[] => {\n if (!src) return [];\n const ocorrencias: Ocorrencia[] = [];\n try {\n const doc = parseDocument(src);\n const workflow = doc.toJS();\n if (!workflow || typeof workflow !== 'object') return ocorrencias;\n const onConfig = workflow.on;\n if (!onConfig || typeof onConfig !== 'object') {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-ausente',\n nivel: 'info',\n mensagem: messages.AnalistaGithubActionsMensagens.workflowWithoutTrigger,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaGithubActionsMensagens.workflowWithoutTriggerSugestao\n }));\n return ocorrencias;\n }\n\n // --- 1. Push em branches protegidos ---\n if (onConfig.push) {\n const pushConf = onConfig.push;\n\n // Se push tem apenas tags, não é push em branches - é disparo por tag\n if (pushConf.tags && !pushConf.branches && !pushConf['branches-ignore']) {\n // Workflow disparado por tags, não por branches - não aplicar esta regra\n } else {\n const branches = typeof pushConf === 'object' && pushConf?.branches ? Array.isArray(pushConf.branches) ? pushConf.branches : [pushConf.branches] : typeof pushConf === 'object' && pushConf?.branches_ignore ? Array.isArray(pushConf.branches_ignore) ? pushConf.branches_ignore : [pushConf.branches_ignore] : undefined;\n\n // Detectar push sem filtro de branches (triggeria em todos os branches)\n if (typeof pushConf === 'object' && !pushConf.branches && !pushConf.branches_ignore && !pushConf.tags || Array.isArray(pushConf) || typeof pushConf === 'string') {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-push-sem-filtro',\n nivel: 'aviso',\n mensagem: 'Trigger push sem filtro de branches definido',\n relPath,\n linha: 1,\n sugestao: 'Defina branches específicos em on.push.branches para limitar onde o workflow é executado'\n }));\n }\n\n // Verificar se inclui branches protegidos sem paths filter\n if (branches) {\n const hasPathsFilter = !!(pushConf.paths || pushConf.paths_ignore || pushConf['paths-ignore'] || pushConf.pathsIgnore);\n if (!hasPathsFilter) {\n for (const branch of branches) {\n if (typeof branch === 'string' && BRANCHES_PROTEGIDOS.some(caminho => branch.toLowerCase() === caminho.toLowerCase() || new RegExp(`^${caminho.replace('/', '\\\\/')}`).test(branch))) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-push-branch-protegido',\n nivel: 'aviso',\n mensagem: `Trigger push configurado para branch protegido \"${branch}\" sem filtro de paths`,\n relPath,\n linha: 1,\n sugestao: 'Adicione filtros de paths (on.push.paths) para limitar quando o workflow é executado'\n }));\n }\n }\n }\n }\n }\n }\n\n // --- 2. Pull request sem verificação de branches ---\n if (onConfig.pull_request) {\n // Detectar pull_request_target\n if (onConfig.pull_request_target) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-pull-request-target',\n nivel: 'erro',\n mensagem: messages.AnalistaGithubActionsMensagens.pullRequestTargetGrantsWritePermissions,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaGithubActionsMensagens.pullRequestTargetGrantsWritePermissionsSugestao\n }));\n }\n }\n\n // --- 3. Workflow_dispatch sem inputs de validação ---\n if (onConfig.workflow_dispatch) {\n const dispatchConf = onConfig.workflow_dispatch;\n if (typeof dispatchConf === 'object' && dispatchConf.inputs) {\n const inputs = dispatchConf.inputs;\n for (const [_inputName, inputConfig] of Object.entries(inputs as Record<string, unknown>)) {\n const inputConf = inputConfig as Record<string, unknown> | undefined;\n if (inputConf && !inputConf.required) {\n // Não é erro, mas pode ser melhorado\n }\n }\n }\n // workflow_dispatch sem inputs de qualquer tipo é potencialmente perigoso\n if (typeof dispatchConf !== 'object' || !dispatchConf.inputs) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-workflow-dispatch-sem-inputs',\n nivel: 'info',\n mensagem: messages.AnalistaGithubActionsMensagens.workflowDispatchWithoutInputs,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaGithubActionsMensagens.workflowDispatchWithoutInputsSugestao\n }));\n }\n }\n\n // --- 4. Schedule em branches sensíveis ---\n if (onConfig.schedule) {\n const pushConf = onConfig.push;\n const targetBranches = typeof pushConf === 'object' && pushConf?.branches ? Array.isArray(pushConf.branches) ? pushConf.branches : [pushConf.branches] : undefined;\n if (targetBranches) {\n for (const branch of targetBranches) {\n if (typeof branch === 'string' && branch.toLowerCase() === 'production') {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-schedule-branch-sensivel',\n nivel: 'aviso',\n mensagem: 'Workflow com schedule direcionado para branch \"production\"',\n relPath,\n linha: 1,\n sugestao: 'Considere usar branches de staging para execuções agendadas'\n }));\n }\n }\n }\n }\n\n // --- 5. Triggers com wildcards excessivamente amplos ---\n const yamlRaw = src;\n if (/on:\\s*\\n\\s*push:\\s*\\n\\s*branches:\\s*\\n\\s*-\\s+'\\*\\*'/m.test(yamlRaw) || /on:\\s*\\n\\s*push:\\s*\\n\\s*branches:\\s*\\n\\s*-\\s+\"\\*\\*\"/m.test(yamlRaw)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-wildcard-amplo',\n nivel: 'info',\n mensagem: 'Trigger push com wildcard \"**\" em branches (captura todos os branches)',\n relPath,\n linha: 1,\n sugestao: 'Use padrões mais específicos para limitar os branches monitorados'\n }));\n }\n\n // --- 6. Verificar se workflow executa actions perigosas em triggers de push amplo ---\n if (onConfig.push && !onConfig.pull_request) {\n // Se push tem apenas tags, não é push em branches\n const isPushToTags = onConfig.push.tags && !onConfig.push.branches && !onConfig.push['branches-ignore'];\n if (!isPushToTags) {\n const linhas = splitLines(src);\n const hasDangerousAction = linhas.some(linha => {\n const usesMatch = linha.match(/uses:\\s*(.+)/);\n return usesMatch && DANGEROUS_ACTIONS.some(arquivo => linha.includes(arquivo));\n });\n const isPushToAllBranches = !onConfig.push.branches && !onConfig.push['branches-ignore'];\n if (isPushToAllBranches && hasDangerousAction) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-push-ampla-com-actions-perigosas',\n nivel: 'aviso',\n mensagem: 'Push sem restrição de branches executa actions que modificam estado do repositório',\n relPath,\n linha: 1,\n sugestao: 'Considere restringir push branches ou adicionar proteções (environment protection rules, approvals)'\n }));\n }\n }\n }\n } catch {\n // Fallback para análise por regex se o YAML parsing falhar\n\n // Detectar pull_request_target\n if (src.includes('pull_request_target:')) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-pull-request-target',\n nivel: 'erro',\n mensagem: messages.AnalistaGithubActionsMensagens.pullRequestTargetGrantsWritePermissions,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaGithubActionsMensagens.pullRequestTargetExecutesForkCodeSugestao\n }));\n }\n\n // Detectar push sem filtro\n if (/on:\\s*push:\\s*$/m.test(src) || /on:\\s*\\n\\s*push:\\s*true\\s*$/m.test(src)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-push-sem-filtro',\n nivel: 'aviso',\n mensagem: 'Trigger push sem filtro de branches definido',\n relPath,\n linha: 1,\n sugestao: 'Defina branches específicos em on.push.branches'\n }));\n }\n }\n return ocorrencias;\n }\n};"]}
|
|
1
|
+
{"version":3,"file":"detector-workflow-trigger-unsafe.js","sourceRoot":"","sources":["../../../../src/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * [BUSCA] Detector de Workflow Triggers Inseguros para GitHub Actions\n *\n * Detecta configurações de trigger perigosas em workflows:\n * - Push em branches protegidos (main, master, release/*) sem proteção\n * - Workflow_dispatch sem restrições\n * - Schedule em branches sensíveis\n * - Triggers amplos demais (push em wildcards)\n */\n\nimport { messages } from '@core/messages';\nimport { splitLines } from '@shared/helpers';\nimport { parseDocument } from 'yaml';\n\nimport type { Analista, Ocorrencia } from '@';\nimport { criarOcorrencia } from '@';\n\nconst BRANCHES_PROTEGIDOS = ['main', 'master', 'production', 'release', 'prod'];\n\n// Actions que modificam o estado do repositório (alta permissão)\nconst DANGEROUS_ACTIONS = ['actions/checkout', 'peter-evans/create-or-update-comment', 'peter-evans/create-pull-request', 'marocchino/sticky-pull-request', 'softprops/action-gh-release', 'ncipollo/release-action', 'docker/build-push-action', 'docker/login-action', 'docker/push-action', 'aws-actions/configure-aws-credentials', 'google-github-actions/auth', 'azure/login', 'hashicorp/vault-action'];\nexport const detectorWorkflowTriggerInseguro: Analista = {\n nome: 'detector-workflow-trigger-inseguro',\n categoria: 'workflows',\n descricao: 'Detecta triggers de workflow potencialmente inseguros',\n test: (relPath: string): boolean => /\\.github\\/workflows\\/.*\\.ya?ml$/i.test(relPath),\n aplicar: (src: string, relPath: string): Ocorrencia[] => {\n if (!src) return [];\n const ocorrencias: Ocorrencia[] = [];\n try {\n const doc = parseDocument(src);\n const workflow = doc.toJS();\n if (!workflow || typeof workflow !== 'object') return ocorrencias;\n const onConfig = workflow.on;\n if (!onConfig || typeof onConfig !== 'object') {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-ausente',\n nivel: 'info',\n mensagem: messages.AnalistaGithubActionsMensagens.workflowWithoutTrigger,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaGithubActionsMensagens.workflowWithoutTriggerSugestao\n }));\n return ocorrencias;\n }\n\n // --- 1. Push em branches protegidos ---\n if (onConfig.push) {\n const pushConf = onConfig.push;\n\n // Se push tem apenas tags, não é push em branches - é disparo por tag\n if (pushConf.tags && !pushConf.branches && !pushConf['branches-ignore']) {\n // Workflow disparado por tags, não por branches - não aplicar esta regra\n } else {\n const branches = typeof pushConf === 'object' && pushConf?.branches ? Array.isArray(pushConf.branches) ? pushConf.branches : [pushConf.branches] : typeof pushConf === 'object' && pushConf?.branches_ignore ? Array.isArray(pushConf.branches_ignore) ? pushConf.branches_ignore : [pushConf.branches_ignore] : undefined;\n\n // Detectar push sem filtro de branches (triggeria em todos os branches)\n if (typeof pushConf === 'object' && !pushConf.branches && !pushConf.branches_ignore && !pushConf.tags || Array.isArray(pushConf) || typeof pushConf === 'string') {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-push-sem-filtro',\n nivel: 'aviso',\n mensagem: 'Trigger push sem filtro de branches definido',\n relPath,\n linha: 1,\n sugestao: 'Defina branches específicos em on.push.branches para limitar onde o workflow é executado'\n }));\n }\n\n // Verificar se inclui branches protegidos sem paths filter\n if (branches) {\n const hasPathsFilter = !!(pushConf.paths || pushConf.paths_ignore || pushConf['paths-ignore'] || pushConf.pathsIgnore);\n if (!hasPathsFilter) {\n for (const branch of branches) {\n if (typeof branch === 'string' && BRANCHES_PROTEGIDOS.some(caminho => branch.toLowerCase() === caminho.toLowerCase() || new RegExp(`^${caminho.replace('/', '\\\\/')}`).test(branch))) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-push-branch-protegido',\n nivel: 'aviso',\n mensagem: `Trigger push configurado para branch protegido \"${branch}\" sem filtro de paths`,\n relPath,\n linha: 1,\n sugestao: 'Adicione filtros de paths (on.push.paths) para limitar quando o workflow é executado'\n }));\n }\n }\n }\n }\n }\n }\n\n // --- 2. Pull request sem verificação de branches ---\n if (onConfig.pull_request) {\n // Detectar pull_request_target\n if (onConfig.pull_request_target) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-pull-request-target',\n nivel: 'erro',\n mensagem: messages.AnalistaGithubActionsMensagens.pullRequestTargetGrantsWritePermissions,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaGithubActionsMensagens.pullRequestTargetGrantsWritePermissionsSugestao\n }));\n }\n }\n\n // --- 3. Workflow_dispatch sem inputs de validação ---\n if (onConfig.workflow_dispatch) {\n const dispatchConf = onConfig.workflow_dispatch;\n if (typeof dispatchConf === 'object' && dispatchConf.inputs) {\n const inputs = dispatchConf.inputs;\n for (const [_inputName, inputConfig] of Object.entries(inputs as Record<string, unknown>)) {\n const inputConf = inputConfig as Record<string, unknown> | undefined;\n if (inputConf && !inputConf.required) {\n // Não é erro, mas pode ser melhorado\n }\n }\n }\n // workflow_dispatch sem inputs de qualquer tipo é potencialmente perigoso\n if (typeof dispatchConf !== 'object' || !dispatchConf.inputs) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-workflow-dispatch-sem-inputs',\n nivel: 'info',\n mensagem: messages.AnalistaGithubActionsMensagens.workflowDispatchWithoutInputs,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaGithubActionsMensagens.workflowDispatchWithoutInputsSugestao\n }));\n }\n }\n\n // --- 4. Schedule em branches sensíveis ---\n if (onConfig.schedule) {\n const pushConf = onConfig.push;\n const targetBranches = typeof pushConf === 'object' && pushConf?.branches ? Array.isArray(pushConf.branches) ? pushConf.branches : [pushConf.branches] : undefined;\n if (targetBranches) {\n for (const branch of targetBranches) {\n if (typeof branch === 'string' && branch.toLowerCase() === 'production') {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-schedule-branch-sensivel',\n nivel: 'aviso',\n mensagem: 'Workflow com schedule direcionado para branch \"production\"',\n relPath,\n linha: 1,\n sugestao: 'Considere usar branches de staging para execuções agendadas'\n }));\n }\n }\n }\n }\n\n // --- 5. Triggers com wildcards excessivamente amplos ---\n const yamlRaw = src;\n if (/on:\\s*\\n\\s*push:\\s*\\n\\s*branches:\\s*\\n\\s*-\\s+'\\*\\*'/m.test(yamlRaw) || /on:\\s*\\n\\s*push:\\s*\\n\\s*branches:\\s*\\n\\s*-\\s+\"\\*\\*\"/m.test(yamlRaw)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-wildcard-amplo',\n nivel: 'info',\n mensagem: 'Trigger push com wildcard \"**\" em branches (captura todos os branches)',\n relPath,\n linha: 1,\n sugestao: 'Use padrões mais específicos para limitar os branches monitorados'\n }));\n }\n\n // --- 6. Verificar se workflow executa actions perigosas em triggers de push amplo ---\n if (onConfig.push && !onConfig.pull_request) {\n // Se push tem apenas tags, não é push em branches\n const isPushToTags = onConfig.push.tags && !onConfig.push.branches && !onConfig.push['branches-ignore'];\n if (!isPushToTags) {\n const linhas = splitLines(src);\n const hasDangerousAction = linhas.some(linha => {\n const usesMatch = linha.match(/uses:\\s*(.+)/);\n return usesMatch && DANGEROUS_ACTIONS.some(arquivo => linha.includes(arquivo));\n });\n const isPushToAllBranches = !onConfig.push.branches && !onConfig.push['branches-ignore'];\n if (isPushToAllBranches && hasDangerousAction) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-push-ampla-com-actions-perigosas',\n nivel: 'aviso',\n mensagem: 'Push sem restrição de branches executa actions que modificam estado do repositório',\n relPath,\n linha: 1,\n sugestao: 'Considere restringir push branches ou adicionar proteções (environment protection rules, approvals)'\n }));\n }\n }\n }\n } catch {\n // Fallback para análise por regex se o YAML parsing falhar\n\n // Detectar pull_request_target\n if (src.includes('pull_request_target:')) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-pull-request-target',\n nivel: 'erro',\n mensagem: messages.AnalistaGithubActionsMensagens.pullRequestTargetGrantsWritePermissions,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaGithubActionsMensagens.pullRequestTargetExecutesForkCodeSugestao\n }));\n }\n\n // Detectar push sem filtro\n if (/on:\\s*push:\\s*$/m.test(src) || /on:\\s*\\n\\s*push:\\s*true\\s*$/m.test(src)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'trigger-push-sem-filtro',\n nivel: 'aviso',\n mensagem: 'Trigger push sem filtro de branches definido',\n relPath,\n linha: 1,\n sugestao: 'Defina branches específicos em on.push.branches'\n }));\n }\n }\n return ocorrencias;\n }\n};"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyst-gitlab-ci.d.ts","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/analysts/analyst-gitlab-ci.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analyst-gitlab-ci.d.ts","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/analysts/analyst-gitlab-ci.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAgC,MAAM,GAAG,CAAC;AAKhE,eAAO,MAAM,gBAAgB,EAAE,QAqD9B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseDocument } from 'yaml';
|
|
2
1
|
import { messages } from '../../../core/messages/index.js';
|
|
2
|
+
import { parseDocument } from 'yaml';
|
|
3
3
|
import { detectorGitLabCIPerformance } from '../detectors/detector-gitlab-ci-performance.js';
|
|
4
4
|
import { detectorGitLabCISecurity } from '../detectors/detector-gitlab-ci-security.js';
|
|
5
5
|
export const analistaGitLabCI = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyst-gitlab-ci.js","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/analysts/analyst-gitlab-ci.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"analyst-gitlab-ci.js","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/analysts/analyst-gitlab-ci.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAIrC,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAEvF,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,IAAI,EAAE,WAAW;IACjB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,6CAA6C;IACxD,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,KAAK,gBAAgB,IAAI,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAC7F,OAAO,EAAE,KAAK,EAAE,QAAgB,EAAE,OAAe,EAAE,OAAwB,IAAI,EAAE,GAAY,EAAE,QAA2B,EAAyB,EAAE;QACnJ,MAAM,WAAW,GAAiB,EAAE,CAAC;QAErC,IAAI,CAAC;YAEH,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;YACxH,MAAM,kBAAkB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,2BAA2B,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;YAE9H,WAAW,CAAC,IAAI,CAAC,GAAI,eAAgC,EAAE,GAAI,kBAAmC,CAAC,CAAC;YAGhG,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAA6B,CAAC;YAEvD,IAAI,QAAQ,EAAE,CAAC;gBAEb,MAAM,MAAM,GAAI,QAAkC,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACzF,KAAK,MAAM,CAAC;gBACZ,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAEpD,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;wBACzI,SAAS;oBACX,CAAC;oBAGD,MAAM,GAAG,GAAG,KAAoF,CAAC;oBACjG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;wBAE1F,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;4BACxD,WAAW,CAAC,IAAI,CAAC;gCACf,IAAI,EAAE,wBAAwB;gCAC9B,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,mBAAmB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;gCACxF,OAAO;gCACP,KAAK,EAAE,CAAC;gCACR,KAAK,EAAE,MAAM;gCACb,QAAQ,EAAE,wFAAwF;6BACnG,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QAEH,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;CACF,CAAC","sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * [BUSCA] Analista Principal de GitLab CI\n *\n * Analisa a estrutura e qualidade de pipelines do GitLab CI.\n */\n\nimport type { NodePath } from '@babel/traverse';\nimport { messages } from '@core/messages';\nimport { parseDocument } from 'yaml';\n\nimport type { Analista, ContextoExecucao, Ocorrencia } from '@';\n\nimport { detectorGitLabCIPerformance } from '../detectors/detector-gitlab-ci-performance.js';\nimport { detectorGitLabCISecurity } from '../detectors/detector-gitlab-ci-security.js';\n\nexport const analistaGitLabCI: Analista = {\n nome: 'gitlab-ci',\n categoria: 'workflows',\n descricao: 'Analista avançado de pipelines do GitLab CI',\n test: (relPath: string) => relPath === '.gitlab-ci.yml' || relPath.endsWith('.gitlab-ci.yml'),\n aplicar: async (conteudo: string, relPath: string, _ast: NodePath | null = null, _fc?: string, contexto?: ContextoExecucao): Promise<Ocorrencia[]> => {\n const ocorrencias: Ocorrencia[] = [];\n\n try {\n // 1. Executar detectores baseados em regex (rápidos)\n const securityResults = await Promise.resolve(detectorGitLabCISecurity.aplicar(conteudo, relPath, null, _fc, contexto));\n const performanceResults = await Promise.resolve(detectorGitLabCIPerformance.aplicar(conteudo, relPath, null, _fc, contexto));\n\n ocorrencias.push(...(securityResults as Ocorrencia[]), ...(performanceResults as Ocorrencia[]));\n\n // 2. Análise Estrutural via YAML AST (para detecções mais complexas)\n const doc = parseDocument(conteudo);\n const pipeline = doc.toJS() as Record<string, unknown>;\n\n if (pipeline) {\n // Exemplo: Detecção de jobs sem stage definido\n const stages = (pipeline as { stages?: string[] }).stages || ['build', 'test', 'deploy'];\n void stages; // Reservado para futuras detecções de stages inválidos\n for (const [key, value] of Object.entries(pipeline)) {\n // Ignorar palavras reservadas\n if (['image', 'services', 'stages', 'types', 'before_script', 'after_script', 'variables', 'cache', 'include', 'workflow'].includes(key)) {\n continue;\n }\n\n // Se o valor for um objeto com 'script', provavelmente é um job\n const job = value as { script?: string[]; trigger?: unknown; extends?: unknown; stage?: string };\n if (typeof job === 'object' && job !== null && (job.script || job.trigger || job.extends)) {\n // Detecção de job muito longo (ex: mais de 15 linhas de script)\n if (Array.isArray(job.script) && job.script.length > 15) {\n ocorrencias.push({\n tipo: 'GITLAB_CI_JOB_TOO_LONG',\n mensagem: messages.AnalistaGitlabCiMensagens.jobScriptMuitoLongo(key, job.script.length),\n relPath,\n linha: 1, // Precisaria de mapeamento de linha do YAML para ser exato\n nivel: 'info',\n sugestao: 'Considere extrair o script para um arquivo separado ou quebrar em múltiplos jobs/steps'\n });\n }\n }\n }\n }\n\n } catch {\n // Silenciar erros de parse no momento da análise para não travar o processo\n }\n\n return ocorrencias;\n }\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector-gitlab-ci-performance.d.ts","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-performance.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"detector-gitlab-ci-performance.d.ts","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-performance.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,GAAG,CAAC;AAG9C,eAAO,MAAM,2BAA2B,EAAE,QAuDzC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { criarOcorrencia } from '../../../types/index.js';
|
|
2
1
|
import { messages } from '../../../core/messages/index.js';
|
|
2
|
+
import { criarOcorrencia } from '../../../types/index.js';
|
|
3
3
|
export const detectorGitLabCIPerformance = {
|
|
4
4
|
nome: 'detector-gitlab-ci-performance',
|
|
5
5
|
categoria: 'performance',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector-gitlab-ci-performance.js","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-performance.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"detector-gitlab-ci-performance.js","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-performance.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,CAAC;AAEpC,MAAM,CAAC,MAAM,2BAA2B,GAAa;IACnD,IAAI,EAAE,gCAAgC;IACtC,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,yDAAyD;IACpE,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAC7D,OAAO,EAAE,CAAC,GAAW,EAAE,OAAe,EAAgB,EAAE;QACtD,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,WAAW,GAAiB,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAG/B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;gBAC/B,IAAI,EAAE,yBAAyB;gBAC/B,KAAK,EAAE,OAAO;gBACd,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,QAAQ;gBACrD,OAAO;gBACP,KAAK,EAAE,CAAC;gBACR,QAAQ,EAAE,iFAAiF;aAC5F,CAAC,CAAC,CAAC;QACN,CAAC;QAGD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;gBAC/B,IAAI,EAAE,iCAAiC;gBACvC,KAAK,EAAE,MAAM;gBACb,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,gBAAgB;gBAC7D,OAAO;gBACP,KAAK,EAAE,CAAC;gBACR,QAAQ,EAAE,0FAA0F;aACrG,CAAC,CAAC,CAAC;QACP,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC9B,MAAM,WAAW,GAAG,KAAK,GAAG,CAAC,CAAC;YAG9B,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBAClC,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;wBAC/B,IAAI,EAAE,mCAAmC;wBACzC,KAAK,EAAE,MAAM;wBACb,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,qBAAqB;wBAClE,OAAO;wBACP,KAAK,EAAE,WAAW;wBAClB,QAAQ,EAAE,oEAAoE;qBAC/E,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,WAAW,CAAC;IACrB,CAAC;CACF,CAAC","sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * [BUSCA] Detector de Performance para GitLab CI\n *\n * Detecta problemas de performance em pipelines:\n * - Falta de cache\n * - Falta de interruptible (cancelamento automático)\n * - Artifacts sem expiração\n */\n\nimport { messages } from '@core/messages';\n\nimport type { Analista, Ocorrencia } from '@';\nimport { criarOcorrencia } from '@';\n\nexport const detectorGitLabCIPerformance: Analista = {\n nome: 'detector-gitlab-ci-performance',\n categoria: 'performance',\n descricao: 'Detecta problemas de performance em GitLab CI pipelines',\n test: (relPath: string) => relPath.endsWith('.gitlab-ci.yml'),\n aplicar: (src: string, relPath: string): Ocorrencia[] => {\n if (!src) return [];\n const ocorrencias: Ocorrencia[] = [];\n const linhas = src.split('\\n');\n\n // 1. Falta de cache\n if (!/cache:/.test(src)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-missing-cache',\n nivel: 'aviso',\n mensagem: messages.AnalistaGitlabCiMensagens.semCache,\n relPath,\n linha: 1,\n sugestao: 'Use cache para dependências (ex: node_modules, .cache) para acelerar o pipeline'\n }));\n }\n\n // 2. Uso de interruptible\n if (!/interruptible:/.test(src)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-missing-interruptible',\n nivel: 'info',\n mensagem: messages.AnalistaGitlabCiMensagens.semInterruptible,\n relPath,\n linha: 1,\n sugestao: 'Adicione interruptible: true para cancelar pipelines antigos quando um novo push ocorrer'\n }));\n }\n\n linhas.forEach((linha, index) => {\n const numeroLinha = index + 1;\n\n // 3. Artifacts sem expiração\n if (/artifacts:/.test(linha)) {\n const nextLines = src.split('\\n').slice(index, index + 5).join('\\n');\n if (!/expire_in:/.test(nextLines)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-artifacts-no-expiration',\n nivel: 'info',\n mensagem: messages.AnalistaGitlabCiMensagens.artifactsSemExpiracao,\n relPath,\n linha: numeroLinha,\n sugestao: 'Adicione expire_in: (ex: 1 week) para economizar storage no GitLab'\n }));\n }\n }\n });\n\n return ocorrencias;\n }\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector-gitlab-ci-security.d.ts","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-security.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"detector-gitlab-ci-security.d.ts","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-security.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,GAAG,CAAC;AAG9C,eAAO,MAAM,wBAAwB,EAAE,QAqDtC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { criarOcorrencia } from '../../../types/index.js';
|
|
2
1
|
import { messages } from '../../../core/messages/index.js';
|
|
2
|
+
import { criarOcorrencia } from '../../../types/index.js';
|
|
3
3
|
export const detectorGitLabCISecurity = {
|
|
4
4
|
nome: 'detector-gitlab-ci-security',
|
|
5
5
|
categoria: 'security',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector-gitlab-ci-security.js","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-security.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"detector-gitlab-ci-security.js","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-security.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,CAAC;AAEpC,MAAM,CAAC,MAAM,wBAAwB,GAAa;IAChD,IAAI,EAAE,6BAA6B;IACnC,SAAS,EAAE,UAAU;IACrB,SAAS,EAAE,iDAAiD;IAC5D,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAC7D,OAAO,EAAE,CAAC,GAAW,EAAE,OAAe,EAAgB,EAAE;QACtD,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,WAAW,GAAiB,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC9B,MAAM,WAAW,GAAG,KAAK,GAAG,CAAC,CAAC;YAI9B,IAAI,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;gBACxH,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;oBAC/B,IAAI,EAAE,wBAAwB;oBAC9B,KAAK,EAAE,OAAO;oBACd,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,YAAY;oBACzD,OAAO;oBACP,KAAK,EAAE,WAAW;oBAClB,QAAQ,EAAE,0FAA0F;iBACrG,CAAC,CAAC,CAAC;YACP,CAAC;YAGD,IAAI,yDAAyD,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjG,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;oBAC/B,IAAI,EAAE,4BAA4B;oBAClC,KAAK,EAAE,MAAM;oBACb,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,eAAe;oBAC5D,OAAO;oBACP,KAAK,EAAE,WAAW;oBAClB,QAAQ,EAAE,0FAA0F;iBACrG,CAAC,CAAC,CAAC;YACN,CAAC;YAGD,IAAI,sEAAsE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChH,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;oBAC/B,IAAI,EAAE,4BAA4B;oBAClC,KAAK,EAAE,MAAM;oBACb,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,eAAe;oBAC5D,OAAO;oBACP,KAAK,EAAE,WAAW;oBAClB,QAAQ,EAAE,8FAA8F;iBACzG,CAAC,CAAC,CAAC;YACN,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,WAAW,CAAC;IACrB,CAAC;CACF,CAAC","sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * [BUSCA] Detector de Segurança para GitLab CI\n *\n * Detecta vulnerabilidades em pipelines:\n * - Imagens sem versão específica (latest)\n * - Secrets hardcoded\n * - Script injection\n */\n\nimport { messages } from '@core/messages';\n\nimport type { Analista, Ocorrencia } from '@';\nimport { criarOcorrencia } from '@';\n\nexport const detectorGitLabCISecurity: Analista = {\n nome: 'detector-gitlab-ci-security',\n categoria: 'security',\n descricao: 'Detecta vulnerabilidades em GitLab CI pipelines',\n test: (relPath: string) => relPath.endsWith('.gitlab-ci.yml'),\n aplicar: (src: string, relPath: string): Ocorrencia[] => {\n if (!src) return [];\n const ocorrencias: Ocorrencia[] = [];\n const linhas = src.split('\\n');\n\n linhas.forEach((linha, index) => {\n const numeroLinha = index + 1;\n\n // 1. Imagens sem versão (latest)\n // Detecta 'image: name:latest' ou 'image: name' sem dois pontos\n if (/\\bimage:\\s*[^\\s@]+:latest\\b/.test(linha) || (/\\bimage:\\s*[^\\s@:]+$/.test(linha.trim()) && linha.includes('image:'))) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-image-latest',\n nivel: 'aviso',\n mensagem: messages.AnalistaGitlabCiMensagens.imagemLatest,\n relPath,\n linha: numeroLinha,\n sugestao: 'Use uma versão específica da imagem (ex: alpine:3.18) para garantir builds reproduzíveis'\n }));\n }\n\n // 2. Variáveis sensíveis hardcoded\n if (/\\b(TOKEN|SECRET|PASSWORD|KEY)\\b.*[:=]\\s*['\"][^'\"]+['\"]/i.test(linha) && !/\\$\\{/.test(linha)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-hardcoded-secret',\n nivel: 'erro',\n mensagem: messages.AnalistaGitlabCiMensagens.secretHardcoded,\n relPath,\n linha: numeroLinha,\n sugestao: 'Use variáveis de ambiente do GitLab (Settings > CI/CD > Variables) e referencie com $VAR'\n }));\n }\n\n // 3. Script injection\n if (/\\$\\{\\s*(CI_COMMIT_TITLE|CI_COMMIT_DESCRIPTION|GITLAB_USER_NAME)\\s*\\}/.test(linha) && /\\s*-\\s+/.test(linha)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-script-injection',\n nivel: 'erro',\n mensagem: messages.AnalistaGitlabCiMensagens.scriptInjection,\n relPath,\n linha: numeroLinha,\n sugestao: 'Evite usar essas variáveis diretamente em comandos de shell ou use aspas duplas corretamente'\n }));\n }\n });\n\n return ocorrencias;\n }\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector-gitlab-ci-structure.d.ts","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"detector-gitlab-ci-structure.d.ts","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,GAAG,CAAC;AAG9C,eAAO,MAAM,yBAAyB,EAAE,QAqDvC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { messages } from '../../../core/messages/index.js';
|
|
1
2
|
import { parseDocument } from 'yaml';
|
|
2
3
|
import { criarOcorrencia } from '../../../types/index.js';
|
|
3
|
-
import { messages } from '../../../core/messages/index.js';
|
|
4
4
|
export const detectorGitLabCIEstrutura = {
|
|
5
5
|
nome: 'detector-gitlab-ci-estrutura',
|
|
6
6
|
categoria: 'workflows',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector-gitlab-ci-structure.js","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"detector-gitlab-ci-structure.js","sourceRoot":"","sources":["../../../../src/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAGrC,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,CAAC;AAEpC,MAAM,CAAC,MAAM,yBAAyB,GAAa;IACjD,IAAI,EAAE,8BAA8B;IACpC,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,sDAAsD;IACjE,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAC7D,OAAO,EAAE,CAAC,GAAW,EAAE,OAAe,EAAgB,EAAE;QACtD,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,WAAW,GAAiB,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAA6B,CAAC;YACvD,IAAI,CAAC,QAAQ;gBAAE,OAAO,WAAW,CAAC;YAElC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAA8B,CAAC;YACvD,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;oBAC/B,IAAI,EAAE,yBAAyB;oBAC/B,KAAK,EAAE,MAAM;oBACb,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC;oBACxE,OAAO,EAAE,KAAK,EAAE,CAAC;oBACjB,QAAQ,EAAE,mEAAmE;iBAC9E,CAAC,CAAC,CAAC;YACN,CAAC;YAED,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnE,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;oBAC/B,IAAI,EAAE,0BAA0B;oBAChC,KAAK,EAAE,OAAO;oBACd,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,CAAC,YAAY;oBACzD,OAAO,EAAE,KAAK,EAAE,CAAC;oBACjB,QAAQ,EAAE,4EAA4E;iBACvF,CAAC,CAAC,CAAC;YACN,CAAC;YAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE;gBAC9D,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAAE,OAAO,KAAK,CAAC;gBAClK,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,QAAQ,IAAK,GAA+B,CAAC;YACjG,CAAC,CAAC,CAAC,MAAM,CAAC;YAEV,IAAI,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC9B,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC;oBAC/B,IAAI,EAAE,qBAAqB;oBAC3B,KAAK,EAAE,MAAM;oBACb,QAAQ,EAAE,GAAG,QAAQ,sDAAsD;oBAC3E,OAAO,EAAE,KAAK,EAAE,CAAC;oBACjB,QAAQ,EAAE,uFAAuF;iBAClG,CAAC,CAAC,CAAC;YACN,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAyB,CAAC;QAEnC,OAAO,WAAW,CAAC;IACrB,CAAC;CACF,CAAC","sourcesContent":["// SPDX-License-Identifier: MIT\n\nimport { messages } from '@core/messages';\nimport { parseDocument } from 'yaml';\n\nimport type { Analista, Ocorrencia } from '@';\nimport { criarOcorrencia } from '@';\n\nexport const detectorGitLabCIEstrutura: Analista = {\n nome: 'detector-gitlab-ci-estrutura',\n categoria: 'workflows',\n descricao: 'Detecta problemas estruturais em GitLab CI pipelines',\n test: (relPath: string) => relPath.endsWith('.gitlab-ci.yml'),\n aplicar: (src: string, relPath: string): Ocorrencia[] => {\n if (!src) return [];\n const ocorrencias: Ocorrencia[] = [];\n try {\n const doc = parseDocument(src);\n const pipeline = doc.toJS() as Record<string, unknown>;\n if (!pipeline) return ocorrencias;\n\n const stages = pipeline.stages as string[] | undefined;\n if (stages && stages.length > 5) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-muitos-stages',\n nivel: 'info',\n mensagem: messages.AnalistaGitlabCiMensagens.muitosStages(stages.length),\n relPath, linha: 1,\n sugestao: 'Considere separar em pipelines independentes ou consolidar stages'\n }));\n }\n\n if (stages && !stages.includes('test') && !stages.includes('lint')) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-sem-test-stage',\n nivel: 'aviso',\n mensagem: messages.AnalistaGitlabCiMensagens.semTestStage,\n relPath, linha: 1,\n sugestao: 'Adicione um stage de test com jobs de lint, unit tests ou análise estática'\n }));\n }\n\n const hasNeeds = /needs:/.test(src);\n const jobCount = Object.entries(pipeline).filter(([key, val]) => {\n if (['image', 'services', 'stages', 'types', 'before_script', 'after_script', 'variables', 'cache', 'include', 'workflow', 'default'].includes(key)) return false;\n return typeof val === 'object' && val !== null && 'script' in (val as Record<string, unknown>);\n }).length;\n\n if (jobCount > 5 && !hasNeeds) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'gitlab-ci-sem-needs',\n nivel: 'info',\n mensagem: `${jobCount} jobs sem utilização de needs para otimizar execução`,\n relPath, linha: 1,\n sugestao: 'Use needs para definir dependências entre jobs e executar em paralelo quando possível'\n }));\n }\n } catch { /* silent parse fail */ }\n\n return ocorrencias;\n }\n};\n"]}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type Msg = ReturnType<typeof criarOcorrencia>;
|
|
1
|
+
import type { OcorrenciaBase } from '../../../types/index.js';
|
|
3
2
|
export declare const analistaHtml: {
|
|
4
3
|
nome: string;
|
|
5
4
|
categoria: string;
|
|
6
5
|
descricao: string;
|
|
7
6
|
global: false;
|
|
8
7
|
test: (relPath: string) => boolean;
|
|
9
|
-
aplicar: (src: string, relPath: string) => Promise<
|
|
8
|
+
aplicar: (src: string, relPath: string) => Promise<OcorrenciaBase[] | null>;
|
|
10
9
|
};
|
|
11
|
-
export {};
|
|
12
10
|
//# sourceMappingURL=analyst-html.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyst-html.d.ts","sourceRoot":"","sources":["../../../../src/analysts/html/analysts/analyst-html.ts"],"names":[],"mappings":"AAMA,OAAO,
|
|
1
|
+
{"version":3,"file":"analyst-html.d.ts","sourceRoot":"","sources":["../../../../src/analysts/html/analysts/analyst-html.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,GAAG,CAAC;AAqbxD,eAAO,MAAM,YAAY;;;;;oBAKP,MAAM,KAAG,OAAO;+CACD,OAAO,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC;CAK/D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyst-html.js","sourceRoot":"","sources":["../../../../src/analysts/html/analysts/analyst-html.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: MIT\nimport { messages } from '@core/messages';\nimport { createLineLookup, maskHtmlComments, maskTagBlocks } from '@shared/helpers';\nimport type { AnyNode, Document, Element, Text } from 'domhandler';\nimport { parseDocument } from 'htmlparser2';\n\nimport { criarAnalista, criarOcorrencia } from '@';\n\nconst disableEnv = process.env.TUTANUS_DISABLE_PLUGIN_HTML === '1';\ntype Msg = ReturnType<typeof criarOcorrencia>;\nfunction warn(message: string, relPath: string, line?: number): Msg {\n return criarOcorrencia({\n relPath,\n mensagem: message,\n linha: line,\n nivel: messages.SeverityNiveis.warning,\n origem: messages.AnalystOrigens.html,\n tipo: messages.AnalystTipos.html\n });\n}\ntype NodeWithChildren = AnyNode & {\n children?: AnyNode[];\n};\nfunction isElement(node: AnyNode): node is Element {\n return node.type === 'tag';\n}\nfunction getAttr(el: Element, name: string): string {\n const attrs = el.attribs || {};\n const valor = attrs[name] ?? attrs[name.toLowerCase()] ?? '';\n return typeof valor === 'string' ? valor : '';\n}\nfunction hasAnyDataAttr(el: Element): boolean {\n const attrs = el.attribs || {};\n return Object.keys(attrs).some(chave => chave.toLowerCase().startsWith('data-'));\n}\nfunction walk(node: AnyNode, visit: (node: AnyNode) => void) {\n visit(node);\n const children = (node as NodeWithChildren).children;\n if (Array.isArray(children)) {\n for (const elem of children) walk(elem, visit);\n }\n}\nfunction isInlineEvent(attr: string): boolean {\n const arquivo = attr.toLowerCase();\n return arquivo === 'onclick' || arquivo === 'onchange' || arquivo === 'onsubmit' || arquivo === 'onload' || arquivo === 'onerror' || arquivo === 'onmouseover' || arquivo === 'onmouseout' || arquivo === 'onkeyup' || arquivo === 'onkeydown' || arquivo === 'onfocus' || arquivo === 'onblur' || arquivo === 'oninput';\n}\nfunction checkDoctype(node: AnyNode): boolean | null {\n if (node.type !== 'directive') return null;\n const data = String((node as unknown as { data?: string }).data || '');\n return /^!doctype\\s+html\\b/i.test(data);\n}\nfunction validateHtmlLang(node: Element, tag: string, isTemplate: boolean): boolean {\n if (tag !== 'html' || isTemplate) return false;\n return !!getAttr(node, 'lang');\n}\nfunction validateTitleTag(tag: string, isTemplate: boolean): boolean {\n return tag === 'title' && !isTemplate;\n}\nfunction validateMetaTag(node: Element, tag: string, isTemplate: boolean): { charset: boolean; viewport: boolean } | null {\n if (tag !== 'meta' || isTemplate) return null;\n let charset = false;\n let viewport = false;\n const charsetVal = getAttr(node, 'charset');\n if (charsetVal) charset = true;\n const httpEquiv = getAttr(node, 'http-equiv').toLowerCase();\n const content = getAttr(node, 'content');\n if (httpEquiv === 'content-type' && /charset\\s*=\\s*utf-8/i.test(content)) charset = true;\n const name = getAttr(node, 'name').toLowerCase();\n if (name === 'viewport') viewport = true;\n return { charset, viewport };\n}\nfunction validateHeading(\n node: Element,\n tag: string,\n line: number,\n relPath: string,\n isTemplate: boolean,\n ocorrencias: Msg[],\n lastHeadingNivel: number\n): { h1Inc: number; nivel: number } | null {\n if (!/^h[1-6]$/.test(tag) || isTemplate) return null;\n const level = parseInt(tag.charAt(1), 10);\n let h1Inc = 0;\n if (level === 1) h1Inc = 1;\n if (level > lastHeadingNivel + 1 && lastHeadingNivel > 0) {\n ocorrencias.push(warn(messages.HtmlMensagens.headingSkipped(level, lastHeadingNivel + 1), relPath, line));\n }\n return { h1Inc, nivel: level };\n}\ntype Validador = (node: Element, tag: string, line: number, relPath: string, ocorrencias: Msg[], isTemplate: boolean) => void;\n\nconst validadores: Record<string, Validador> = {\n button(node, tag, line, relPath, ocorrencias) {\n const text = (node as NodeWithChildren).children?.some(elem => elem.type === 'text' && String((elem as Text).data || '').trim().length > 0);\n const ariaLabel = !!getAttr(node, 'aria-label');\n const title = !!getAttr(node, 'title');\n if (!text && !ariaLabel && !title) {\n ocorrencias.push(warn(messages.HtmlMensagens.buttonWithoutText, relPath, line));\n }\n },\n table(node, tag, line, relPath, ocorrencias) {\n const hasCaption = (node as NodeWithChildren).children?.some(elem => elem.type === 'tag' && String((elem as Element).name).toLowerCase() === 'caption');\n const ariaLabel = !!getAttr(node, 'aria-label');\n if (!hasCaption && !ariaLabel) {\n ocorrencias.push(warn(messages.HtmlMensagens.tableWithoutCaption, relPath, line));\n }\n },\n iframe(node, tag, line, relPath, ocorrencias) {\n const title = getAttr(node, 'title');\n if (!title) {\n ocorrencias.push(warn(messages.HtmlMensagens.iframeWithoutTitle, relPath, line));\n }\n },\n a(node, tag, line, relPath, ocorrencias) {\n const target = getAttr(node, 'target');\n if (target === '_blank') {\n const rel = getAttr(node, 'rel');\n const safe = /(noopener|noreferrer)/i.test(rel);\n if (!safe) ocorrencias.push(warn(messages.HtmlMensagens.linkTargetBlank, relPath, line));\n }\n const attrs = node.attribs || {};\n const hasHref = Object.prototype.hasOwnProperty.call(attrs, 'href');\n const href = getAttr(node, 'href');\n if (!hasHref || href === '' || href === '#') {\n const hasOnClick = Object.keys(attrs).some(chave => chave.toLowerCase() === 'onclick');\n const role = getAttr(node, 'role').toLowerCase();\n const tabindex = getAttr(node, 'tabindex');\n const isRoleButton = role === 'button';\n if (!hasOnClick && !isRoleButton && !tabindex) {\n ocorrencias.push(warn(messages.HtmlMensagens.linkNoHref, relPath, line));\n }\n }\n },\n img(node, tag, line, relPath, ocorrencias, isTemplate) {\n const alt = getAttr(node, 'alt');\n const ariaHidden = getAttr(node, 'aria-hidden').toLowerCase() === 'true';\n const ariaLabel = !!getAttr(node, 'aria-label');\n const role = getAttr(node, 'role').toLowerCase();\n const decorative = ariaHidden || ariaLabel || role === 'presentation' || role === 'none';\n const srcAttr = getAttr(node, 'src');\n const isSvg = /\\.svg(\\?|#|$)/i.test(srcAttr);\n const attrs = node.attribs || {};\n const dataAttr = Object.keys(attrs).some(chave => /^(data-)?(decorative|icon|symbol)$/i.test(chave));\n if (!alt && !decorative && !dataAttr && !isSvg) {\n ocorrencias.push(warn(messages.HtmlMensagens.imgWithoutAlt, relPath, line));\n }\n const loading = getAttr(node, 'loading');\n if (!loading && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.imgWithoutLoading, relPath, line));\n }\n const width = getAttr(node, 'width');\n const height = getAttr(node, 'height');\n if (!width || !height) {\n ocorrencias.push(warn(messages.HtmlMensagens.imgWithoutDimensions, relPath, line));\n }\n },\n form(node, tag, line, relPath, ocorrencias) {\n const method = getAttr(node, 'method');\n const action = getAttr(node, 'action');\n if (!method) ocorrencias.push(warn(messages.HtmlMensagens.formWithoutMethod, relPath, line));\n if (!action && !hasAnyDataAttr(node)) {\n ocorrencias.push(warn(messages.HtmlMensagens.formWithoutAction, relPath, line));\n }\n },\n input(node, tag, line, relPath, ocorrencias) {\n const type = getAttr(node, 'type').toLowerCase();\n const name = getAttr(node, 'name');\n const ariaLabel = getAttr(node, 'aria-label');\n const isHidden = type === 'hidden';\n const isButton = type === 'button' || type === 'submit' || type === 'reset';\n if (!isHidden && !isButton && !ariaLabel && !name) {\n ocorrencias.push(warn(messages.HtmlMensagens.inputWithoutLabel, relPath, line));\n }\n if (!type) {\n ocorrencias.push(warn(messages.HtmlMensagens.inputWithoutType, relPath, line));\n }\n if (type === 'password') {\n const autocomplete = getAttr(node, 'autocomplete');\n if (!autocomplete) {\n ocorrencias.push(warn(messages.HtmlMensagens.passwordWithoutAutocomplete, relPath, line));\n }\n }\n },\n script(node, tag, line, relPath, ocorrencias, isTemplate) {\n const srcAttr = getAttr(node, 'src');\n const children = (node as unknown as NodeWithChildren).children || [];\n const textNodes = children.filter((elem): elem is Text => elem.type === 'text');\n const text = textNodes.map(elem => String((elem as Text).data || '')).join('');\n if (!srcAttr && text.trim().length > 0) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineScript, relPath, line));\n if (text.length > 1000) {\n ocorrencias.push(warn(messages.HtmlMensagens.largeInlineScript, relPath, line));\n }\n }\n if (srcAttr && !isTemplate) {\n const defer = getAttr(node, 'defer');\n const async = getAttr(node, 'async');\n if (!defer && !async) {\n ocorrencias.push(warn(messages.HtmlMensagens.scriptWithoutDefer, relPath, line));\n }\n }\n },\n style(node, tag, line, relPath, ocorrencias) {\n const children = (node as unknown as NodeWithChildren).children || [];\n const textNodes = children.filter((elem): elem is Text => elem.type === 'text');\n const text = textNodes.map(elem => String((elem as Text).data || '')).join('');\n if (text.trim().length > 0) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineStyle, relPath, line));\n }\n }\n};\n\nfunction validateNode(node: Element, tag: string, line: number, relPath: string, ocorrencias: Msg[], isTemplate: boolean): void {\n const validador = validadores[tag];\n if (validador) {\n validador(node, tag, line, relPath, ocorrencias, isTemplate);\n }\n const attrs = node?.attribs || {};\n for (const chave of Object.keys(attrs)) {\n if (isInlineEvent(chave)) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineHandler, relPath, line));\n break;\n }\n }\n}\nfunction verificarDocumento(\n ocorrencias: Msg[],\n relPath: string,\n hasDoctype: boolean,\n htmlLangOk: boolean,\n hasCharset: boolean,\n hasViewport: boolean,\n hasTitle: boolean,\n h1Contagem: number,\n isTemplate: boolean\n): void {\n if (isTemplate) return;\n if (!hasDoctype) ocorrencias.push(warn(messages.HtmlMensagens.doctype, relPath, 1));\n if (!htmlLangOk) ocorrencias.push(warn(messages.HtmlMensagens.htmlLang, relPath, 1));\n if (!hasCharset) ocorrencias.push(warn(messages.HtmlMensagens.metaCharset, relPath, 1));\n if (!hasViewport) ocorrencias.push(warn(messages.HtmlMensagens.viewport, relPath, 1));\n if (!hasTitle) ocorrencias.push(warn(messages.HtmlMensagens.title, relPath, 1));\n if (h1Contagem > 1) ocorrencias.push(warn(messages.HtmlMensagens.multipleH1, relPath, 1));\n}\nfunction collectHtmlIssuesAst(src: string, relPath: string): Msg[] {\n const ocorrencias: Msg[] = [];\n const isTemplate = /\\.(template\\.html|\\.component\\.html)$/i.test(relPath);\n const lineOf = createLineLookup(src).lineAt;\n const doc = parseDocument(src, {\n xmlMode: false,\n withStartIndices: true,\n withEndIndices: true,\n recognizeSelfClosing: true\n }) as unknown as Document;\n let hasDoctype = false;\n let hasTitle = false;\n let hasViewport = false;\n let hasCharset = false;\n let htmlLangOk = false;\n let lastHeadingNivel = 0;\n let h1Contagem = 0;\n const startLineOf = (node: AnyNode) => {\n const indice = typeof (node as unknown as {\n startIndex?: number | null;\n }).startIndex === 'number' ? (node as unknown as {\n startIndex?: number | null;\n }).startIndex as number : 0;\n return lineOf(indice);\n };\n walk(doc as unknown as AnyNode, node => {\n const doctype = checkDoctype(node);\n if (doctype !== null) { hasDoctype = doctype; return; }\n if (!isElement(node)) return;\n const tag = String(node.name || '').toLowerCase();\n const line = startLineOf(node);\n if (validateTitleTag(tag, isTemplate)) hasTitle = true;\n const langResult = validateHtmlLang(node, tag, isTemplate);\n if (langResult) htmlLangOk = true;\n const metaResult = validateMetaTag(node, tag, isTemplate);\n if (metaResult) {\n if (metaResult.charset) hasCharset = true;\n if (metaResult.viewport) hasViewport = true;\n }\n const headingResult = validateHeading(node, tag, line, relPath, isTemplate, ocorrencias, lastHeadingNivel);\n if (headingResult) {\n h1Contagem += headingResult.h1Inc;\n lastHeadingNivel = headingResult.nivel;\n }\n validateNode(node, tag, line, relPath, ocorrencias, isTemplate);\n });\n verificarDocumento(ocorrencias, relPath, hasDoctype, htmlLangOk, hasCharset, hasViewport, hasTitle, h1Contagem, isTemplate);\n return ocorrencias;\n}\nfunction checkDocTypeRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: Msg[]): void {\n if (!/<!DOCTYPE\\s+html>/i.test(scan) && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.doctype, relPath, 1));\n }\n}\nfunction checkHtmlLangRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: Msg[], lineOfMasked: (idx: number) => number): void {\n const htmlTag = scan.match(/<html[^>]*>/i);\n if (htmlTag && !isTemplate) {\n const hasLang = /\\slang=['\"][^'\" >]+['\"]/i.test(htmlTag[0]);\n if (!hasLang) {\n ocorrencias.push(warn(messages.HtmlMensagens.htmlLang, relPath, lineOfMasked(htmlTag.index ?? 0)));\n }\n }\n}\nfunction checkMetaCharsetRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: Msg[]): void {\n const hasCharsetAttr = /<meta\\s+[^>]*\\bcharset\\s*=\\s*['\"]?[^'\">\\s]+/i.test(scan);\n const hasCharsetInContentTipo = /<meta\\s+[^>]*http-equiv\\s*=\\s*['\"]content-type['\"][^>]*>/i.test(scan) && /charset\\s*=\\s*utf-8/i.test(scan);\n if (!hasCharsetAttr && !hasCharsetInContentTipo && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.metaCharset, relPath, 1));\n }\n}\nfunction checkViewportRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: Msg[]): void {\n if (!/<meta\\s+[^>]*name=[\"']viewport[\"']/i.test(scan) && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.viewport, relPath, 1));\n }\n}\nfunction checkTitleRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: Msg[]): void {\n if (!/<title>[^<]*<\\/title>/i.test(scan) && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.title, relPath, 1));\n }\n}\nfunction checkLinkTargetBlankRegex(scan: string, relPath: string, ocorrencias: Msg[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<a[^>]*target=['\"]?_blank['\"]?[^>]*>/gi)) {\n const hasRelSafe = /rel=['\"][^'\"]*(noopener|noreferrer)[^'\"]*['\"]/i.test(metrica[0]);\n if (!hasRelSafe) {\n ocorrencias.push(warn(messages.HtmlMensagens.linkTargetBlank, relPath, lineOfMasked(metrica.index)));\n }\n }\n}\nfunction checkImgAltRegex(scan: string, relPath: string, ocorrencias: Msg[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<img[^>]*>/gi)) {\n const isSvg = /\\.svg/i.test(metrica[0]);\n const hasAlt = /\\salt=/.test(metrica[0]);\n const ariaHidden = /\\saria-hidden=['\"]true['\"]/i.test(metrica[0]);\n const ariaLabel = /\\saria-label=/i.test(metrica[0]);\n const rolePresentation = /\\srole=['\"](presentation|none)['\"]/i.test(metrica[0]);\n const dataAttr = /\\s(?:data-)?(?:decorative|icon|symbol)=/i.test(metrica[0]);\n if (!hasAlt && !ariaHidden && !ariaLabel && !rolePresentation && !dataAttr && !isSvg) {\n ocorrencias.push(warn(messages.HtmlMensagens.imgWithoutAlt, relPath, lineOfMasked(metrica.index)));\n }\n }\n}\nfunction checkInlineHandlerRegex(scan: string, relPath: string, ocorrencias: Msg[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/\\son(?:click|change|submit|load|error|mouseover|mouseout|keyup|keydown|focus|blur|input)=/gi)) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineHandler, relPath, lineOfMasked(metrica.index)));\n }\n}\nfunction checkFormRegex(scan: string, relPath: string, ocorrencias: Msg[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<form[^>]*>/gi)) {\n const hasMethod = /\\smethod=/i.test(metrica[0]);\n const hasAction = /\\saction=/i.test(metrica[0]);\n if (!hasMethod) {\n ocorrencias.push(warn(messages.HtmlMensagens.formWithoutMethod, relPath, lineOfMasked(metrica.index)));\n }\n if (!hasAction && !/<form[^>]*data-/i.test(metrica[0])) {\n ocorrencias.push(warn(messages.HtmlMensagens.formWithoutAction, relPath, lineOfMasked(metrica.index)));\n }\n }\n}\nfunction checkInputRegex(scan: string, relPath: string, ocorrencias: Msg[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<input[^>]*>/gi)) {\n const hasAriaLabel = /\\saria-label=/i.test(metrica[0]);\n const hasNome = /\\sname=/i.test(metrica[0]);\n const isHidden = /\\stype=['\"]?hidden['\"]?/i.test(metrica[0]);\n const isButton = /\\stype=['\"]?(button|submit|reset)['\"]/i.test(metrica[0]);\n if (!isHidden && !isButton && !hasAriaLabel && !hasNome) {\n ocorrencias.push(warn(messages.HtmlMensagens.inputWithoutLabel, relPath, lineOfMasked(metrica.index)));\n }\n if (/\\stype=['\"]?password['\"]?\\s/.test(metrica[0]) && !/\\sautocomplete=/i.test(metrica[0])) {\n ocorrencias.push(warn(messages.HtmlMensagens.passwordWithoutAutocomplete, relPath, lineOfMasked(metrica.index)));\n }\n }\n}\nfunction checkLinkNoHrefRegex(scan: string, relPath: string, ocorrencias: Msg[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<a[^>]*>/gi)) {\n const hasHref = /\\shref=/.test(metrica[0]);\n const href = /\\shref=['\"]([^'\"]*)['\"]/i.exec(metrica[0]);\n if (!hasHref || href?.[1] === '' || href?.[1] === '#') {\n const hasOnClick = /\\sonclick\\s*=/.test(metrica[0]);\n const hasRoleButton = /\\srole=['\"]button['\"]/i.test(metrica[0]);\n const hasTabIndex = /\\stabindex\\s*=/.test(metrica[0]);\n if (!hasOnClick && !hasRoleButton && !hasTabIndex) {\n ocorrencias.push(warn(messages.HtmlMensagens.linkNoHref, relPath, lineOfMasked(metrica.index)));\n }\n }\n }\n}\nfunction checkInlineScriptRegex(src: string, scanNoScriptStyle: string, relPath: string, ocorrencias: Msg[], lineOfScan: (idx: number) => number): void {\n for (const metrica of src.matchAll(/<script[^>]*>[\\s\\S]*?<\\/\\s*script\\b[^>]*\\s*>/gi)) {\n if (typeof metrica.index === 'number') {\n const idx = metrica.index;\n if ((scanNoScriptStyle[idx] ?? ' ') !== '<') continue;\n }\n const isExternal = /\\ssrc=/.test(metrica[0]);\n const innerScriptContent = metrica[0].replace(/^[\\s\\S]*?<script\\b[^>]*>/i, '').replace(/<\\/\\s*script\\b[^>]*\\s*>[\\s\\S]*$/i, '');\n const isEmpty = innerScriptContent.trim().length === 0;\n if (!isExternal && !isEmpty) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineScript, relPath, lineOfScan(metrica.index)));\n }\n }\n}\nfunction checkInlineStyleRegex(src: string, scanNoScriptStyle: string, relPath: string, ocorrencias: Msg[], lineOfScan: (idx: number) => number): void {\n for (const metrica of src.matchAll(/<style[^>]*>[\\s\\S]*?<\\/\\s*style\\b[^>]*\\s*>/gi)) {\n if (typeof metrica.index === 'number') {\n const idx = metrica.index;\n if ((scanNoScriptStyle[idx] ?? ' ') !== '<') continue;\n }\n const isEmpty = /<style\\b[^>]*>\\s*<\\/\\s*style[^>]*>/i.test(metrica[0]);\n if (!isEmpty) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineStyle, relPath, lineOfScan(metrica.index)));\n }\n }\n}\nfunction collectHtmlIssuesRegex(src: string, relPath: string): Msg[] {\n const ocorrencias: Msg[] = [];\n const isTemplate = /\\.(template\\.html|\\.component\\.html)$/i.test(relPath);\n const lineOfScan = createLineLookup(src).lineAt;\n const scan = maskHtmlComments(maskTagBlocks(maskTagBlocks(src, 'script'), 'style'));\n const lineOfMasked = createLineLookup(scan).lineAt;\n const scanNoScriptStyle = maskHtmlComments(src);\n checkDocTypeRegex(scan, relPath, isTemplate, ocorrencias);\n checkHtmlLangRegex(scan, relPath, isTemplate, ocorrencias, lineOfMasked);\n checkMetaCharsetRegex(scan, relPath, isTemplate, ocorrencias);\n checkViewportRegex(scan, relPath, isTemplate, ocorrencias);\n checkTitleRegex(scan, relPath, isTemplate, ocorrencias);\n checkLinkTargetBlankRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkImgAltRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkInlineHandlerRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkFormRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkInputRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkLinkNoHrefRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkInlineScriptRegex(src, scanNoScriptStyle, relPath, ocorrencias, lineOfScan);\n checkInlineStyleRegex(src, scanNoScriptStyle, relPath, ocorrencias, lineOfScan);\n return ocorrencias;\n}\nfunction collectHtmlIssues(src: string, relPath: string): Msg[] {\n try {\n return collectHtmlIssuesAst(src, relPath);\n } catch {\n return collectHtmlIssuesRegex(src, relPath);\n }\n}\nexport const analistaHtml = criarAnalista({\n nome: 'analista-html',\n categoria: 'markup',\n descricao: 'Heurísticas leves para HTML com convenções padrão.',\n global: false,\n test: (relPath: string): boolean => /\\.(html|htm)$/i.test(relPath),\n aplicar: async (src, relPath): Promise<Msg[] | null> => {\n if (disableEnv) return null;\n const msgs = collectHtmlIssues(src, relPath);\n return msgs.length ? msgs : null;\n }\n});\n"]}
|
|
1
|
+
{"version":3,"file":"analyst-html.js","sourceRoot":"","sources":["../../../../src/analysts/html/analysts/analyst-html.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: MIT\nimport { messages } from '@core/messages';\nimport { createLineLookup, maskHtmlComments, maskTagBlocks } from '@shared/helpers';\nimport type { AnyNode, Document, Element, Text } from 'domhandler';\nimport { parseDocument } from 'htmlparser2';\n\nimport type { OcorrenciaBase , ValidadorHtml } from '@';\nimport { criarAnalista, criarOcorrencia } from '@';\n\nconst disableEnv = process.env.TUTANUS_DISABLE_PLUGIN_HTML === '1';\nfunction warn(message: string, relPath: string, line?: number): OcorrenciaBase {\n return criarOcorrencia({\n relPath,\n mensagem: message,\n linha: line,\n nivel: messages.SeverityNiveis.warning,\n origem: messages.AnalystOrigens.html,\n tipo: messages.AnalystTipos.html\n });\n}\ntype NodeWithChildren = AnyNode & {\n children?: AnyNode[];\n};\nfunction isElement(node: AnyNode): node is Element {\n return node.type === 'tag';\n}\nfunction getAttr(el: Element, name: string): string {\n const attrs = el.attribs || {};\n const valor = attrs[name] ?? attrs[name.toLowerCase()] ?? '';\n return typeof valor === 'string' ? valor : '';\n}\nfunction hasAnyDataAttr(el: Element): boolean {\n const attrs = el.attribs || {};\n return Object.keys(attrs).some(chave => chave.toLowerCase().startsWith('data-'));\n}\nfunction walk(node: AnyNode, visit: (node: AnyNode) => void) {\n visit(node);\n const children = (node as NodeWithChildren).children;\n if (Array.isArray(children)) {\n for (const elem of children) walk(elem, visit);\n }\n}\nfunction isInlineEvent(attr: string): boolean {\n const arquivo = attr.toLowerCase();\n return arquivo === 'onclick' || arquivo === 'onchange' || arquivo === 'onsubmit' || arquivo === 'onload' || arquivo === 'onerror' || arquivo === 'onmouseover' || arquivo === 'onmouseout' || arquivo === 'onkeyup' || arquivo === 'onkeydown' || arquivo === 'onfocus' || arquivo === 'onblur' || arquivo === 'oninput';\n}\nfunction checkDoctype(node: AnyNode): boolean | null {\n if (node.type !== 'directive') return null;\n const data = String((node as unknown as { data?: string }).data || '');\n return /^!doctype\\s+html\\b/i.test(data);\n}\nfunction validateHtmlLang(node: Element, tag: string, isTemplate: boolean): boolean {\n if (tag !== 'html' || isTemplate) return false;\n return !!getAttr(node, 'lang');\n}\nfunction validateTitleTag(tag: string, isTemplate: boolean): boolean {\n return tag === 'title' && !isTemplate;\n}\nfunction validateMetaTag(node: Element, tag: string, isTemplate: boolean): { charset: boolean; viewport: boolean } | null {\n if (tag !== 'meta' || isTemplate) return null;\n let charset = false;\n let viewport = false;\n const charsetVal = getAttr(node, 'charset');\n if (charsetVal) charset = true;\n const httpEquiv = getAttr(node, 'http-equiv').toLowerCase();\n const content = getAttr(node, 'content');\n if (httpEquiv === 'content-type' && /charset\\s*=\\s*utf-8/i.test(content)) charset = true;\n const name = getAttr(node, 'name').toLowerCase();\n if (name === 'viewport') viewport = true;\n return { charset, viewport };\n}\nfunction validateHeading(\n node: Element,\n tag: string,\n line: number,\n relPath: string,\n isTemplate: boolean,\n ocorrencias: OcorrenciaBase[],\n lastHeadingNivel: number\n): { h1Inc: number; nivel: number } | null {\n if (!/^h[1-6]$/.test(tag) || isTemplate) return null;\n const level = parseInt(tag.charAt(1), 10);\n let h1Inc = 0;\n if (level === 1) h1Inc = 1;\n if (level > lastHeadingNivel + 1 && lastHeadingNivel > 0) {\n ocorrencias.push(warn(messages.HtmlMensagens.headingSkipped(level, lastHeadingNivel + 1), relPath, line));\n }\n return { h1Inc, nivel: level };\n}\nconst validadores: Record<string, ValidadorHtml> = {\n button(node, tag, line, relPath, ocorrencias) {\n const text = (node as NodeWithChildren).children?.some(elem => elem.type === 'text' && String((elem as Text).data || '').trim().length > 0);\n const ariaLabel = !!getAttr(node, 'aria-label');\n const title = !!getAttr(node, 'title');\n if (!text && !ariaLabel && !title) {\n ocorrencias.push(warn(messages.HtmlMensagens.buttonWithoutText, relPath, line));\n }\n },\n table(node, tag, line, relPath, ocorrencias) {\n const hasCaption = (node as NodeWithChildren).children?.some(elem => elem.type === 'tag' && String((elem as Element).name).toLowerCase() === 'caption');\n const ariaLabel = !!getAttr(node, 'aria-label');\n if (!hasCaption && !ariaLabel) {\n ocorrencias.push(warn(messages.HtmlMensagens.tableWithoutCaption, relPath, line));\n }\n },\n iframe(node, tag, line, relPath, ocorrencias) {\n const title = getAttr(node, 'title');\n if (!title) {\n ocorrencias.push(warn(messages.HtmlMensagens.iframeWithoutTitle, relPath, line));\n }\n },\n a(node, tag, line, relPath, ocorrencias) {\n const target = getAttr(node, 'target');\n if (target === '_blank') {\n const rel = getAttr(node, 'rel');\n const safe = /(noopener|noreferrer)/i.test(rel);\n if (!safe) ocorrencias.push(warn(messages.HtmlMensagens.linkTargetBlank, relPath, line));\n }\n const attrs = node.attribs || {};\n const hasHref = Object.prototype.hasOwnProperty.call(attrs, 'href');\n const href = getAttr(node, 'href');\n if (!hasHref || href === '' || href === '#') {\n const hasOnClick = Object.keys(attrs).some(chave => chave.toLowerCase() === 'onclick');\n const role = getAttr(node, 'role').toLowerCase();\n const tabindex = getAttr(node, 'tabindex');\n const isRoleButton = role === 'button';\n if (!hasOnClick && !isRoleButton && !tabindex) {\n ocorrencias.push(warn(messages.HtmlMensagens.linkNoHref, relPath, line));\n }\n }\n },\n img(node, tag, line, relPath, ocorrencias, isTemplate) {\n const alt = getAttr(node, 'alt');\n const ariaHidden = getAttr(node, 'aria-hidden').toLowerCase() === 'true';\n const ariaLabel = !!getAttr(node, 'aria-label');\n const role = getAttr(node, 'role').toLowerCase();\n const decorative = ariaHidden || ariaLabel || role === 'presentation' || role === 'none';\n const srcAttr = getAttr(node, 'src');\n const isSvg = /\\.svg(\\?|#|$)/i.test(srcAttr);\n const attrs = node.attribs || {};\n const dataAttr = Object.keys(attrs).some(chave => /^(data-)?(decorative|icon|symbol)$/i.test(chave));\n if (!alt && !decorative && !dataAttr && !isSvg) {\n ocorrencias.push(warn(messages.HtmlMensagens.imgWithoutAlt, relPath, line));\n }\n const loading = getAttr(node, 'loading');\n if (!loading && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.imgWithoutLoading, relPath, line));\n }\n const width = getAttr(node, 'width');\n const height = getAttr(node, 'height');\n if (!width || !height) {\n ocorrencias.push(warn(messages.HtmlMensagens.imgWithoutDimensions, relPath, line));\n }\n },\n form(node, tag, line, relPath, ocorrencias) {\n const method = getAttr(node, 'method');\n const action = getAttr(node, 'action');\n if (!method) ocorrencias.push(warn(messages.HtmlMensagens.formWithoutMethod, relPath, line));\n if (!action && !hasAnyDataAttr(node)) {\n ocorrencias.push(warn(messages.HtmlMensagens.formWithoutAction, relPath, line));\n }\n },\n input(node, tag, line, relPath, ocorrencias) {\n const type = getAttr(node, 'type').toLowerCase();\n const name = getAttr(node, 'name');\n const ariaLabel = getAttr(node, 'aria-label');\n const isHidden = type === 'hidden';\n const isButton = type === 'button' || type === 'submit' || type === 'reset';\n if (!isHidden && !isButton && !ariaLabel && !name) {\n ocorrencias.push(warn(messages.HtmlMensagens.inputWithoutLabel, relPath, line));\n }\n if (!type) {\n ocorrencias.push(warn(messages.HtmlMensagens.inputWithoutType, relPath, line));\n }\n if (type === 'password') {\n const autocomplete = getAttr(node, 'autocomplete');\n if (!autocomplete) {\n ocorrencias.push(warn(messages.HtmlMensagens.passwordWithoutAutocomplete, relPath, line));\n }\n }\n },\n script(node, tag, line, relPath, ocorrencias, isTemplate) {\n const srcAttr = getAttr(node, 'src');\n const children = (node as unknown as NodeWithChildren).children || [];\n const textNodes = children.filter((elem): elem is Text => elem.type === 'text');\n const text = textNodes.map(elem => String((elem as Text).data || '')).join('');\n if (!srcAttr && text.trim().length > 0) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineScript, relPath, line));\n if (text.length > 1000) {\n ocorrencias.push(warn(messages.HtmlMensagens.largeInlineScript, relPath, line));\n }\n }\n if (srcAttr && !isTemplate) {\n const defer = getAttr(node, 'defer');\n const async = getAttr(node, 'async');\n if (!defer && !async) {\n ocorrencias.push(warn(messages.HtmlMensagens.scriptWithoutDefer, relPath, line));\n }\n }\n },\n style(node, tag, line, relPath, ocorrencias) {\n const children = (node as unknown as NodeWithChildren).children || [];\n const textNodes = children.filter((elem): elem is Text => elem.type === 'text');\n const text = textNodes.map(elem => String((elem as Text).data || '')).join('');\n if (text.trim().length > 0) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineStyle, relPath, line));\n }\n }\n};\n\nfunction validateNode(node: Element, tag: string, line: number, relPath: string, ocorrencias: OcorrenciaBase[], isTemplate: boolean): void {\n const validador = validadores[tag];\n if (validador) {\n validador(node, tag, line, relPath, ocorrencias, isTemplate);\n }\n const attrs = node?.attribs || {};\n for (const chave of Object.keys(attrs)) {\n if (isInlineEvent(chave)) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineHandler, relPath, line));\n break;\n }\n }\n}\nfunction verificarDocumento(\n ocorrencias: OcorrenciaBase[],\n relPath: string,\n hasDoctype: boolean,\n htmlLangOk: boolean,\n hasCharset: boolean,\n hasViewport: boolean,\n hasTitle: boolean,\n h1Contagem: number,\n isTemplate: boolean\n): void {\n if (isTemplate) return;\n if (!hasDoctype) ocorrencias.push(warn(messages.HtmlMensagens.doctype, relPath, 1));\n if (!htmlLangOk) ocorrencias.push(warn(messages.HtmlMensagens.htmlLang, relPath, 1));\n if (!hasCharset) ocorrencias.push(warn(messages.HtmlMensagens.metaCharset, relPath, 1));\n if (!hasViewport) ocorrencias.push(warn(messages.HtmlMensagens.viewport, relPath, 1));\n if (!hasTitle) ocorrencias.push(warn(messages.HtmlMensagens.title, relPath, 1));\n if (h1Contagem > 1) ocorrencias.push(warn(messages.HtmlMensagens.multipleH1, relPath, 1));\n}\nfunction collectHtmlIssuesAst(src: string, relPath: string): OcorrenciaBase[] {\n const ocorrencias: OcorrenciaBase[] = [];\n const isTemplate = /\\.(template\\.html|\\.component\\.html)$/i.test(relPath);\n const lineOf = createLineLookup(src).lineAt;\n const doc = parseDocument(src, {\n xmlMode: false,\n withStartIndices: true,\n withEndIndices: true,\n recognizeSelfClosing: true\n }) as unknown as Document;\n let hasDoctype = false;\n let hasTitle = false;\n let hasViewport = false;\n let hasCharset = false;\n let htmlLangOk = false;\n let lastHeadingNivel = 0;\n let h1Contagem = 0;\n const startLineOf = (node: AnyNode) => {\n const indice = typeof (node as unknown as {\n startIndex?: number | null;\n }).startIndex === 'number' ? (node as unknown as {\n startIndex?: number | null;\n }).startIndex as number : 0;\n return lineOf(indice);\n };\n walk(doc as unknown as AnyNode, node => {\n const doctype = checkDoctype(node);\n if (doctype !== null) { hasDoctype = doctype; return; }\n if (!isElement(node)) return;\n const tag = String(node.name || '').toLowerCase();\n const line = startLineOf(node);\n if (validateTitleTag(tag, isTemplate)) hasTitle = true;\n const langResult = validateHtmlLang(node, tag, isTemplate);\n if (langResult) htmlLangOk = true;\n const metaResult = validateMetaTag(node, tag, isTemplate);\n if (metaResult) {\n if (metaResult.charset) hasCharset = true;\n if (metaResult.viewport) hasViewport = true;\n }\n const headingResult = validateHeading(node, tag, line, relPath, isTemplate, ocorrencias, lastHeadingNivel);\n if (headingResult) {\n h1Contagem += headingResult.h1Inc;\n lastHeadingNivel = headingResult.nivel;\n }\n validateNode(node, tag, line, relPath, ocorrencias, isTemplate);\n });\n verificarDocumento(ocorrencias, relPath, hasDoctype, htmlLangOk, hasCharset, hasViewport, hasTitle, h1Contagem, isTemplate);\n return ocorrencias;\n}\nfunction checkDocTypeRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: OcorrenciaBase[]): void {\n if (!/<!DOCTYPE\\s+html>/i.test(scan) && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.doctype, relPath, 1));\n }\n}\nfunction checkHtmlLangRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: OcorrenciaBase[], lineOfMasked: (idx: number) => number): void {\n const htmlTag = scan.match(/<html[^>]*>/i);\n if (htmlTag && !isTemplate) {\n const hasLang = /\\slang=['\"][^'\" >]+['\"]/i.test(htmlTag[0]);\n if (!hasLang) {\n ocorrencias.push(warn(messages.HtmlMensagens.htmlLang, relPath, lineOfMasked(htmlTag.index ?? 0)));\n }\n }\n}\nfunction checkMetaCharsetRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: OcorrenciaBase[]): void {\n const hasCharsetAttr = /<meta\\s+[^>]*\\bcharset\\s*=\\s*['\"]?[^'\">\\s]+/i.test(scan);\n const hasCharsetInContentTipo = /<meta\\s+[^>]*http-equiv\\s*=\\s*['\"]content-type['\"][^>]*>/i.test(scan) && /charset\\s*=\\s*utf-8/i.test(scan);\n if (!hasCharsetAttr && !hasCharsetInContentTipo && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.metaCharset, relPath, 1));\n }\n}\nfunction checkViewportRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: OcorrenciaBase[]): void {\n if (!/<meta\\s+[^>]*name=[\"']viewport[\"']/i.test(scan) && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.viewport, relPath, 1));\n }\n}\nfunction checkTitleRegex(scan: string, relPath: string, isTemplate: boolean, ocorrencias: OcorrenciaBase[]): void {\n if (!/<title>[^<]*<\\/title>/i.test(scan) && !isTemplate) {\n ocorrencias.push(warn(messages.HtmlMensagens.title, relPath, 1));\n }\n}\nfunction checkLinkTargetBlankRegex(scan: string, relPath: string, ocorrencias: OcorrenciaBase[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<a[^>]*target=['\"]?_blank['\"]?[^>]*>/gi)) {\n const hasRelSafe = /rel=['\"][^'\"]*(noopener|noreferrer)[^'\"]*['\"]/i.test(metrica[0]);\n if (!hasRelSafe) {\n ocorrencias.push(warn(messages.HtmlMensagens.linkTargetBlank, relPath, lineOfMasked(metrica.index)));\n }\n }\n}\nfunction checkImgAltRegex(scan: string, relPath: string, ocorrencias: OcorrenciaBase[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<img[^>]*>/gi)) {\n const isSvg = /\\.svg/i.test(metrica[0]);\n const hasAlt = /\\salt=/.test(metrica[0]);\n const ariaHidden = /\\saria-hidden=['\"]true['\"]/i.test(metrica[0]);\n const ariaLabel = /\\saria-label=/i.test(metrica[0]);\n const rolePresentation = /\\srole=['\"](presentation|none)['\"]/i.test(metrica[0]);\n const dataAttr = /\\s(?:data-)?(?:decorative|icon|symbol)=/i.test(metrica[0]);\n if (!hasAlt && !ariaHidden && !ariaLabel && !rolePresentation && !dataAttr && !isSvg) {\n ocorrencias.push(warn(messages.HtmlMensagens.imgWithoutAlt, relPath, lineOfMasked(metrica.index)));\n }\n }\n}\nfunction checkInlineHandlerRegex(scan: string, relPath: string, ocorrencias: OcorrenciaBase[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/\\son(?:click|change|submit|load|error|mouseover|mouseout|keyup|keydown|focus|blur|input)=/gi)) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineHandler, relPath, lineOfMasked(metrica.index)));\n }\n}\nfunction checkFormRegex(scan: string, relPath: string, ocorrencias: OcorrenciaBase[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<form[^>]*>/gi)) {\n const hasMethod = /\\smethod=/i.test(metrica[0]);\n const hasAction = /\\saction=/i.test(metrica[0]);\n if (!hasMethod) {\n ocorrencias.push(warn(messages.HtmlMensagens.formWithoutMethod, relPath, lineOfMasked(metrica.index)));\n }\n if (!hasAction && !/<form[^>]*data-/i.test(metrica[0])) {\n ocorrencias.push(warn(messages.HtmlMensagens.formWithoutAction, relPath, lineOfMasked(metrica.index)));\n }\n }\n}\nfunction checkInputRegex(scan: string, relPath: string, ocorrencias: OcorrenciaBase[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<input[^>]*>/gi)) {\n const hasAriaLabel = /\\saria-label=/i.test(metrica[0]);\n const hasNome = /\\sname=/i.test(metrica[0]);\n const isHidden = /\\stype=['\"]?hidden['\"]?/i.test(metrica[0]);\n const isButton = /\\stype=['\"]?(button|submit|reset)['\"]/i.test(metrica[0]);\n if (!isHidden && !isButton && !hasAriaLabel && !hasNome) {\n ocorrencias.push(warn(messages.HtmlMensagens.inputWithoutLabel, relPath, lineOfMasked(metrica.index)));\n }\n if (/\\stype=['\"]?password['\"]?\\s/.test(metrica[0]) && !/\\sautocomplete=/i.test(metrica[0])) {\n ocorrencias.push(warn(messages.HtmlMensagens.passwordWithoutAutocomplete, relPath, lineOfMasked(metrica.index)));\n }\n }\n}\nfunction checkLinkNoHrefRegex(scan: string, relPath: string, ocorrencias: OcorrenciaBase[], lineOfMasked: (idx: number) => number): void {\n for (const metrica of scan.matchAll(/<a[^>]*>/gi)) {\n const hasHref = /\\shref=/.test(metrica[0]);\n const href = /\\shref=['\"]([^'\"]*)['\"]/i.exec(metrica[0]);\n if (!hasHref || href?.[1] === '' || href?.[1] === '#') {\n const hasOnClick = /\\sonclick\\s*=/.test(metrica[0]);\n const hasRoleButton = /\\srole=['\"]button['\"]/i.test(metrica[0]);\n const hasTabIndex = /\\stabindex\\s*=/.test(metrica[0]);\n if (!hasOnClick && !hasRoleButton && !hasTabIndex) {\n ocorrencias.push(warn(messages.HtmlMensagens.linkNoHref, relPath, lineOfMasked(metrica.index)));\n }\n }\n }\n}\nfunction checkInlineScriptRegex(src: string, scanNoScriptStyle: string, relPath: string, ocorrencias: OcorrenciaBase[], lineOfScan: (idx: number) => number): void {\n for (const metrica of src.matchAll(/<script[^>]*>[\\s\\S]*?<\\/\\s*script\\b[^>]*\\s*>/gi)) {\n if (typeof metrica.index === 'number') {\n const idx = metrica.index;\n if ((scanNoScriptStyle[idx] ?? ' ') !== '<') continue;\n }\n const isExternal = /\\ssrc=/.test(metrica[0]);\n const innerScriptContent = metrica[0].replace(/^[\\s\\S]*?<script\\b[^>]*>/i, '').replace(/<\\/\\s*script\\b[^>]*\\s*>[\\s\\S]*$/i, '');\n const isEmpty = innerScriptContent.trim().length === 0;\n if (!isExternal && !isEmpty) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineScript, relPath, lineOfScan(metrica.index)));\n }\n }\n}\nfunction checkInlineStyleRegex(src: string, scanNoScriptStyle: string, relPath: string, ocorrencias: OcorrenciaBase[], lineOfScan: (idx: number) => number): void {\n for (const metrica of src.matchAll(/<style[^>]*>[\\s\\S]*?<\\/\\s*style\\b[^>]*\\s*>/gi)) {\n if (typeof metrica.index === 'number') {\n const idx = metrica.index;\n if ((scanNoScriptStyle[idx] ?? ' ') !== '<') continue;\n }\n const isEmpty = /<style\\b[^>]*>\\s*<\\/\\s*style[^>]*>/i.test(metrica[0]);\n if (!isEmpty) {\n ocorrencias.push(warn(messages.HtmlMensagens.inlineStyle, relPath, lineOfScan(metrica.index)));\n }\n }\n}\nfunction collectHtmlIssuesRegex(src: string, relPath: string): OcorrenciaBase[] {\n const ocorrencias: OcorrenciaBase[] = [];\n const isTemplate = /\\.(template\\.html|\\.component\\.html)$/i.test(relPath);\n const lineOfScan = createLineLookup(src).lineAt;\n const scan = maskHtmlComments(maskTagBlocks(maskTagBlocks(src, 'script'), 'style'));\n const lineOfMasked = createLineLookup(scan).lineAt;\n const scanNoScriptStyle = maskHtmlComments(src);\n checkDocTypeRegex(scan, relPath, isTemplate, ocorrencias);\n checkHtmlLangRegex(scan, relPath, isTemplate, ocorrencias, lineOfMasked);\n checkMetaCharsetRegex(scan, relPath, isTemplate, ocorrencias);\n checkViewportRegex(scan, relPath, isTemplate, ocorrencias);\n checkTitleRegex(scan, relPath, isTemplate, ocorrencias);\n checkLinkTargetBlankRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkImgAltRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkInlineHandlerRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkFormRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkInputRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkLinkNoHrefRegex(scan, relPath, ocorrencias, lineOfMasked);\n checkInlineScriptRegex(src, scanNoScriptStyle, relPath, ocorrencias, lineOfScan);\n checkInlineStyleRegex(src, scanNoScriptStyle, relPath, ocorrencias, lineOfScan);\n return ocorrencias;\n}\nfunction collectHtmlIssues(src: string, relPath: string): OcorrenciaBase[] {\n try {\n return collectHtmlIssuesAst(src, relPath);\n } catch {\n return collectHtmlIssuesRegex(src, relPath);\n }\n}\nexport const analistaHtml = criarAnalista({\n nome: 'analista-html',\n categoria: 'markup',\n descricao: 'Heurísticas leves para HTML com convenções padrão.',\n global: false,\n test: (relPath: string): boolean => /\\.(html|htm)$/i.test(relPath),\n aplicar: async (src, relPath): Promise<OcorrenciaBase[] | null> => {\n if (disableEnv) return null;\n const msgs = collectHtmlIssues(src, relPath);\n return msgs.length ? msgs : null;\n }\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"correction-react.js","sourceRoot":"","sources":["../../../../src/analysts/react/corrections/correction-react.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"correction-react.js","sourceRoot":"","sources":["../../../../src/analysts/react/corrections/correction-react.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,CAAC;AASpC,MAAM,UAAU,sBAAsB,CAAC,GAAW,EAAE,QAAgB;IAClE,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC9B,MAAM,WAAW,GAAG,KAAK,GAAG,CAAC,CAAC;QAC9B,IAAI,2BAA2B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,SAAS,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,oBAAoB;gBAC1B,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE;gBACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,0BAA0B,EAAE,eAAe,CAAC;gBACpE,KAAK,EAAE,WAAW;gBAClB,SAAS,EAAE,EAAE;aACd,CAAC,CAAC;QACL,CAAC;QACD,IAAI,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,SAAS,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,sBAAsB;gBAC5B,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE;gBACtB,QAAQ,EAAE,gFAAgF;gBAC1F,KAAK,EAAE,WAAW;gBAClB,SAAS,EAAE,EAAE;aACd,CAAC,CAAC;QACL,CAAC;QACD,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,SAAS,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,sBAAsB;gBAC5B,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE;gBACtB,QAAQ,EAAE,uEAAuE;gBACjF,KAAK,EAAE,WAAW;gBAClB,SAAS,EAAE,EAAE;aACd,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,SAAS,CAAC;AACnB,CAAC;AACD,MAAM,CAAC,MAAM,eAAe,GAAa;IACvC,IAAI,EAAE,kBAAkB;IACxB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,4CAA4C;IACvD,IAAI,EAAE,CAAC,OAAe,EAAW,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;IACjE,OAAO,EAAE,CAAC,GAAW,EAAE,OAAe,EAAE,IAA2B,EAAgB,EAAE;QACnF,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,sBAAsB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC;YAC3C,IAAI,EAAE,cAAc,IAAI,CAAC,IAAI,EAAE;YAC/B,KAAK,EAAE,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YAC7C,QAAQ,EAAE,QAAQ,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;YACpE,OAAO;YACP,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,UAAU,IAAI,CAAC,QAAQ,UAAU,IAAI,CAAC,QAAQ,gBAAgB,IAAI,CAAC,SAAS,GAAG;SAC1F,CAAC,CAAC,CAAC;IACN,CAAC;CACF,CAAC","sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * [CHAVE-INGLESA] Correções automáticas para React\n *\n * Fornece correções sugeridas para problemas comuns em React:\n * - Adicionar key prop em listas\n * - Substituir dangerouslySetInnerHTML\n * - Extrair handlers inline\n */\n\nimport type { NodePath } from '@babel/traverse';\nimport type { Node } from '@babel/types';\nimport { messages } from '@core/messages';\nimport { splitLines } from '@shared/helpers';\n\nimport type { Analista, Ocorrencia } from '@';\nimport { criarOcorrencia } from '@';\n\nexport interface ReactCorrection {\n tipo: string;\n original: string;\n sugerido: string;\n linha: number;\n confianca: number;\n}\nexport function detectarCorrecoesReact(src: string, _relPath: string): ReactCorrection[] {\n const correcoes: ReactCorrection[] = [];\n const linhas = splitLines(src);\n linhas.forEach((linha, index) => {\n const numeroLinha = index + 1;\n if (/key=\\{.*(?:index|i|idx)\\}/.test(linha)) {\n correcoes.push({\n tipo: 'react-index-as-key',\n original: linha.trim(),\n sugerido: linha.replace(/key=\\{.*?(index|i|idx)\\}/, 'key={item.id}'),\n linha: numeroLinha,\n confianca: 80\n });\n }\n if (/dangerouslySetInnerHTML/.test(linha)) {\n correcoes.push({\n tipo: 'react-dangerous-html',\n original: linha.trim(),\n sugerido: '// Use: <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html) }} />',\n linha: numeroLinha,\n confianca: 90\n });\n }\n if (/onClick=\\{[^}]*=>/.test(linha)) {\n correcoes.push({\n tipo: 'react-inline-handler',\n original: linha.trim(),\n sugerido: '// Extraia para: const handleClick = useCallback(() => {...}, [deps])',\n linha: numeroLinha,\n confianca: 70\n });\n }\n });\n return correcoes;\n}\nexport const correctionReact: Analista = {\n nome: 'correction-react',\n categoria: 'framework',\n descricao: 'Correções automáticas para problemas React',\n test: (relPath: string): boolean => /\\.(jsx|tsx)$/i.test(relPath),\n aplicar: (src: string, relPath: string, _ast: NodePath<Node> | null): Ocorrencia[] => {\n if (!src) return [];\n const correcoes = detectarCorrecoesReact(src, relPath);\n return correcoes.map(elem => criarOcorrencia({\n tipo: `correction-${elem.tipo}`,\n nivel: elem.confianca > 85 ? 'aviso' : 'info',\n mensagem: messages.SharedCommonMensagens.correcaoSugerida(elem.tipo),\n relPath,\n linha: elem.linha,\n sugestao: `[ERRO] ${elem.original}\\n[OK] ${elem.sugerido}\\nConfiança: ${elem.confianca}%`\n }));\n }\n};"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyst-shell.d.ts","sourceRoot":"","sources":["../../../../src/analysts/shell/analysts/analyst-shell.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analyst-shell.d.ts","sourceRoot":"","sources":["../../../../src/analysts/shell/analysts/analyst-shell.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC;AAOpC,eAAO,MAAM,aAAa;;;;oBAIR,MAAM;mBACD,MAAM,WAAW,MAAM,KAAG,OAAO,CAAC,UAAU,EAAE,CAAC;;CAoHpE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyst-shell.js","sourceRoot":"","sources":["../../../../src/analysts/shell/analysts/analyst-shell.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"analyst-shell.js","sourceRoot":"","sources":["../../../../src/analysts/shell/analysts/analyst-shell.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: MIT\nimport { messages } from '@core/messages';\n\nimport type { Ocorrencia } from '@';\nimport { criarAnalista, criarOcorrencia } from '@';\n\n/**\n * Analista de Shell Script\n * Detecta práticas inseguras, comandos perigosos e má organização em scripts .sh, .bash, etc.\n */\nexport const analistaShell = criarAnalista({\n nome: 'analista-shell',\n categoria: 'infrastructure',\n descricao: 'Analisa scripts Shell em busca de comandos perigosos, insegurança e falta de boas práticas.',\n test: (relPath: string) => /\\.(sh|bash|zsh|fish)$/i.test(relPath),\n aplicar: async (src: string, relPath: string): Promise<Ocorrencia[]> => {\n const ocorrencias: Ocorrencia[] = [];\n const linhas = src.split('\\n');\n\n // 1. Verificar Shebang (Boas Práticas)\n if (linhas.length > 0 && !linhas[0].startsWith('#!')) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'codigo-fragil',\n nivel: 'aviso',\n mensagem: messages.AnalistaShellMensagens.missingShebang,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaShellMensagens.missingShebangSugestao\n }));\n }\n\n // 2. Verificar 'set -e' ou 'set -o pipefail' (Tratamento de Erros)\n const srcCompleto = src.toLowerCase();\n if (!srcCompleto.includes('set -e') && !srcCompleto.includes('set -o pipefail')) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'codigo-fragil',\n nivel: 'info',\n mensagem: messages.AnalistaShellMensagens.missingSetE,\n relPath,\n linha: 1,\n sugestao: messages.AnalistaShellMensagens.missingSetESugestao\n }));\n }\n\n linhas.forEach((linha, index) => {\n const numeroLinha = index + 1;\n const linhaTrim = linha.trim();\n\n // Ignorar comentários\n if (linhaTrim.startsWith('#')) return;\n\n // 3. Uso de eval (Insegurança)\n if (/\\beval\\s+/.test(linha)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'vulnerabilidade-seguranca',\n nivel: 'erro',\n mensagem: messages.AnalistaShellMensagens.evalUsage,\n relPath,\n linha: numeroLinha,\n sugestao: messages.AnalistaShellMensagens.evalUsageSugestao\n }));\n }\n\n // 4. Variáveis não aspeadas (Fragilidade)\n // Detecta patterns como $VAR sem aspas (ex: echo $USER, mas ignora em loops/condicionais complexas)\n if (/\\$(\\w+)\\b/.test(linha) && !/[\"'].*\\$\\w+.*[\"']/.test(linha) && !/\\$\\(.*\\)/.test(linha) && !/^\\s*(for|while|if|case|read)\\s+/.test(linhaTrim)) {\n // Heurística simples: se a variável aparece sozinha ou em comando comum\n if (/\\b(echo|ls|cd|rm|cp|mv)\\s+.*\\$\\w+/.test(linhaTrim)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'codigo-fragil',\n nivel: 'info',\n mensagem: messages.AnalistaShellMensagens.unquotedVariable,\n relPath,\n linha: numeroLinha,\n sugestao: messages.AnalistaShellMensagens.unquotedVariableSugestao\n }));\n }\n }\n\n // 5. Comandos perigosos (Segurança/Risco)\n if (/\\brm\\s+-rf\\s+\\/(\\s|$|['\"`])/.test(linha)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'vulnerabilidade-seguranca',\n nivel: 'critica',\n mensagem: messages.AnalistaShellMensagens.rmRfRoot,\n relPath,\n linha: numeroLinha,\n sugestao: messages.AnalistaShellMensagens.rmRfRootSugestao\n }));\n }\n\n // 6. curl/wget pipe to sh (Risco de Segurança)\n if (/(curl|wget).*(|\\s)sh(\\s|$)/.test(linha)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'vulnerabilidade-seguranca',\n nivel: 'alta',\n mensagem: messages.AnalistaShellMensagens.curlPipeSh,\n relPath,\n linha: numeroLinha,\n sugestao: messages.AnalistaShellMensagens.curlPipeShSugestao\n }));\n }\n\n // 7. Senhas em variáveis (Segurança)\n if (/\\b(password|pass|secret|token|key)\\b\\s*=\\s*['\"].*['\"]/i.test(linha)) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'vulnerabilidade-seguranca',\n nivel: 'erro',\n mensagem: messages.AnalistaShellMensagens.hardcodedPassword,\n relPath,\n linha: numeroLinha,\n sugestao: messages.AnalistaShellMensagens.hardcodedPasswordSugestao\n }));\n }\n\n // 8. Uso de sudo (Boas Práticas de Infra)\n if (/\\bsudo\\s+/.test(linha) && !relPath.includes('setup') && !relPath.includes('install')) {\n ocorrencias.push(criarOcorrencia({\n tipo: 'codigo-fragil',\n nivel: 'info',\n mensagem: messages.AnalistaShellMensagens.sudoUsage,\n relPath,\n linha: numeroLinha,\n sugestao: messages.AnalistaShellMensagens.sudoUsageSugestao\n }));\n }\n });\n\n return ocorrencias;\n },\n global: false\n});\n"]}
|