diff --git a/.github/actions/mobsfscan-json.yml b/.github/actions/mobsfscan-json.yml deleted file mode 100644 index fccd9a7..0000000 --- a/.github/actions/mobsfscan-json.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Mobsfscan -description: A scanner for mobile applications -#outputs: -# random-number: -# description: "Random number" -# value: ${{ steps.random-number-generator.outputs.random-number }} -runs: - using: "composite" - steps: - - name: mobsfscan - uses: MobSF/mobsfscan@main - with: - args: '. --json' -# manual evaluation of the result is required here (check if there exists a solution already for it) diff --git a/.github/actions/nuclei-scan.yml b/.github/actions/nuclei-scan.yml deleted file mode 100644 index d9f96cc..0000000 --- a/.github/actions/nuclei-scan.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Nuclei Scan -description: A website scanner -input: - target: - required: true - type: string - -runs: - using: "composite" - steps: - - uses: actions/checkout@v2 - - - name: Nuclei - Vulnerability Scan - uses: projectdiscovery/nuclei-action@main - with: - target: ${{ inputs.target }} - - name: GitHub Workflow artifacts - uses: actions/upload-artifact@v2 - with: - name: nuclei.log - path: nuclei.log - - - name: GitHub Security Dashboard Alerts update - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: nuclei.sarif diff --git a/.github/workflows/flutter-security-checks.yml b/.github/workflows/flutter-security-checks.yml deleted file mode 100644 index 88ef070..0000000 --- a/.github/workflows/flutter-security-checks.yml +++ /dev/null @@ -1,149 +0,0 @@ -on: - workflow_call: - inputs: - flutter-version: - required: true - type: string - relative-include-path: - required: false - type: string - relative-exclude-path: - required: false - type: string - git-lfs: - description: "Checkout the project with git lfs" - type: boolean - default: false - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - secret_scanner: - runs-on: [ self-hosted ] - steps: - - uses: actions/checkout@v2 - with: - lfs: ${{ inputs.git-lfs }} - - run: echo ${{inputs.relative-include-path}} ${{inputs.relative-exclude-path}} - - uses: max/secret-scan@master - with: - include_path: '${{ inputs.relative-include-path }}' - exclude_path: '${{ inputs.relative-exclude-path }}' -# - run: echo >\n -# !!!!!!!!!!!!!! Message from the security officer !!!!!!!!!!!!!!\n -# Should there be findings, think about if that upload-key should be put into source code?\n -# \n -# If the upload-key can be in the source code, put the path of that file into a text file and provide that path as an input parameter for the security checks job \"relative-exclude-path":" .pathtofile/secret_check_ignore_paths.txt\"\n -# If the upload-key should not be in the source code, consider putting it into the GitHub secrets\n - - trufflehog-package-analysis: - runs-on: [ self-hosted ] - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: set env variables for check - if: inputs.relative-exclude-path != '' - run: | - echo 'TH_EXCLUDE_PATHS=--exclude-paths=${{ inputs.relative-exclude-path }}' >> $GITHUB_ENV - - name: set env variables for check - if: inputs.relative-include-path != '' - run: | - echo 'TH_INCLUDE_PATHS=--include-paths=${{ inputs.relative-include-path }}' >> $GITHUB_ENV - - name: TruffleHog OSS - uses: trufflesecurity/trufflehog@main - with: - path: ./ - base: ${{ github.event.repository.default_branch }} - head: HEAD - extra_args: --debug --only-verified ${{ env.TH_EXCLUDE_PATHS }} ${{ env.TH_INCLUDE_PATHS }} - - # https://github.com/fundacaocerti/mobsf-action - # https://github.com/fundacaocerti/mobsf-action/pull/16 - # https://github.com/fundacaocerti/mobsf-action/pull/17 -# mobsf_scan_only: -# runs-on: [ self-hosted ] -# steps: -# - name: Checkout Repo -# uses: actions/checkout@master -# - name: Set-up Java -# uses: actions/setup-java@v1 -# with: -# java-version: '12.x' -# - name: Set-up Flutter -# uses: subosito/flutter-action@v1 -# with: -# flutter-version: ${{ inputs.flutterVersion }} -# - name: Flutter Install Dependencies -# run: flutter pub get -# - name: Flutter Build -# run: flutter build apk -## - name: Fix Permissions for MobSF Docker -## run: | -## set -e -## sudo mkdir -p /home/runner/work/_temp/_github_home -## sudo chown -R 9901:9901 /home/runner/work/_temp/_github_home -## sudo mkdir -p /home/runner/work/$REPO_NAME/$REPO_NAME -## sudo chown -R 9901:9901 /home/runner/work/$REPO_NAME/$REPO_NAME -## env: -## REPO_NAME: ${{ github.event.repository.name }} -# - name: Run MobSF Analysis -# uses: fundacaocerti/mobsf-action@v1.7.2 -# env: -# INPUT_FILE_NAME: build/app/outputs/apk/app.apk -# SCAN_TYPE: apk -# OUTPUT_FILE_NAME: mobsf-report -## - name: Cleanup MobSF Permissions -## run: | -## set -e -## sudo chown -R runner:docker /home/runner/work/_temp/_github_home -## sudo chown -R runner:docker /home/runner/work/$REPO_NAME/$REPO_NAME -## env: -## REPO_NAME: ${{ github.event.repository.name }} -# - name: Upload MobSF Analysis PDF Result -# uses: actions/upload-artifact@v2 -# with: -# name: mobsf-report-apk.pdf -# path: mobsf-report-apk.pdf -# - name: Upload MobSF Analysis JSON Result -# uses: actions/upload-artifact@v2 -# with: -# name: mobsf-report-apk.json -# path: mobsf-report-apk.json - -# mobsf_scan_ios: -# runs-on: [ self-hosted, ios ] -# steps: -# - name: Checkout Repo -# uses: actions/checkout@master -# - name: Set-up Java -# uses: actions/setup-java@v1 -# with: -# java-version: '12.x' -# - name: Set-up Flutter -# uses: subosito/flutter-action@v1 -# with: -# flutter-version: ${{ inputs.flutterVersion }} -# - name: Flutter Install Dependencies -# run: flutter pub get -# - name: Flutter Build -# run: flutter build ipa -# - name: Run MobSF Analysis -# uses: fundacaocerti/mobsf-action@v1.7.2 -# env: -# INPUT_FILE_NAME: build/ios/archive/Runner.xcarchive -# SCAN_TYPE: ipa -# OUTPUT_FILE_NAME: mobsf-report -# - name: Upload MobSF Analysis PDF Result -# uses: actions/upload-artifact@v2 -# with: -# name: mobsf-report-ipa.pdf -# path: mobsf-report-ipa.pdf -# - name: Upload MobSF Analysis JSON Result -# uses: actions/upload-artifact@v2 -# with: -# name: mobsf-report-ipa.json -# path: mobsf-report-ipa.json diff --git a/.github/workflows/qb-security.yml b/.github/workflows/qb-security.yml new file mode 100644 index 0000000..63e5de7 --- /dev/null +++ b/.github/workflows/qb-security.yml @@ -0,0 +1,40 @@ +name: QB Security + +on: + workflow_call: + inputs: + runs-on: + description: 'Runner label for the scan job.' + type: string + default: 'default-k8s-runner' + search-directory: + description: 'Directory to scan recursively for invisible Unicode characters.' + type: string + default: '.' + exclude-dirs: + description: 'Comma-separated directory names to exclude from the scan.' + type: string + default: '.git,node_modules,.idea,build,dist' + exclude-patterns: + description: 'Comma-separated file glob patterns to exclude from the scan.' + type: string + default: '*.png,*.jpg,*.jpeg,*.gif,*.ico,*.pdf,*.zip,*.tar,*.gz,*.bin,*.dill' + fail-on-found: + description: 'Fail the workflow when invisible Unicode characters are found.' + type: boolean + default: true + +jobs: + unicode-security-scan: + runs-on: ${{ inputs.runs-on }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Detect Invisible Unicode + uses: QuickBirdEng/actions/detect-invisible-unicode@main + with: + search-directory: ${{ inputs.search-directory }} + exclude-dirs: ${{ inputs.exclude-dirs }} + exclude-patterns: ${{ inputs.exclude-patterns }} + fail-on-found: ${{ inputs.fail-on-found }} diff --git a/README.md b/README.md index 8d1a48a..c8ed979 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,11 @@ The examples in [The docs folder](docs/) are provided as examples of calling wor From the root of your project repo, place the calling workflow in `.github/workflows`. +## Workflows + +| Workflow | Description | Docs | +|---|---|---| +| `qb-security` | Invisible Unicode detection + verified secret scanning on pull requests | [docs/qb-security](docs/qb-security/explanation.md) | +| `sanity-requirements` | LoC delta check and branch-ticket check for feature branches | [docs/sanity-requirements](docs/sanity-requirements/explanation.md) | +| `flutter-package-branch` / `flutter-package-release` | Flutter lint, test, and Slack notification for package repos | [docs/flutter-packages](docs/flutter-packages/explanation.md) | + diff --git a/docs/qb-security/explanation.md b/docs/qb-security/explanation.md new file mode 100644 index 0000000..8fe1917 --- /dev/null +++ b/docs/qb-security/explanation.md @@ -0,0 +1,89 @@ +# QB Security + +A reusable workflow that runs supply-chain security checks on every pull request. + +## What it checks + +### Invisible Unicode detection + +Scans every source file in the PR for invisible Unicode characters used in two known supply-chain attacks: + +- **GlassWorm** — embeds Unicode Variation Selectors (U+FE00–U+FE0F, U+E0100–U+E01EF) inside commits. The characters are invisible in code editors, terminals, and GitHub's diff view, allowing payloads to hide inside what appear to be legitimate changes. +- **Trojan Source** — uses bidirectional control characters (U+202A–U+202E, U+2066–U+2069) to visually reorder code during review so that what a reviewer sees differs from what the compiler executes. + +Binary files are skipped automatically. Findings are emitted as inline PR annotations pointing to the exact file and line. + +### Secret scanning (TruffleHog) + +Scans the commits introduced by the PR for verified secrets using [TruffleHog OSS](https://github.com/trufflesecurity/trufflehog). Only **verified** secrets (credentials that TruffleHog can confirm are active against the real service) are reported, which eliminates false positives from example keys or already-rotated credentials. Findings are emitted as inline PR annotations. + +## Usage + +```yaml +name: Security + +on: + pull_request: + +jobs: + # Invisible Unicode detection — no secrets needed + security: + uses: QuickBirdEng/workflows/.github/workflows/qb-security.yml@main + + # Secret scanning — separate job, passes only the token it needs + trufflehog-scan: + runs-on: default-k8s-runner + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: QuickBirdEng/actions/trufflehog-scan@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +The unicode scan requires no secrets. TruffleHog runs as a separate job and receives only `GITHUB_TOKEN` — no `secrets: inherit` needed. + +## Inputs + +All inputs are optional. Defaults are intentionally broad so most repos need no configuration. + +| Input | Type | Default | Description | +|---|---|---|---| +| `runs-on` | string | `default-k8s-runner` | Runner label | +| `search-directory` | string | `.` | Root directory for the invisible Unicode scan | +| `exclude-dirs` | string | `.git,node_modules,.idea,build,dist` | Directory names to skip | +| `exclude-patterns` | string | `*.png,*.jpg,*.jpeg,*.gif,*.ico,*.pdf,*.zip,*.tar,*.gz,*.bin,*.dill` | File glob patterns to skip | +| `fail-on-found` | boolean | `true` | Fail the check when invisible Unicode is detected | + +## Typical overrides + +**Exclude an additional generated directory:** +```yaml +jobs: + security: + uses: QuickBirdEng/workflows/.github/workflows/qb-security.yml@main + with: + exclude-dirs: '.git,node_modules,.idea,build,dist,generated' + secrets: inherit +``` + +**Run on a self-hosted runner:** +```yaml +jobs: + security: + uses: QuickBirdEng/workflows/.github/workflows/qb-security.yml@main + with: + runs-on: 'self-hosted' + secrets: inherit +``` + +**Audit mode (report but do not fail):** +```yaml +jobs: + security: + uses: QuickBirdEng/workflows/.github/workflows/qb-security.yml@main + with: + fail-on-found: false + secrets: inherit +``` diff --git a/docs/qb-security/qb-security-calling-example.yml b/docs/qb-security/qb-security-calling-example.yml new file mode 100644 index 0000000..38f7494 --- /dev/null +++ b/docs/qb-security/qb-security-calling-example.yml @@ -0,0 +1,18 @@ +name: Security + +on: + pull_request: + +jobs: + security: + uses: QuickBirdEng/workflows/.github/workflows/qb-security.yml@main + + trufflehog-scan: + runs-on: default-k8s-runner + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: QuickBirdEng/actions/trufflehog-scan@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}