-
Notifications
You must be signed in to change notification settings - Fork 2
Bugfixes #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bugfixes #8
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -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" | ||||
|
||||
| export SHIELDCI_RESULTS_FILE="$HOME/Desktop/ShieldCI/tests/shield_results.json" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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... |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,5 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||
| "status": "Clean", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "vulnerabilities": [], | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+2
to
+3
|
||||||||||||||||||||||||||||||||||||||||||||||||
| "status": "Clean", | |
| "vulnerabilities": [], | |
| "status": "Vulnerable", | |
| "vulnerabilities": [ | |
| { | |
| "id": "SQL_INJECTION_LOGIN", | |
| "title": "SQL Injection in /login route", | |
| "severity": "critical", | |
| "description": "The GET /login route builds SQL queries via string concatenation using unsanitized user input, allowing SQL injection." | |
| }, | |
| { | |
| "id": "INSECURE_PASSWORD_STORAGE", | |
| "title": "Insecure password storage", | |
| "severity": "high", | |
| "description": "Passwords are stored in plaintext instead of being hashed with a secure algorithm such as bcrypt." | |
| }, | |
| { | |
| "id": "IDOR_LOGIN", | |
| "title": "Insecure Direct Object Reference in /login", | |
| "severity": "high", | |
| "description": "The /login route does not properly validate or sanitize the username parameter, potentially exposing sensitive user data." | |
| } | |
| ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workflow hardcodes an API key (and an API URL) directly in the repository. This exposes credentials to anyone with repo access and to any workflow log/runner that can read the YAML. Move these values back to GitHub Secrets (e.g.,
secrets.SHIELDCI_API_URL/secrets.SHIELDCI_API_KEY) and avoid committing real keys to source control.