π‘οΈ Security Scan #45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: π‘οΈ Security Scan | |
on: | |
push: | |
branches: [ "master", "main", "develop" ] | |
pull_request: | |
branches: [ "master", "main" ] | |
schedule: | |
# Run security scan daily at 2 AM UTC | |
- cron: '0 2 * * *' | |
workflow_dispatch: # Allow manual trigger | |
jobs: | |
security-scan: | |
name: π Security Vulnerability Scan | |
runs-on: ubuntu-latest | |
permissions: | |
actions: read | |
contents: read | |
security-events: write | |
strategy: | |
matrix: | |
python-version: ["3.10", "3.11", "3.12"] | |
steps: | |
- name: π₯ Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: π Set up Python ${{ matrix.python-version }} | |
uses: actions/setup-python@v4 | |
with: | |
python-version: ${{ matrix.python-version }} | |
cache: 'pip' | |
cache-dependency-path: 'requirements.txt' | |
timeout-minutes: 10 | |
- name: β Verify Python Version (Must be 3.10+) | |
run: | | |
python_version=$(python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") | |
echo "Python version detected: $python_version" | |
if [[ "$python_version" < "3.10" ]]; then | |
echo "β ERROR: This workflow requires Python 3.10+ but found $python_version" | |
echo "This indicates an old workflow is running. Please cancel old workflow runs." | |
exit 1 | |
fi | |
echo "β Python version $python_version is compatible with MCP library" | |
- name: π¦ Install dependencies | |
timeout-minutes: 15 | |
run: | | |
python -m pip install --upgrade pip | |
# Install dependencies, skipping Windows-specific packages on Linux | |
if [[ "$RUNNER_OS" == "Linux" ]]; then | |
# Create temp requirements file without Windows-specific packages for Linux | |
grep -v "platform_system==\"Windows\"" requirements.txt > temp-requirements.txt | |
echo "Installing filtered requirements for Linux:" | |
cat temp-requirements.txt | |
pip install -r temp-requirements.txt --timeout 300 | |
else | |
pip install -r requirements.txt --timeout 300 | |
fi | |
pip install safety bandit semgrep --timeout 300 | |
- name: π Run Safety - Check for known vulnerabilities | |
run: | | |
echo "## π‘οΈ Safety - Known Vulnerabilities Check" >> $GITHUB_STEP_SUMMARY | |
safety check --json --output safety-report.json || true | |
if [ -f safety-report.json ]; then | |
echo "### Safety Report Results:" >> $GITHUB_STEP_SUMMARY | |
python -c "import json; data=json.load(open('safety-report.json')); print('- Total vulnerabilities found:', len(data.get('vulnerabilities', [])))" >> $GITHUB_STEP_SUMMARY | |
if [ $(python -c "import json; data=json.load(open('safety-report.json')); print(len(data.get('vulnerabilities', [])))") -gt 0 ]; then | |
echo "β Vulnerabilities detected! See full report in artifacts." >> $GITHUB_STEP_SUMMARY | |
exit 1 | |
else | |
echo "β No known vulnerabilities found!" >> $GITHUB_STEP_SUMMARY | |
fi | |
fi | |
- name: π Run Bandit - Security linter for Python | |
run: | | |
echo "## π Bandit - Python Security Linter" >> $GITHUB_STEP_SUMMARY | |
bandit -r . -f json -o bandit-report.json || true | |
if [ -f bandit-report.json ]; then | |
echo "### Bandit Report Results:" >> $GITHUB_STEP_SUMMARY | |
python -c "import json; data=json.load(open('bandit-report.json')); print('- Total issues found:', len(data.get('results', [])))" >> $GITHUB_STEP_SUMMARY | |
python -c "import json; data=json.load(open('bandit-report.json')); high=[r for r in data.get('results',[]) if r.get('issue_severity')=='HIGH']; medium=[r for r in data.get('results',[]) if r.get('issue_severity')=='MEDIUM']; print(f'- High severity: {len(high)}'); print(f'- Medium severity: {len(medium)}')" >> $GITHUB_STEP_SUMMARY | |
fi | |
- name: β‘ Run Semgrep - Static analysis | |
run: | | |
echo "## β‘ Semgrep - Static Code Analysis" >> $GITHUB_STEP_SUMMARY | |
semgrep --config=auto --json --output=semgrep-report.json . || true | |
if [ -f semgrep-report.json ]; then | |
echo "### Semgrep Report Results:" >> $GITHUB_STEP_SUMMARY | |
python -c "import json; data=json.load(open('semgrep-report.json')); results=data.get('results',[]); print('- Total findings:', len(results)); critical=[r for r in results if r.get('extra',{}).get('severity')=='ERROR']; warning=[r for r in results if r.get('extra',{}).get('severity')=='WARNING']; print(f'- Critical: {len(critical)}'); print(f'- Warnings: {len(warning)}')" >> $GITHUB_STEP_SUMMARY | |
fi | |
- name: π Generate Security Report | |
run: | | |
echo "## π Security Scan Summary" >> $GITHUB_STEP_SUMMARY | |
echo "### Scan Details:" >> $GITHUB_STEP_SUMMARY | |
echo "- Python Version: ${{ matrix.python-version }}" >> $GITHUB_STEP_SUMMARY | |
echo "- Scan Date: $(date)" >> $GITHUB_STEP_SUMMARY | |
echo "- Repository: ${{ github.repository }}" >> $GITHUB_STEP_SUMMARY | |
echo "- Branch: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY | |
- name: π€ Upload Security Reports | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: security-reports-py${{ matrix.python-version }} | |
path: | | |
safety-report.json | |
bandit-report.json | |
semgrep-report.json | |
retention-days: 30 | |
dependency-review: | |
name: π Dependency Review | |
runs-on: ubuntu-latest | |
if: github.event_name == 'pull_request' | |
steps: | |
- name: π₯ Checkout repository | |
uses: actions/checkout@v4 | |
- name: π Dependency Review | |
uses: actions/dependency-review-action@v3 | |
with: | |
fail-on-severity: moderate | |
codeql-analysis: | |
name: π΅οΈ CodeQL Analysis | |
runs-on: ubuntu-latest | |
permissions: | |
actions: read | |
contents: read | |
security-events: write | |
strategy: | |
fail-fast: false | |
matrix: | |
language: [ 'python' ] | |
steps: | |
- name: π₯ Checkout repository | |
uses: actions/checkout@v4 | |
- name: π§ Initialize CodeQL | |
uses: github/codeql-action/init@v2 | |
with: | |
languages: ${{ matrix.language }} | |
queries: security-extended,security-and-quality | |
- name: ποΈ Autobuild | |
uses: github/codeql-action/autobuild@v2 | |
- name: π Perform CodeQL Analysis | |
uses: github/codeql-action/analyze@v2 | |
with: | |
category: "/language:${{matrix.language}}" | |
secret-scan: | |
name: π Secret Scanning | |
runs-on: ubuntu-latest | |
steps: | |
- name: π₯ Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: π Run TruffleHog | |
uses: trufflesecurity/trufflehog@main | |
with: | |
path: ./ | |
base: ${{ github.event.before || format('{0}~1', github.sha) }} | |
head: ${{ github.sha }} | |
extra_args: --debug --only-verified | |
security-audit: | |
name: π‘οΈ Security Audit | |
runs-on: ubuntu-latest | |
needs: [security-scan, codeql-analysis] | |
if: always() | |
steps: | |
- name: π₯ Checkout repository | |
uses: actions/checkout@v4 | |
- name: π Security Audit Summary | |
run: | | |
echo "# π‘οΈ Security Audit Complete" >> $GITHUB_STEP_SUMMARY | |
echo "" >> $GITHUB_STEP_SUMMARY | |
echo "## π Scans Performed:" >> $GITHUB_STEP_SUMMARY | |
echo "- β Python Security Linting (Bandit)" >> $GITHUB_STEP_SUMMARY | |
echo "- β Known Vulnerability Check (Safety)" >> $GITHUB_STEP_SUMMARY | |
echo "- β Static Code Analysis (Semgrep)" >> $GITHUB_STEP_SUMMARY | |
echo "- β Advanced Code Analysis (CodeQL)" >> $GITHUB_STEP_SUMMARY | |
echo "- β Secret Detection (TruffleHog)" >> $GITHUB_STEP_SUMMARY | |
echo "" >> $GITHUB_STEP_SUMMARY | |
echo "## π Artifacts Generated:" >> $GITHUB_STEP_SUMMARY | |
echo "- Security reports available in workflow artifacts" >> $GITHUB_STEP_SUMMARY | |
echo "- CodeQL results available in Security tab" >> $GITHUB_STEP_SUMMARY | |
echo "" >> $GITHUB_STEP_SUMMARY | |
echo "## π¨ Next Steps:" >> $GITHUB_STEP_SUMMARY | |
echo "1. Review all security findings" >> $GITHUB_STEP_SUMMARY | |
echo "2. Address high-priority vulnerabilities" >> $GITHUB_STEP_SUMMARY | |
echo "3. Update dependencies as needed" >> $GITHUB_STEP_SUMMARY | |
echo "4. Document remediation actions" >> $GITHUB_STEP_SUMMARY |