-
Notifications
You must be signed in to change notification settings - Fork 4
Add continuous autonomous security testing framework (v3.0) #35
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
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 |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| name: Argus Retest After Fix | ||
| on: | ||
| pull_request: | ||
| types: [closed] | ||
|
|
||
| jobs: | ||
| retest: | ||
| # Only run when an argus/fix- PR is merged | ||
| if: > | ||
| github.event.pull_request.merged == true && | ||
| startsWith(github.event.pull_request.head.ref, 'argus/fix-') | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.11' | ||
|
|
||
| - name: Install dependencies | ||
| run: pip install -r requirements.txt | ||
|
|
||
| - name: Extract fix metadata | ||
| id: meta | ||
| run: | | ||
| BRANCH="${{ github.event.pull_request.head.ref }}" | ||
| # Extract vuln type and finding ID from branch name: argus/fix-{type}-{id} | ||
| VULN_TYPE=$(echo "$BRANCH" | sed 's|argus/fix-||' | sed 's|-[a-f0-9]*$||') | ||
| FINDING_ID=$(echo "$BRANCH" | grep -oP '[a-f0-9]{8}$' || echo "unknown") | ||
| echo "vuln_type=$VULN_TYPE" >> $GITHUB_OUTPUT | ||
| echo "finding_id=$FINDING_ID" >> $GITHUB_OUTPUT | ||
| # Get changed files from the PR | ||
| CHANGED_FILES=$(gh pr view ${{ github.event.pull_request.number }} --json files -q '.files[].path' || echo "") | ||
| echo "changed_files=$CHANGED_FILES" >> $GITHUB_OUTPUT | ||
|
Comment on lines
+32
to
+41
Check failureCode scanning / Semgrep OSS Semgrep Finding: yaml.github-actions.security.run-shell-injection.run-shell-injection Error
Using variable interpolation ${...} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
|
||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Run regression tests | ||
| id: regression | ||
| continue-on-error: true | ||
| run: | | ||
| python -c " | ||
| import sys | ||
| sys.path.insert(0, 'scripts') | ||
| try: | ||
| from regression_tester import RegressionTester | ||
| tester = RegressionTester() | ||
| results = tester.run('tests/security_regression') | ||
| passed = results.get('passed', 0) | ||
| failed = results.get('failed', 0) | ||
| print(f'Regression tests: {passed} passed, {failed} failed') | ||
| sys.exit(1 if failed > 0 else 0) | ||
| except Exception as e: | ||
| print(f'Regression test error: {e}') | ||
| sys.exit(1) | ||
| " | ||
|
|
||
| - name: Run targeted SAST rescan | ||
| id: rescan | ||
| continue-on-error: true | ||
| env: | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| run: | | ||
| python scripts/run_ai_audit.py \ | ||
| --project-type auto \ | ||
| --only-changed \ | ||
| --review-type security | ||
|
|
||
| - name: Update finding status | ||
| if: steps.regression.outcome == 'success' && steps.rescan.outcome == 'success' | ||
| run: | | ||
| python -c " | ||
| import sys | ||
| sys.path.insert(0, 'scripts') | ||
| try: | ||
| from findings_store import FindingsStore | ||
| store = FindingsStore() | ||
| store.record_fix( | ||
| finding_id='${{ steps.meta.outputs.finding_id }}', | ||
| fix_commit='${{ github.sha }}', | ||
| fix_method='autofix', | ||
| retest_passed=True, | ||
| ) | ||
| print('Finding marked as fix-verified') | ||
| except Exception as e: | ||
| print(f'Could not update findings store: {e}') | ||
| " | ||
|
|
||
| - name: Post retest results | ||
| if: always() | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const regression = '${{ steps.regression.outcome }}'; | ||
| const rescan = '${{ steps.rescan.outcome }}'; | ||
| const allPassed = regression === 'success' && rescan === 'success'; | ||
|
|
||
| const body = `## Argus Retest Results | ||
|
|
||
| | Check | Status | | ||
| |-------|--------| | ||
| | Regression Tests | ${regression === 'success' ? 'Passed' : 'Failed'} | | ||
| | SAST Rescan | ${rescan === 'success' ? 'Clean' : 'Issues found'} | | ||
| | **Overall** | **${allPassed ? 'Fix Verified' : 'Needs Review'}** | | ||
|
|
||
| ${allPassed ? 'The fix has been verified. The vulnerability is confirmed resolved.' : 'The retest found issues. Please review the scan results.'} | ||
|
|
||
| --- | ||
| *Argus Security Retest — triggered by merge of \`${{ github.event.pull_request.head.ref }}\`*`; | ||
|
|
||
| // Comment on the merged PR | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: ${{ github.event.pull_request.number }}, | ||
| body: body | ||
| }); | ||
|
Comment on lines
+100
to
+124
Check failureCode scanning / Semgrep OSS Semgrep Finding: yaml.github-actions.security.github-script-injection.github-script-injection Error
Using variable interpolation ${...} with github context data in a actions/github-script's script: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| name: Post-Deploy Security Validation | ||
| on: | ||
| deployment_status: | ||
| # Trigger when deployment succeeds | ||
| workflow_dispatch: | ||
| inputs: | ||
| target_url: | ||
| description: 'Deployment URL to scan' | ||
| required: false | ||
| type: string | ||
| environment: | ||
| description: 'Deployment environment' | ||
| required: false | ||
| default: 'staging' | ||
| type: string | ||
|
|
||
| jobs: | ||
| post-deploy-scan: | ||
| if: > | ||
| github.event_name == 'workflow_dispatch' || | ||
| github.event.deployment_status.state == 'success' | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| security-events: write | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.11' | ||
|
|
||
| - name: Install dependencies | ||
| run: pip install -r requirements.txt | ||
|
|
||
| - name: Determine deployment context | ||
| id: context | ||
| run: | | ||
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | ||
| echo "target_url=${{ inputs.target_url }}" >> $GITHUB_OUTPUT | ||
| echo "environment=${{ inputs.environment }}" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "target_url=${{ github.event.deployment.payload.web_url || '' }}" >> $GITHUB_OUTPUT | ||
| echo "environment=${{ github.event.deployment.environment }}" >> $GITHUB_OUTPUT | ||
| fi | ||
| # Get diff since last successful scan | ||
| PREV_SHA=$(git log --format='%H' -2 | tail -1) | ||
| echo "prev_sha=$PREV_SHA" >> $GITHUB_OUTPUT | ||
| CHANGED=$(git diff --name-only $PREV_SHA HEAD | head -100) | ||
| echo "has_changes=$( [ -n "$CHANGED" ] && echo true || echo false )" >> $GITHUB_OUTPUT | ||
|
|
||
|
Comment on lines
+42
to
+55
Check failureCode scanning / Semgrep OSS Semgrep Finding: yaml.github-actions.security.run-shell-injection.run-shell-injection Error
Using variable interpolation ${...} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
|
||
| - name: Run diff-scoped SAST scan | ||
| if: steps.context.outputs.has_changes == 'true' | ||
| env: | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| ONLY_CHANGED: "true" | ||
| run: | | ||
| python scripts/run_ai_audit.py \ | ||
| --project-type auto \ | ||
| --only-changed \ | ||
| --review-type security | ||
|
|
||
| - name: Run DAST against deployment | ||
| if: steps.context.outputs.target_url != '' | ||
| env: | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| DAST_TARGET_URL: ${{ steps.context.outputs.target_url }} | ||
| run: | | ||
| echo "Running DAST scan against $DAST_TARGET_URL" | ||
| python -c " | ||
| import sys | ||
| sys.path.insert(0, 'scripts') | ||
| try: | ||
| from dast_orchestrator import DASTOrchestrator, OrchestratorConfig | ||
| config = OrchestratorConfig( | ||
| project_path='.', | ||
| enable_nuclei=True, | ||
| enable_zap=False, | ||
| max_duration=600, | ||
| ) | ||
| orch = DASTOrchestrator(config=config) | ||
| results = orch.run('${{ steps.context.outputs.target_url }}') | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Script injection via target URL in workflowHigh Severity The Additional Locations (1) |
||
| print(f'DAST scan complete: {len(results.get(\"findings\", []))} findings') | ||
| except ImportError as e: | ||
| print(f'DAST not available: {e}') | ||
| except Exception as e: | ||
| print(f'DAST scan error: {e}') | ||
| " | ||
|
|
||
| - name: Upload results | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: post-deploy-scan-results | ||
| path: | | ||
| .argus/ | ||
| *.sarif | ||
| retention-days: 30 | ||


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.
Shell injection via branch ref in workflow
High Severity
${{ github.event.pull_request.head.ref }}is interpolated directly into a shell script. While theifcondition ensures the branch starts withargus/fix-, the remainder is attacker-controlled. A branch name containing shell metacharacters like$(cmd)or backticks would execute arbitrary commands during therunstep, potentially exfiltrating secrets likeANTHROPIC_API_KEYorGITHUB_TOKEN.