From e1e68e8011bf69948f0b5b4d241eff990f6e2c0c Mon Sep 17 00:00:00 2001 From: Aleksei Fedorov Date: Tue, 26 May 2026 19:16:22 +0000 Subject: [PATCH] security pipeline --- .github/workflows/security.yaml | 109 ++++++++++++++++++ .github/workflows/security/bandit.ini | 8 ++ .github/workflows/security/bandit.yml | 9 ++ .../workflows/security/eslint-security.json | 21 ++++ .github/workflows/security/npm-audit.json | 4 + .github/workflows/security/pip-audit.toml | 7 ++ .github/workflows/security/trivy.yaml | 18 +++ 7 files changed, 176 insertions(+) create mode 100644 .github/workflows/security.yaml create mode 100644 .github/workflows/security/bandit.ini create mode 100644 .github/workflows/security/bandit.yml create mode 100644 .github/workflows/security/eslint-security.json create mode 100644 .github/workflows/security/npm-audit.json create mode 100644 .github/workflows/security/pip-audit.toml create mode 100644 .github/workflows/security/trivy.yaml diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml new file mode 100644 index 0000000..d58316b --- /dev/null +++ b/.github/workflows/security.yaml @@ -0,0 +1,109 @@ +name: Security Scan + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + schedule: + - cron: "27 3 * * 1" + +permissions: + contents: read + security-events: write + +jobs: + security: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + if: always() + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install Python security tools + if: always() + continue-on-error: true + run: | + pip install bandit pip-audit safety || true + + - name: Bandit scan + if: always() + continue-on-error: true + run: | + bandit -c .github/workflows/security/bandit.yml -r . --severity-level high --confidence-level high -f json -o bandit-report.json || true + + - name: pip-audit dependencies + if: always() + continue-on-error: true + run: | + if [ -f requirements.txt ]; then + pip-audit -r requirements.txt -f json -o pip-audit-report.json || true + fi + + - name: Setup Node + if: always() + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install JS dependencies + if: always() + continue-on-error: true + run: | + if [ -f package.json ]; then + npm install || true + fi + + - name: NPM audit + if: always() + continue-on-error: true + run: | + if [ -f package.json ]; then + npm audit --audit-level=critical || true + fi + + - name: ESLint security scan + if: always() + continue-on-error: true + run: | + if [ -f package.json ]; then + npm install eslint eslint-plugin-security || true + npx eslint . -c .github/workflows/security/eslint-security.json || true + fi + + - name: Gitleaks scan + if: always() + continue-on-error: true + uses: gitleaks/gitleaks-action@v2 + + - name: Trivy filesystem scan + if: always() + continue-on-error: true + uses: aquasecurity/trivy-action@v0.36.0 + with: + scan-type: fs + scan-ref: . + config: .github/workflows/security/trivy.yaml + + - name: Upload Bandit report + if: always() + uses: actions/upload-artifact@v4 + with: + name: bandit-report + path: bandit-report.json + if-no-files-found: ignore + + - name: Upload pip-audit report + if: always() + uses: actions/upload-artifact@v4 + with: + name: pip-audit-report + path: pip-audit-report.json + if-no-files-found: ignore diff --git a/.github/workflows/security/bandit.ini b/.github/workflows/security/bandit.ini new file mode 100644 index 0000000..d13bab9 --- /dev/null +++ b/.github/workflows/security/bandit.ini @@ -0,0 +1,8 @@ +[bandit] + +exclude = tests,node_modules,dist,build,venv,.venv,migrations,.git + +skips = + B101, + B104, + B110 diff --git a/.github/workflows/security/bandit.yml b/.github/workflows/security/bandit.yml new file mode 100644 index 0000000..93af46a --- /dev/null +++ b/.github/workflows/security/bandit.yml @@ -0,0 +1,9 @@ +exclude_dirs: + - tests + - node_modules + - dist + - build + - venv + - .venv + - migrations + - .git diff --git a/.github/workflows/security/eslint-security.json b/.github/workflows/security/eslint-security.json new file mode 100644 index 0000000..a2c503a --- /dev/null +++ b/.github/workflows/security/eslint-security.json @@ -0,0 +1,21 @@ +{ + "env": { + "browser": true, + "es2021": true, + "node": true + }, + "extends": [ + "eslint:recommended", + "plugin:security/recommended" + ], + "plugins": [ + "security" + ], + "rules": { + "security/detect-eval-with-expression": "error", + "security/detect-object-injection": "warn", + "security/detect-non-literal-regexp": "warn", + "security/detect-child-process": "error", + "security/detect-unsafe-regex": "warn" + } +} diff --git a/.github/workflows/security/npm-audit.json b/.github/workflows/security/npm-audit.json new file mode 100644 index 0000000..38359f6 --- /dev/null +++ b/.github/workflows/security/npm-audit.json @@ -0,0 +1,4 @@ +{ + "audit-level": "high", + "production": false +} diff --git a/.github/workflows/security/pip-audit.toml b/.github/workflows/security/pip-audit.toml new file mode 100644 index 0000000..b0790e5 --- /dev/null +++ b/.github/workflows/security/pip-audit.toml @@ -0,0 +1,7 @@ +[tool.pip-audit] + +ignore-vulns = [] +require-hashes = false +progress-spinner = "on" +desc = true +format = "json" diff --git a/.github/workflows/security/trivy.yaml b/.github/workflows/security/trivy.yaml new file mode 100644 index 0000000..81c39ba --- /dev/null +++ b/.github/workflows/security/trivy.yaml @@ -0,0 +1,18 @@ +format: table + +severity: + - CRITICAL + +ignore-unfixed: true + +vulnerability: + type: + - os + - library + +scan: + skip-dirs: + - node_modules + - dist + - build + - .git