From 2be41b2e8d37448e2fb5eb73f9c50fe7cf04f27e Mon Sep 17 00:00:00 2001 From: Ed Fricker Date: Fri, 3 Apr 2026 19:54:13 +0100 Subject: [PATCH 1/3] Harden dependency supply chain security - Add bundler-audit for Ruby dependency scanning - Add security audit workflow (daily + PR) - Verify Package.resolved is committed (already was) - Add BUNDLE_FROZEN=true in CI (setup action + build-app) - Update Dependabot with open-pull-requests-limit - SHA-pin all GitHub Actions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/actions/setup/action.yml | 4 ++- .github/dependabot.yml | 5 +-- .github/workflows/audit.yml | 41 ++++++++++++++++++++++++ .github/workflows/auto-author-assign.yml | 2 +- .github/workflows/build-app.yml | 8 +++-- .github/workflows/post_release.yml | 6 ++-- .github/workflows/sdk-primary.yml | 8 ++--- .github/workflows/stale.yml | 2 +- Gemfile | 1 + Gemfile.lock | 5 +++ 10 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/audit.yml diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 49d791ba..82ccf89c 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -44,7 +44,7 @@ runs: shell: bash - name: Cache Ruby gems - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: vendor/bundle key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} @@ -54,3 +54,5 @@ runs: - name: Install Ruby Gems run: bundle install --jobs 4 --retry 3 shell: bash + env: + BUNDLE_FROZEN: "true" diff --git a/.github/dependabot.yml b/.github/dependabot.yml index da3832c4..8dc9c3bb 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,6 +2,7 @@ version: 2 updates: - package-ecosystem: github-actions directory: / + open-pull-requests-limit: 5 schedule: interval: weekly day: monday @@ -11,6 +12,7 @@ updates: - '*' - package-ecosystem: "swift" directory: "/" + open-pull-requests-limit: 0 schedule: interval: "weekly" day: monday @@ -18,9 +20,9 @@ updates: swift-dependencies: patterns: - '*' - - package-ecosystem: "bundler" directory: "/" + open-pull-requests-limit: 0 schedule: interval: "weekly" day: monday @@ -28,4 +30,3 @@ updates: bundler-dependencies: patterns: - '*' - diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 00000000..c52c0930 --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,41 @@ +name: Security Audit + +on: + pull_request: + paths: + - 'Package.swift' + - 'Package.resolved' + - 'Gemfile' + - 'Gemfile.lock' + workflow_dispatch: + schedule: + - cron: '0 9 * * *' + +jobs: + ruby-audit: + name: Ruby Security Audit + runs-on: macos-latest + permissions: + contents: read + issues: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1 + with: + bundler-cache: true + - name: Update advisory database + run: bundle exec bundler-audit update + - name: Run bundler-audit + run: bundle exec bundler-audit check + - name: Create issue on failure + if: failure() && github.event_name != 'pull_request' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + EXISTING=$(gh issue list --label "security-audit" --state open --json number --jq 'length') + if [ "$EXISTING" -gt 0 ]; then exit 0; fi + TITLE_DATE=$(date +%Y-%m-%d) + gh issue create \ + --title "Security: Ruby dependency vulnerabilities detected (${TITLE_DATE})" \ + --label "security-audit,priority:high" \ + --body "The daily security audit has detected vulnerabilities. See [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details." diff --git a/.github/workflows/auto-author-assign.yml b/.github/workflows/auto-author-assign.yml index 51c609f8..8f2f34d7 100644 --- a/.github/workflows/auto-author-assign.yml +++ b/.github/workflows/auto-author-assign.yml @@ -13,4 +13,4 @@ jobs: if: ${{ !contains(github.event.pull_request.assignees, '') }} runs-on: ubuntu-latest steps: - - uses: toshimaru/auto-author-assign@v3.0.1 + - uses: toshimaru/auto-author-assign@4d585cc37690897bd9015942ed6e766aa7cdb97f # v3.0.1 diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index 7197e1fd..3c9dc329 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -16,12 +16,14 @@ jobs: timeout-minutes: 15 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Setup environment run: bundle install + env: + BUNDLE_FROZEN: "true" - name: Select Xcode Version - uses: maxim-lobanov/setup-xcode@v1 + uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1 with: xcode-version: 16.4 @@ -61,7 +63,7 @@ jobs: - name: Send Slack Notification - uses: slackapi/slack-github-action@v3.0.1 + uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1 with: payload: | { diff --git a/.github/workflows/post_release.yml b/.github/workflows/post_release.yml index 30a5fe24..ba636e01 100644 --- a/.github/workflows/post_release.yml +++ b/.github/workflows/post_release.yml @@ -10,11 +10,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout ios - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: path: ios - name: Checkout docs - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: repository: smileidentity/docs path: docs @@ -22,7 +22,7 @@ jobs: - name: Copy CHANGELOG.md to Release Notes run: cp ios/CHANGELOG.md docs/integration-options/mobile/ios-v10/release-notes.md - name: Create docs PR - uses: peter-evans/create-pull-request@v8 + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8 with: token: ${{ secrets.GH_PAT }} path: docs diff --git a/.github/workflows/sdk-primary.yml b/.github/workflows/sdk-primary.yml index 3ee9b547..4c2d9936 100644 --- a/.github/workflows/sdk-primary.yml +++ b/.github/workflows/sdk-primary.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: SwiftFormat Lint uses: docker://ghcr.io/nicklockwood/swiftformat:latest with: @@ -30,7 +30,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Write Smile Config id: write_smile_config # Mask the config so that it doesn't show up in the logs @@ -59,7 +59,7 @@ jobs: echo "Current developer directory: $(xcode-select -p)" ls -1 /Applications | grep Xcode || true - name: Cache SwiftPM - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 with: path: | ~/.swiftpm @@ -67,7 +67,7 @@ jobs: key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }} restore-keys: ${{ runner.os }}-spm- - name: Cache CocoaPods (validator downloads) - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 with: path: | ~/Library/Caches/CocoaPods diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index e96283fc..2183f296 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 1 steps: - - uses: actions/stale@v10 + - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10 with: stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days.' stale-pr-message: 'This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days.' diff --git a/Gemfile b/Gemfile index b0be835d..8c3bcd7e 100644 --- a/Gemfile +++ b/Gemfile @@ -4,3 +4,4 @@ gem "xcodeproj" gem "arkana" gem 'cocoapods', '~> 1.16.2' gem "rake", "~> 13.3.1" +gem 'bundler-audit', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 05d9223b..837f78c7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -27,6 +27,9 @@ GEM base64 (0.3.0) benchmark (0.5.0) bigdecimal (4.0.1) + bundler-audit (0.9.3) + bundler (>= 1.2.0) + thor (~> 1.0) claide (1.1.0) cocoapods (1.16.2) addressable (~> 2.8) @@ -97,6 +100,7 @@ GEM rexml (3.4.4) ruby-macho (2.5.1) securerandom (0.4.1) + thor (1.5.0) typhoeus (1.4.1) ethon (>= 0.9.0) tzinfo (2.0.6) @@ -118,6 +122,7 @@ PLATFORMS DEPENDENCIES arkana + bundler-audit cocoapods (~> 1.16.2) rake (~> 13.3.1) xcodeproj From 44ae1f43f91c063f9a84589153cfa6881d0ffc26 Mon Sep 17 00:00:00 2001 From: Ed Fricker Date: Fri, 3 Apr 2026 20:05:35 +0100 Subject: [PATCH 2/3] fix: address review feedback on audit workflow and dependency config - Fix CI: add ruby-version to setup-ruby (no .ruby-version file exists) - Use ubuntu-latest instead of macos-latest (bundler-audit doesn't need macOS) - Add BUNDLE_FROZEN=true to audit job for lockfile consistency - Create labels before gh issue create to prevent failures - Remove Swift paths from audit triggers (only Ruby is audited) - Keep Dependabot PRs enabled for Swift (no audit covers it) - Align actions/cache to v5 across all workflows Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/actions/setup/action.yml | 2 +- .github/dependabot.yml | 2 +- .github/workflows/audit.yml | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 82ccf89c..a305e18a 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -44,7 +44,7 @@ runs: shell: bash - name: Cache Ruby gems - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 with: path: vendor/bundle key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8dc9c3bb..5c7406d7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,7 +12,7 @@ updates: - '*' - package-ecosystem: "swift" directory: "/" - open-pull-requests-limit: 0 + open-pull-requests-limit: 5 schedule: interval: "weekly" day: monday diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index c52c0930..8cbd98e9 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -3,8 +3,6 @@ name: Security Audit on: pull_request: paths: - - 'Package.swift' - - 'Package.resolved' - 'Gemfile' - 'Gemfile.lock' workflow_dispatch: @@ -14,14 +12,17 @@ on: jobs: ruby-audit: name: Ruby Security Audit - runs-on: macos-latest + runs-on: ubuntu-latest permissions: contents: read issues: write + env: + BUNDLE_FROZEN: "true" steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1 with: + ruby-version: ruby bundler-cache: true - name: Update advisory database run: bundle exec bundler-audit update @@ -35,6 +36,8 @@ jobs: EXISTING=$(gh issue list --label "security-audit" --state open --json number --jq 'length') if [ "$EXISTING" -gt 0 ]; then exit 0; fi TITLE_DATE=$(date +%Y-%m-%d) + gh label create "security-audit" --description "Automated security audit findings" --color "D93F0B" 2>/dev/null || true + gh label create "priority:high" --description "High priority" --color "B60205" 2>/dev/null || true gh issue create \ --title "Security: Ruby dependency vulnerabilities detected (${TITLE_DATE})" \ --label "security-audit,priority:high" \ From 4d514b9243eb4265672694ee98309157fb51ffd2 Mon Sep 17 00:00:00 2001 From: Ed Fricker Date: Sun, 19 Apr 2026 16:36:37 +0100 Subject: [PATCH 3/3] fix: pin Ruby to 3.4 in audit workflow for ffi compatibility ffi 1.17.2 pre-built binary (x86_64-linux-gnu) only supports Ruby >= 2.5, < 3.5.dev. The workflow used 'ruby-version: ruby' which resolved to Ruby 4.0.2 after its release, breaking bundle install. Pin to 3.4 which is compatible with the current Gemfile.lock. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 8cbd98e9..32d59c6b 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1 with: - ruby-version: ruby + ruby-version: "3.4" bundler-cache: true - name: Update advisory database run: bundle exec bundler-audit update