diff --git a/.github/workflows/shieldci.yml b/.github/workflows/shieldci.yml index 2363160..d782422 100644 --- a/.github/workflows/shieldci.yml +++ b/.github/workflows/shieldci.yml @@ -1,8 +1,11 @@ name: ShieldCI Security Scan on: + push: + branches: [main, master] pull_request: branches: [main, master] + workflow_dispatch: jobs: shieldci-scan: @@ -13,81 +16,79 @@ jobs: - name: Checkout target repository uses: actions/checkout@v4 - - name: Get PR metadata + - name: Gather metadata id: meta run: | echo "repo=${{ github.repository }}" >> "$GITHUB_OUTPUT" - echo "branch=${{ github.head_ref }}" >> "$GITHUB_OUTPUT" - echo "commit=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT" - echo "commit_msg=$(git log -1 --pretty=%s 2>/dev/null || echo 'PR scan')" >> "$GITHUB_OUTPUT" + if [ "${{ github.event_name }}" = "pull_request" ]; then + echo "branch=${{ github.head_ref }}" >> "$GITHUB_OUTPUT" + echo "commit=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT" + echo "trigger=PR" >> "$GITHUB_OUTPUT" + else + echo "branch=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" + echo "commit=${{ github.sha }}" >> "$GITHUB_OUTPUT" + echo "trigger=${{ github.event_name }}" >> "$GITHUB_OUTPUT" + fi + echo "commit_msg=$(git log -1 --pretty=%s 2>/dev/null || echo 'scan')" >> "$GITHUB_OUTPUT" - name: Check ShieldCI engine is available run: | if [ ! -f "$HOME/Desktop/ShieldCI/target/release/shield-ci" ]; then - echo "ERROR: ShieldCI engine not found at ~/Desktop/ShieldCI/target/release/shield-ci" - echo "Please build the engine first: cd ~/Desktop/ShieldCI && cargo build --release" + echo "ERROR: ShieldCI engine not found" exit 1 fi - - name: Copy shieldci.yml to engine tests directory + - name: Copy shieldci.yml config run: | if [ -f "shieldci.yml" ]; then cp shieldci.yml "$HOME/Desktop/ShieldCI/tests/shieldci.yml" - echo "Copied shieldci.yml config" - else - echo "No shieldci.yml found in repo root, engine will auto-detect" fi - - name: Copy target repo to engine tests directory + - name: Copy target repo to engine run: | rm -rf "$HOME/Desktop/ShieldCI/tests/repo" cp -r "$GITHUB_WORKSPACE" "$HOME/Desktop/ShieldCI/tests/repo" - name: Run ShieldCI engine id: scan - working-directory: ${{ env.HOME }}/Desktop/ShieldCI/tests run: | START_TIME=$(date +%s) cd "$HOME/Desktop/ShieldCI/tests" "$HOME/Desktop/ShieldCI/target/release/shield-ci" 2>&1 | tee scan_output.log || true END_TIME=$(date +%s) - DURATION=$((END_TIME - START_TIME)) - echo "duration=${DURATION}s" >> "$GITHUB_OUTPUT" + echo "duration=$((END_TIME - START_TIME))s" >> "$GITHUB_OUTPUT" - name: Push results to ShieldCI dashboard if: always() env: - SHIELDCI_API_URL: ${{ secrets.SHIELDCI_API_URL }} - SHIELDCI_API_KEY: ${{ secrets.SHIELDCI_API_KEY }} + SHIELDCI_API_URL: http://localhost:3000 + SHIELDCI_API_KEY: fc09420a3737855a3094ff7831a6219565cee6777a0fbeec SHIELDCI_REPO: ${{ steps.meta.outputs.repo }} SHIELDCI_BRANCH: ${{ steps.meta.outputs.branch }} SHIELDCI_COMMIT: ${{ steps.meta.outputs.commit }} SHIELDCI_COMMIT_MSG: ${{ steps.meta.outputs.commit_msg }} SHIELDCI_DURATION: ${{ steps.scan.outputs.duration }} - SHIELDCI_TRIGGERED_BY: PR - SHIELDCI_RESULTS_FILE: ${{ env.HOME }}/Desktop/ShieldCI/tests/shield_results.json + SHIELDCI_TRIGGERED_BY: ${{ steps.meta.outputs.trigger }} + SHIELDCI_RESULTS_FILE: ${{ runner.temp }}/../../../Desktop/ShieldCI/tests/shield_results.json run: | + export SHIELDCI_RESULTS_FILE="$HOME/Desktop/ShieldCI/tests/shield_results.json" python3 "$HOME/Desktop/ShieldCI/push_results.py" - name: Post scan summary as PR comment - if: always() + if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const fs = require('fs'); - const reportPath = `${process.env.HOME}/Desktop/ShieldCI/tests/SHIELD_REPORT.md`; + const reportPath = process.env.HOME + '/Desktop/ShieldCI/tests/SHIELD_REPORT.md'; let report = 'Scan completed but no report was generated.'; try { report = fs.readFileSync(reportPath, 'utf8'); - if (report.length > 60000) { - report = report.substring(0, 60000) + '\n\n... (truncated)'; - } - } catch (e) { - report = 'Could not read scan report.'; - } + if (report.length > 60000) report = report.substring(0, 60000) + '\n\n... (truncated)'; + } catch (e) { report = 'Could not read scan report.'; } await github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - body: `## 🛡️ ShieldCI Security Scan Results\n\n${report}` + body: '## 🛡️ ShieldCI Security Scan Results\n\n' + report }); diff --git a/run.sh b/run.sh old mode 100644 new mode 100755 diff --git a/tests/repo b/tests/repo new file mode 160000 index 0000000..7d5bc89 --- /dev/null +++ b/tests/repo @@ -0,0 +1 @@ +Subproject commit 7d5bc89eb71a33a435477526145bcea42baafad6 diff --git a/tests/scan_output.log b/tests/scan_output.log new file mode 100644 index 0000000..f8b73e5 --- /dev/null +++ b/tests/scan_output.log @@ -0,0 +1,64 @@ +🛡️ Booting ShieldCI Orchestrator... +📋 Loaded shieldci.yml configuration +⚙️ Running build: npm install + +up to date, audited 192 packages in 685ms + +26 packages are looking for funding + run `npm fund` for details + +7 vulnerabilities (2 low, 5 high) + +To address all issues (including breaking changes), run: + npm audit fix --force + +Run `npm audit` for details. +🚀 Launching Node.js server on http://127.0.0.1:3000... +⏳ Waiting for target http://127.0.0.1:3000 to come online... +✅ Target is up and responding! +Recursively flattening codebase for full context... + +📋 Test Plan (5 tests): + 1. [RECON: Port Scan] nmap_scan → http://host.docker.internal:3000 + 2. [RECON: Security Headers] check_headers → http://host.docker.internal:3000 + 3. [VULN SCAN: Web Server] nikto_scan → http://host.docker.internal:3000 + 4. [DISCOVERY: Hidden Paths] gobuster_scan → http://host.docker.internal:3000 + 5. [SQLi: GET /login] sqlmap_scan → http://host.docker.internal:3000/login?username=test + +--- Test 1/5: RECON: Port Scan --- +🤝 Initiating MCP Handshake & Strike: nmap_scan on http://host.docker.internal:3000 +[03/07/26 02:07:37] INFO Processing request of type server.py:720 + CallToolRequest + +--- Test 2/5: RECON: Security Headers --- +🤝 Initiating MCP Handshake & Strike: check_headers on http://host.docker.internal:3000 +[03/07/26 02:07:38] INFO Processing request of type server.py:720 + CallToolRequest + +--- Test 3/5: VULN SCAN: Web Server --- +🤝 Initiating MCP Handshake & Strike: nikto_scan on http://host.docker.internal:3000 +[03/07/26 02:07:39] INFO Processing request of type server.py:720 + CallToolRequest + +--- Test 4/5: DISCOVERY: Hidden Paths --- +🤝 Initiating MCP Handshake & Strike: gobuster_scan on http://host.docker.internal:3000 +[03/07/26 02:07:53] INFO Processing request of type server.py:720 + CallToolRequest + +--- Test 5/5: SQLi: GET /login --- +🤝 Initiating MCP Handshake & Strike: sqlmap_scan on http://host.docker.internal:3000/login?username=test +[03/07/26 02:07:54] INFO Processing request of type server.py:720 + CallToolRequest + +--- Adaptive Strike 1 --- +🧠 Invoking local model via Ollama API... +🤝 Initiating MCP Handshake & Strike: sqlmap_scan on http://host.docker.internal:3000/login?username=admin +[03/07/26 02:08:01] INFO Processing request of type server.py:720 + CallToolRequest + +--- Adaptive Strike 2 --- +🧠 Invoking local model via Ollama API... +🤝 Initiating MCP Handshake & Strike: sqlmap_scan on http://host.docker.internal:3000/login?username=test +[03/07/26 02:08:09] INFO Processing request of type server.py:720 + CallToolRequest +📝 Compiling final security assessment... diff --git a/tests/shield_results.json b/tests/shield_results.json new file mode 100644 index 0000000..3192e05 --- /dev/null +++ b/tests/shield_results.json @@ -0,0 +1,5 @@ +{ + "status": "Clean", + "vulnerabilities": [], + "report_markdown": "The provided code snippets are quite extensive, and I'll focus on the most critical vulnerabilities and provide corrected versions.\n\n**1. SQL Injection Vulnerability in `/login` Route**\n\nThe `GET /login` route is vulnerable to SQL injection. The issue lies in the following line:\n```javascript\nconst query = \"SELECT * FROM users WHERE username = '\" + user + \"'\";\n```\nHere, the `user` parameter is not properly sanitized, allowing an attacker to inject malicious SQL code. For example, if an attacker enters `Robert'); DROP TABLE users; --`, the query would become:\n```sql\nSELECT * FROM users WHERE username = 'Robert'); DROP TABLE users; --'\n```\nThis would execute the malicious query, dropping the `users` table.\n\n**Corrected Version:**\n```javascript\nconst query = \"SELECT * FROM users WHERE username = ? \";\ndb.get(query, [user], (err, row) => {\n // ...\n});\n```\nIn this corrected version, we use a parameterized query with a parameter `?`, which is replaced with the actual `user` value. This prevents SQL injection attacks.\n\n**2. Code Injection Vulnerability in `app.js`**\n\nIn the `/login` route, there's a code injection vulnerability in the following line:\n```javascript\nconst query = \"SELECT * FROM users WHERE username = '\" + user + \"'\";\n```\nSimilarly, the `user` parameter is not properly sanitized, allowing an attacker to inject malicious code. However, this vulnerability is more related to the fact that the query is being constructed as a string, making it vulnerable to code injection.\n\n**Corrected Version:**\n\nUse parameterized queries or prepared statements to prevent code injection.\n\n**3. Path Traversal Vulnerability in `app.js`**\n\nIn the `/login` route, there's a path traversal vulnerability in the following line:\n```javascript\nconst user = req.query.username || '';\nconst query = \"SELECT * FROM users WHERE username = '\" + user + \"'\";\n```\nIf an attacker enters a specially crafted `username` parameter, they could traverse the file system and access sensitive files.\n\n**Corrected Version:**\n\nUse a parameterized query or prepared statement to prevent path traversal.\n\n**4. Security Misconfiguration in `app.js`**\n\nThe `/login` route uses the `sqlite3` library, which is not secure for production environments. The `serialize()` method is used, which can lead to unexpected behavior and security issues.\n\n**Corrected Version:**\n\nUse a more secure database library, such as `pg` or `mysql2`, and ensure proper error handling and security configurations.\n\n**5. Command Injection Vulnerability in `app.js`**\n\nThe `/login` route uses the `sqlite3` library, which is vulnerable to command injection attacks.\n\n**Corrected Version:**\n\nUse a parameterized query or prepared statement to prevent command injection.\n\n**6. Insecure Direct Object Reference (IDOR) in `app.js`**\n\nThe `/login` route uses the `users` table, which contains sensitive user data. However, the route does not properly validate or sanitize the `username` parameter, allowing an attacker to access sensitive user data.\n\n**Corrected Version:**\n\nUse proper input validation and sanitization to prevent IDOR attacks.\n\n**7. Insecure Password Storage in `app.js`**\n\nThe `/login` route stores passwords in plaintext, which is a significant security risk.\n\n**Corrected Version:**\n\nUse a secure password hashing library, such as `bcrypt`, to store passwords securely.\n\n**8. Security Misconfiguration in `app.js`**\n\nThe `/login` route uses the `express` library, which has several security-related configuration options. However, the route does not properly configure these options, leading to potential security issues.\n\n**Corrected Version:**\n\nProperly configure the `express` library to ensure security settings are enabled.\n\n**9. Insecure Deserialization in `app.js`**\n\nThe `/login` route uses the `sqlite3` library, which is vulnerable to insecure deserialization attacks.\n\n**Corrected Version:**\n\nUse a secure deserialization library, such as `pg`, and ensure proper error handling and security configurations.\n\n**10. Security Misconfiguration in `app.js`**\n\nThe `/login` route uses the `sqlite3` library, which is not secure for production environments. The `serialize()` method is used, which can lead to unexpected behavior and security issues.\n\n**Corrected Version:**\n\nUse a more secure database library, such as `pg` or `mysql2`, and ensure proper error handling and security configurations.\n\nThese vulnerabilities are significant, and it's essential to address them to ensure the security of your application." +} \ No newline at end of file