From d612c173131928abd22becf89503a61bb1719392 Mon Sep 17 00:00:00 2001 From: Rafael Joaquim Date: Thu, 21 May 2026 20:50:52 -0300 Subject: [PATCH 1/3] subindo workflow git --- .github/codeql/codeql-config.yml | 13 ++ .github/scripts/security-review.js | 158 +++++++++++++++++++++++ .github/workflows/devsecops-security.yml | 79 ++++++++++++ sobre este projeto.md | 112 ++++++++++++++++ 4 files changed, 362 insertions(+) create mode 100644 .github/codeql/codeql-config.yml create mode 100644 .github/scripts/security-review.js create mode 100644 .github/workflows/devsecops-security.yml create mode 100644 sobre este projeto.md diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 00000000..2717f1e5 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,13 @@ +name: ConvNetJS Security Scanning +rules: + - query: security-and-quality + - query: security-extended + - query: security-audit + - query: experimental + - query: performance + +exclude: + - path: test/** + - path: demo/** + - path: build/** + - path: compile/** diff --git a/.github/scripts/security-review.js b/.github/scripts/security-review.js new file mode 100644 index 00000000..674f479f --- /dev/null +++ b/.github/scripts/security-review.js @@ -0,0 +1,158 @@ +const fs = require('fs'); +const path = require('path'); +const https = require('https'); + +const sarifPath = process.argv[2] || 'results.sarif'; +const reportPath = process.argv[3] || 'security-report.md'; +const openAiKey = process.env.OPENAI_API_KEY; +const openAiModel = process.env.OPENAI_MODEL || 'gpt-4o-mini'; + +function loadSarif(filePath) { + if (!fs.existsSync(filePath)) { + throw new Error(`SARIF file not found: ${filePath}`); + } + return JSON.parse(fs.readFileSync(filePath, 'utf8')); +} + +function summarizeFindings(results) { + const severityOrder = ['error', 'warning', 'note', 'none']; + const severityCounts = results.reduce((acc, item) => { + const severity = (item.level || item.kind || 'warning').toLowerCase(); + acc[severity] = (acc[severity] || 0) + 1; + return acc; + }, {}); + + const byRule = results.reduce((acc, item) => { + const ruleId = item.ruleId || 'unknown'; + acc[ruleId] = acc[ruleId] || { count: 0, message: [] }; + acc[ruleId].count += 1; + if (item.message && item.message.text) acc[ruleId].message.push(item.message.text); + return acc; + }, {}); + + return { severityCounts, byRule }; +} + +function formatReport(sarif, summary, topFindings) { + const totalFindings = topFindings.length; + const severityLines = Object.entries(summary.severityCounts) + .sort(([a], [b]) => severityOrder.indexOf(a) - severityOrder.indexOf(b)) + .map(([level, count]) => `- **${level}**: ${count}`) + .join('\n'); + + const findingLines = topFindings.map((item, index) => { + const location = item.locations && item.locations[0] && item.locations[0].physicalLocation; + const file = location && location.artifactLocation && location.artifactLocation.uri; + const region = location && location.region; + const line = region ? region.startLine : 'N/A'; + return [`### Finding ${index + 1}`, + `- **Rule**: ${item.ruleId || 'unknown'}`, + `- **Severity**: ${item.level || item.kind || 'warning'}`, + `- **Message**: ${item.message && item.message.text ? item.message.text : 'N/A'}`, + `- **Location**: ${file || 'unknown'}:${line}`, + ''].join('\n'); + }).join('\n'); + + return [`# Security Report`, + '', + `## Summary`, + '', + `- Total findings: **${totalFindings}**`, + severityLines ? `\n${severityLines}` : '', + '', + `## Top Findings`, + '', + findingLines || 'No findings detected.', + '', + `## Review Notes`, + '', + `The report was generated automatically by the GitHub Actions DevSecOps pipeline.`, + openAiKey ? `An LLM review was requested and its analysis is included below.` : `LLM review was skipped because OPENAI_API_KEY is not configured.`, + '', + `---`, + '', + `*Generated by the DevSecOps pipeline.*`].join('\n'); +} + +function extractTopFindings(results, max = 8) { + return results.slice(0, max); +} + +async function callOpenAI(prompt) { + const body = JSON.stringify({ + model: openAiModel, + messages: [{ role: 'system', content: 'Você é um assistente de segurança de software. Revise os resultados SARIF e gere um resumo conciso com risco, gravidade e recomendações.' }, + { role: 'user', content: prompt }], + max_tokens: 500, + temperature: 0.2 + }); + + const options = { + hostname: 'api.openai.com', + path: '/v1/chat/completions', + method: 'POST', + headers: { + 'Authorization': `Bearer ${openAiKey}`, + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(body) + } + }; + + return new Promise((resolve, reject) => { + const req = https.request(options, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => { + if (res.statusCode >= 200 && res.statusCode < 300) { + try { + const json = JSON.parse(data); + const content = json.choices && json.choices[0] && json.choices[0].message && json.choices[0].message.content; + resolve(content || 'LLM review completed but no content was returned.'); + } catch (error) { + reject(new Error(`Falha ao analisar retorno do OpenAI: ${error.message}`)); + } + } else { + reject(new Error(`OpenAI API error ${res.statusCode}: ${data}`)); + } + }); + }); + + req.on('error', reject); + req.write(body); + req.end(); + }); +} + +async function main() { + const sarif = loadSarif(sarifPath); + const results = (sarif.runs || []).flatMap(run => run.results || []); + const summary = summarizeFindings(results); + const topFindings = extractTopFindings(results); + let report = formatReport(sarif, summary, topFindings); + + if (openAiKey && results.length > 0) { + const prompt = `Aqui estão os ${results.length} resultados SARIF mais importantes. Forneça um resumo de risco, explique os impactos e indique ações corretivas relevantes. Exiba como listas claras e concisas. \n\n` + + topFindings.map((item, index) => { + const location = item.locations && item.locations[0] && item.locations[0].physicalLocation; + const file = location && location.artifactLocation && location.artifactLocation.uri; + const region = location && location.region; + const line = region ? region.startLine : 'N/A'; + return `${index + 1}. Rule: ${item.ruleId || 'unknown'}; Severity: ${item.level || item.kind || 'warning'}; File: ${file || 'unknown'}:${line}; Message: ${item.message && item.message.text ? item.message.text : 'N/A'}`; + }).join('\n'); + + try { + const llmReview = await callOpenAI(prompt); + report += '\n\n## LLM Review\n\n' + llmReview + '\n'; + } catch (error) { + report += `\n\n## LLM Review\n\nFalha ao obter análise LLM: ${error.message}\n`; + } + } + + fs.writeFileSync(reportPath, report, 'utf8'); + console.log(`Security report written to ${reportPath}`); +} + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/.github/workflows/devsecops-security.yml b/.github/workflows/devsecops-security.yml new file mode 100644 index 00000000..748f01a0 --- /dev/null +++ b/.github/workflows/devsecops-security.yml @@ -0,0 +1,79 @@ +name: DevSecOps Security Pipeline + +on: + push: + branches: + - main + - master + - develop + pull_request: + types: [opened, synchronize, reopened] + workflow_dispatch: + schedule: + - cron: '0 3 * * *' + +jobs: + codeql: + name: CodeQL SAST Scan + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + analysis: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: javascript + config-file: .github/codeql/codeql-config.yml + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@v3 + with: + output: results.sarif + + - name: Upload SARIF artifact + uses: actions/upload-artifact@v4 + with: + name: codeql-sarif + path: results.sarif + + security_review: + name: LLM Security Review & PR Comment + runs-on: ubuntu-latest + needs: codeql + if: always() + permissions: + contents: read + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download SARIF artifact + uses: actions/download-artifact@v4 + with: + name: codeql-sarif + + - name: Generate security report + run: | + node .github/scripts/security-review.js results.sarif security-report.md + + - name: Upload security report artifact + uses: actions/upload-artifact@v4 + with: + name: security-report + path: security-report.md + + - name: Comment on pull request + if: github.event_name == 'pull_request' + uses: peter-evans/create-or-update-comment@v6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.pull_request.number }} + body-file: security-report.md + edit-mode: replace diff --git a/sobre este projeto.md b/sobre este projeto.md new file mode 100644 index 00000000..cb793d58 --- /dev/null +++ b/sobre este projeto.md @@ -0,0 +1,112 @@ +# Sobre este projeto + +## Visão geral do repositório + +Esse repositório é o `convnetjs` do Andrej Karpathy. É uma biblioteca JavaScript para redes neurais e convolucionais, com foco em uso no navegador e compatibilidade com Node.js. Não é uma aplicação de servidor com banco de dados; é um motor de Deep Learning escrito em JS. + +## Para que serve + +- Implementa redes neurais em JavaScript. +- Suporta: + - camadas totalmente conectadas (`fc`) + - camadas convolucionais + - pooling + - normalização + - funções de perda como `softmax`, `SVM`, `L2` + - otimizadores / treinadores como SGD, Adagrad, Adadelta + - módulo experimental de Reinforcement Learning (Deep Q Learning) +- Inclui demos de exemplos em browser, como MNIST, CIFAR-10, regressão, autoencoder e RL. + +## Linguagem e execução + +- Linguagem: **JavaScript** +- Execução: + - browser + - Node.js (há wrappers `module.exports` em `src/convnet_export.js` e em `build/*`) +- Não há TypeScript. +- Não há `package.json` neste workspace, mas há `bower.json` indicando uso como biblioteca front-end/AMD/Node. + +## Arquitetura do software + +### Camadas principais + +- `src/` + - Contém a implementação modular do motor de rede neural. + - Arquivos principais: + - `convnet_net.js` — rede neural, criação de camadas e fluxo forwards/backwards + - `convnet_trainers.js` — algoritmos de treinamento + - `convnet_vol.js` / `convnet_vol_util.js` — tensores / volumes de dados + - `convnet_util.js` — utilitários gerais + - `convnet_layers_*` — implementação de camadas e funções de ativação: + - `dotproducts`, `dropout`, `input`, `loss`, `nonlinearities`, `normalization`, `pool` + - `convnet_magicnet.js` — rede “mágica” / utilitários de alto nível + - `convnet_export.js` — exportação para Node.js / CommonJS + +### Build e distribuição + +- `build/` + - Contém versões concatenadas/minificadas geradas: + - `convnet.js` + - `convnet-min.js` + - Também há outros módulos compilados como `deepqlearn.js`, `util.js`, `vis.js` +- `compile/` + - Contém `build.xml` para compilar o projeto com Apache Ant e `yuicompressor`. + +### Demos + +- `demo/` + - HTML e JS para demos interativas no browser. + - Usa arquivos estáticos e exemplos de treinamento/visualização. + - Não há backend próprio; os demos são páginas estáticas. + +## Organização de pastas + +- `src/` — código-fonte da biblioteca +- `build/` — saída compilada / bundle JS +- `compile/` — script de build Ant +- `demo/` — demonstrações em HTML/JS/CSS +- `test/` — testes Jasmine +- `bower.json` — metadados do pacote Bower +- `Readme.md` — documentação e exemplos + +## Banco de dados e APIs externas + +- **Não há banco de dados** neste repositório. +- **Não há tabelas** ou modelagem de dados de banco de dados. +- Não há evidência de integração com nenhuma API externa no código principal. +- As demos usam apenas browser APIs e bibliotecas JS locais. + +## Dependências e bibliotecas usadas + +### Dependências internas / bundled + +- Biblioteca principal: `convnetjs` em `src/` +- Demos utilizam bibliotecas front-end empacotadas localmente: + - `demo/js/jquery-1.8.3.min.js` + - `demo/js/pica.js` + - possivelmente outras utilidades JS para manipulação de imagem e UI + +### Dependências de build ou pacote + +- `bower.json` declara `main: build/convnet.js`, e suporte para: + - AMD + - ES6 + - globals + - Node + - YUI + +## Testes + +- Existe um conjunto de testes em `test/jasmine/` +- Arquivos relevantes: + - `test/jasmine/SpecRunner.html` + - `test/jasmine/spec/NeuralNetSpec.js` +- O framework de teste usado é **Jasmine 2.0** +- Os testes estão configurados para rodar no browser via HTML runner. + +## Informações relevantes adicionais + +- O README diz que o projeto não está mais ativamente mantido. +- A compilação do JS é feita por concatenação dos arquivos `src/` e minificação com `yuicompressor`. +- Há suporte histórico para uso com `npm install convnetjs`, mesmo que aqui não exista `package.json`. +- O foco é em pesquisa/educação de redes neurais, não em aplicação web backend. From eaf26503856980806342249b917c61e8fa9b821c Mon Sep 17 00:00:00 2001 From: Rafael Joaquim Date: Thu, 21 May 2026 20:54:14 -0300 Subject: [PATCH 2/3] subindo workflow git --- .github/workflows/devsecops-security.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/devsecops-security.yml b/.github/workflows/devsecops-security.yml index 748f01a0..68216008 100644 --- a/.github/workflows/devsecops-security.yml +++ b/.github/workflows/devsecops-security.yml @@ -20,7 +20,7 @@ jobs: actions: read contents: read security-events: write - analysis: write + #analysis: write steps: - name: Checkout repository uses: actions/checkout@v4 From 511ad87eb9be77fdabaccfa3372b1c0a384fb452 Mon Sep 17 00:00:00 2001 From: Rafael Joaquim Date: Thu, 21 May 2026 22:08:19 -0300 Subject: [PATCH 3/3] =?UTF-8?q?subindo=20refatora=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/devsecops-security.yml | 18 +- demo/autoencoder.html | 1 + demo/cifar10.html | 1 + demo/classify2d.html | 3 +- demo/image_regression.html | 3 +- demo/js/autoencoder.js | 5 +- demo/js/classify2d.js | 7 +- demo/js/image_regression.js | 5 +- demo/js/images-demo.js | 10 +- demo/js/regression.js | 7 +- demo/js/rldemo.js | 5 +- demo/js/safe-config.js | 289 ++++++++++++ demo/js/trainers.js | 5 +- demo/mnist.html | 1 + demo/regression.html | 3 +- demo/rldemo.html | 11 +- demo/trainers.html | 1 + docs/casos-de-uso.md | 250 +++++++++++ docs/contabilizacao-problemas-refatoracao.md | 150 +++++++ docs/diagramas-fluxos-classes.md | 419 ++++++++++++++++++ docs/documento-de-requisitos-de-software.md | 151 +++++++ docs/historias-de-usuario.md | 103 +++++ docs/plano-de-refatoracao.md | 243 ++++++++++ .../relatorio-vulnerabilidades-code-smells.md | 375 ++++++++++++++++ test/jasmine/SpecRunner.html | 18 +- test/jasmine/lib/jasmine-2.0.0/jasmine.js | 4 +- test/jasmine/spec/SafeConfigSpec.js | 66 +++ 27 files changed, 2129 insertions(+), 25 deletions(-) create mode 100644 demo/js/safe-config.js create mode 100644 docs/casos-de-uso.md create mode 100644 docs/contabilizacao-problemas-refatoracao.md create mode 100644 docs/diagramas-fluxos-classes.md create mode 100644 docs/documento-de-requisitos-de-software.md create mode 100644 docs/historias-de-usuario.md create mode 100644 docs/plano-de-refatoracao.md create mode 100644 docs/relatorio-vulnerabilidades-code-smells.md create mode 100644 test/jasmine/spec/SafeConfigSpec.js diff --git a/.github/workflows/devsecops-security.yml b/.github/workflows/devsecops-security.yml index 68216008..37c4f34b 100644 --- a/.github/workflows/devsecops-security.yml +++ b/.github/workflows/devsecops-security.yml @@ -48,7 +48,7 @@ jobs: needs: codeql if: always() permissions: - contents: read + contents: write pull-requests: write steps: - name: Checkout repository @@ -69,6 +69,22 @@ jobs: name: security-report path: security-report.md + - name: Create automatic security report pull request + if: github.event_name != 'pull_request' + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "docs: update automated security report" + title: "docs: update automated security report" + body: | + This pull request was generated automatically by the DevSecOps Security Pipeline. + + It updates the generated `security-report.md` file from the latest CodeQL SARIF results. + branch: automated/security-report + base: ${{ github.ref_name }} + add-paths: security-report.md + labels: security, automated-pr + - name: Comment on pull request if: github.event_name == 'pull_request' uses: peter-evans/create-or-update-comment@v6 diff --git a/demo/autoencoder.html b/demo/autoencoder.html index e2d37f18..234c8ca1 100644 --- a/demo/autoencoder.html +++ b/demo/autoencoder.html @@ -13,6 +13,7 @@ + diff --git a/demo/cifar10.html b/demo/cifar10.html index a8a1594a..80ac0b5b 100644 --- a/demo/cifar10.html +++ b/demo/cifar10.html @@ -12,6 +12,7 @@ + diff --git a/demo/classify2d.html b/demo/classify2d.html index c933ae6c..cf601aef 100644 --- a/demo/classify2d.html +++ b/demo/classify2d.html @@ -7,6 +7,7 @@ +