Skip to main content
Glama
security.yml18.1 kB
name: Security Scanning on: schedule: # Run daily at 2 AM UTC - cron: '0 2 * * *' push: branches: [ main ] pull_request: branches: [ main ] workflow_dispatch: env: PYTHON_VERSION: "3.11" UV_CACHE_DIR: /tmp/.uv-cache jobs: # =========================================================================== # DEPENDENCY VULNERABILITY SCANNING # =========================================================================== dependency-scan: name: Dependency Vulnerability Scan runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install UV uses: astral-sh/setup-uv@v3 with: enable-cache: true - name: Cache UV dependencies uses: actions/cache@v4 with: path: ${{ env.UV_CACHE_DIR }} key: ${{ runner.os }}-uv-${{ hashFiles('**/uv.lock', '**/pyproject.toml') }} restore-keys: | ${{ runner.os }}-uv- - name: Install dependencies run: | uv sync --dev --all-extras uv pip install --system safety pip-audit - name: Run Safety check run: | uv pip freeze | safety check --stdin --json --output safety-report.json || true uv pip freeze | safety check --stdin --full-report - name: Run pip-audit run: | pip-audit --format=json --output=pip-audit-report.json || true pip-audit --format=cyclonedx-json --output=pip-audit-sbom.json || true pip-audit - name: Upload vulnerability reports uses: actions/upload-artifact@v4 if: always() with: name: dependency-vulnerability-reports path: | safety-report.json pip-audit-report.json pip-audit-sbom.json retention-days: 90 # =========================================================================== # STATIC APPLICATION SECURITY TESTING (SAST) # =========================================================================== sast-scan: name: Static Application Security Testing runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install UV uses: astral-sh/setup-uv@v3 - name: Install security tools run: | uv pip install --system bandit[toml] semgrep - name: Run Bandit security linter run: | bandit -r packages/ mcp-server/ -f json -o bandit-report.json || true bandit -r packages/ mcp-server/ -f txt -o bandit-report.txt || true bandit -r packages/ mcp-server/ -ll - name: Run Semgrep env: SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} run: | semgrep --config=auto --json --output=semgrep-report.json . || true semgrep --config=auto . - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: python queries: security-extended - name: Autobuild uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: category: "/language:python" - name: Upload SAST reports uses: actions/upload-artifact@v4 if: always() with: name: sast-reports path: | bandit-report.json bandit-report.txt semgrep-report.json retention-days: 90 # =========================================================================== # CONTAINER SECURITY SCANNING # =========================================================================== container-security: name: Container Security Scan runs-on: ubuntu-latest needs: dependency-scan strategy: matrix: service: [mcp-server, dashboard-api, database] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build Docker image for scanning uses: docker/build-push-action@v5 with: context: . file: ./docker/${{ matrix.service }}/Dockerfile tags: tiger-mcp-${{ matrix.service }}:security-scan load: true cache-from: type=gha cache-to: type=gha,mode=max - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: 'tiger-mcp-${{ matrix.service }}:security-scan' format: 'sarif' output: 'trivy-${{ matrix.service }}.sarif' - name: Run Trivy for JSON report uses: aquasecurity/trivy-action@master with: image-ref: 'tiger-mcp-${{ matrix.service }}:security-scan' format: 'json' output: 'trivy-${{ matrix.service }}.json' - name: Run Trivy for table output uses: aquasecurity/trivy-action@master with: image-ref: 'tiger-mcp-${{ matrix.service }}:security-scan' format: 'table' - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: 'trivy-${{ matrix.service }}.sarif' category: 'container-${{ matrix.service }}' - name: Upload container scan reports uses: actions/upload-artifact@v4 if: always() with: name: container-scan-${{ matrix.service }} path: | trivy-${{ matrix.service }}.sarif trivy-${{ matrix.service }}.json retention-days: 90 # =========================================================================== # SECRET DETECTION # =========================================================================== secret-scan: name: Secret Detection runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Run TruffleHog OSS uses: trufflesecurity/trufflehog@main with: path: ./ base: main head: HEAD extra_args: --debug --only-verified --json --output=trufflehog-report.json - name: Run GitLeaks uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: config-path: .gitleaks.toml - name: Upload secret scan reports uses: actions/upload-artifact@v4 if: always() with: name: secret-scan-reports path: | trufflehog-report.json retention-days: 90 # =========================================================================== # INFRASTRUCTURE AS CODE SECURITY # =========================================================================== iac-scan: name: Infrastructure as Code Security runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Run Checkov id: checkov uses: bridgecrewio/checkov-action@master with: directory: . framework: dockerfile,docker_compose,kubernetes,secrets output_format: sarif output_file_path: checkov-report.sarif quiet: true soft_fail: true - name: Upload Checkov scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: checkov-report.sarif category: 'iac-security' - name: Run Hadolint for Dockerfile linting uses: hadolint/hadolint-action@v3.1.0 with: dockerfile: docker/mcp-server/Dockerfile format: sarif output-file: hadolint-mcp-server.sarif - name: Run Hadolint for Dashboard API Dockerfile uses: hadolint/hadolint-action@v3.1.0 with: dockerfile: docker/dashboard-api/Dockerfile format: sarif output-file: hadolint-dashboard-api.sarif - name: Run Hadolint for Database Dockerfile uses: hadolint/hadolint-action@v3.1.0 with: dockerfile: docker/database/Dockerfile format: sarif output-file: hadolint-database.sarif - name: Upload Hadolint results uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: | hadolint-mcp-server.sarif hadolint-dashboard-api.sarif hadolint-database.sarif category: 'dockerfile-security' - name: Upload IaC scan reports uses: actions/upload-artifact@v4 if: always() with: name: iac-scan-reports path: | checkov-report.sarif hadolint-*.sarif retention-days: 90 # =========================================================================== # SECURITY SCORECARD # =========================================================================== scorecard: name: OSSF Scorecard runs-on: ubuntu-latest permissions: security-events: write id-token: write contents: read actions: read steps: - name: Checkout code uses: actions/checkout@v4 with: persist-credentials: false - name: Run analysis uses: ossf/scorecard-action@v2.3.1 with: results_file: results.sarif results_format: sarif publish_results: true - name: Upload SARIF results to dependency graph uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif # =========================================================================== # LICENSE COMPLIANCE # =========================================================================== license-scan: name: License Compliance Scan runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install UV uses: astral-sh/setup-uv@v3 - name: Install dependencies run: | uv sync --dev --all-extras uv pip install --system pip-licenses - name: Generate license report run: | pip-licenses --format=json --output-file=licenses-report.json --with-urls --with-description pip-licenses --format=csv --output-file=licenses-report.csv --with-urls pip-licenses - name: Upload license reports uses: actions/upload-artifact@v4 with: name: license-reports path: | licenses-report.json licenses-report.csv retention-days: 90 # =========================================================================== # SECURITY SUMMARY REPORT # =========================================================================== security-summary: name: Security Summary Report runs-on: ubuntu-latest needs: [dependency-scan, sast-scan, container-security, secret-scan, iac-scan, license-scan] if: always() steps: - name: Download all artifacts uses: actions/download-artifact@v4 - name: Generate security summary run: | echo "# Security Scan Summary Report" > security-summary.md echo "" >> security-summary.md echo "**Date:** $(date -u)" >> security-summary.md echo "**Workflow:** ${{ github.workflow }}" >> security-summary.md echo "**Run ID:** ${{ github.run_id }}" >> security-summary.md echo "" >> security-summary.md echo "## Scan Results" >> security-summary.md echo "" >> security-summary.md echo "| Security Check | Status | Details |" >> security-summary.md echo "|---------------|--------|---------|" >> security-summary.md echo "| Dependency Scan | ${{ needs.dependency-scan.result == 'success' && '✅ Passed' || '❌ Failed' }} | Vulnerability scanning of dependencies |" >> security-summary.md echo "| SAST Scan | ${{ needs.sast-scan.result == 'success' && '✅ Passed' || '❌ Failed' }} | Static application security testing |" >> security-summary.md echo "| Container Security | ${{ needs.container-security.result == 'success' && '✅ Passed' || '❌ Failed' }} | Container vulnerability scanning |" >> security-summary.md echo "| Secret Detection | ${{ needs.secret-scan.result == 'success' && '✅ Passed' || '❌ Failed' }} | Secret and credential detection |" >> security-summary.md echo "| IaC Security | ${{ needs.iac-scan.result == 'success' && '✅ Passed' || '❌ Failed' }} | Infrastructure as code security |" >> security-summary.md echo "| License Compliance | ${{ needs.license-scan.result == 'success' && '✅ Passed' || '❌ Failed' }} | License compliance check |" >> security-summary.md echo "" >> security-summary.md # Add recommendations echo "## Security Recommendations" >> security-summary.md echo "" >> security-summary.md echo "1. **Regular Updates**: Keep all dependencies up to date" >> security-summary.md echo "2. **Monitoring**: Monitor security advisories for used packages" >> security-summary.md echo "3. **Access Control**: Implement least privilege access principles" >> security-summary.md echo "4. **Secrets Management**: Use proper secrets management solutions" >> security-summary.md echo "5. **Container Security**: Regularly update base images and scan containers" >> security-summary.md echo "" >> security-summary.md echo "---" >> security-summary.md echo "*Report generated by GitHub Actions Security Workflow*" >> security-summary.md - name: Upload security summary uses: actions/upload-artifact@v4 with: name: security-summary-report path: security-summary.md retention-days: 90 - name: Comment PR with security summary if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const fs = require('fs'); const summary = fs.readFileSync('security-summary.md', 'utf8'); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `## 🔒 Security Scan Results\n\n${summary}` }); # =========================================================================== # SECURITY ALERTS AND NOTIFICATIONS # =========================================================================== notify-security: name: Security Alert Notifications runs-on: ubuntu-latest needs: [dependency-scan, sast-scan, container-security, secret-scan] if: | always() && ( needs.dependency-scan.result == 'failure' || needs.sast-scan.result == 'failure' || needs.container-security.result == 'failure' || needs.secret-scan.result == 'failure' ) steps: - name: Send security alert run: | echo "🚨 SECURITY ALERT: One or more security scans failed!" echo "" echo "Scan Results:" echo "- Dependency Scan: ${{ needs.dependency-scan.result }}" echo "- SAST Scan: ${{ needs.sast-scan.result }}" echo "- Container Security: ${{ needs.container-security.result }}" echo "- Secret Detection: ${{ needs.secret-scan.result }}" echo "" echo "Please review the security scan results and take appropriate action." echo "Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - name: Create security issue if: github.event_name == 'schedule' uses: actions/github-script@v7 with: script: | const title = `🚨 Security Scan Failures - ${new Date().toISOString().split('T')[0]}`; const body = ` ## Security Scan Alert One or more scheduled security scans have failed. Please review and address the following: ### Scan Results - **Dependency Scan**: ${{ needs.dependency-scan.result }} - **SAST Scan**: ${{ needs.sast-scan.result }} - **Container Security**: ${{ needs.container-security.result }} - **Secret Detection**: ${{ needs.secret-scan.result }} ### Actions Required 1. Review the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for detailed results 2. Address any critical or high-severity vulnerabilities 3. Update dependencies if needed 4. Review and rotate any exposed secrets 5. Close this issue once all security issues are resolved ### Resources - [Security Policy](./SECURITY.md) - [Contributing Guidelines](./CONTRIBUTING.md) **Workflow Run**: ${{ github.run_id }} **Triggered**: ${new Date().toISOString()} `; github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, title: title, body: body, labels: ['security', 'high-priority', 'automated'] });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/luxiaolei/tiger-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server