-
-
Notifications
You must be signed in to change notification settings - Fork 6
feat: add SAST onboarding automation #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 10 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
ec21c3e
fix root changelog
witmicko 89f2c4e
feat: add onboarding automation for new repos
witmicko ad24efa
update pr template
witmicko e283983
ci: update build command for codeql
witmicko acbbe22
update inputs handlign
witmicko 10735dd
gh token fi
witmicko 8f971de
actionlint fix
witmicko 27e6a83
update branach handling move action file to templates
witmicko ecc9d0a
default to main on empty repo
witmicko ae1d8e4
fix empty repo runs
witmicko da090b6
fix empty repo runs
witmicko 6d3ad6b
another repo edge hase handling
witmicko 5628c2e
Enhance onboarding workflow with validation and opt-out checks for re…
witmicko 1ed47fb
Refactor onboarding workflow to improve error handling and default br…
witmicko d5620e0
Add environment specification to onboarding workflow
witmicko 0abbec5
Remove optional secrets section from onboarding PR template
witmicko 5b979e3
Merge branch 'main' into onboarding-automation
witmicko 1db4d46
Enhance onboarding workflow by adding validation for base branch name…
witmicko d7f3893
Improve error handling in onboarding workflow by validating GitHub AP…
witmicko File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # PR Body Templates | ||
|
|
||
| This directory contains templates for onboarding PRs that add the Security Code Scanner to repositories. | ||
|
|
||
| ## Templates | ||
|
|
||
| ### `onboarding-pr-body-manual.md` | ||
|
|
||
| **Use for:** Manual PRs created by the security team | ||
|
|
||
| - More detailed with full language configuration examples | ||
| - Includes code snippets for common scenarios | ||
| - Comprehensive documentation | ||
| - No auto-merge disclaimer | ||
|
|
||
| ### `onboarding-pr-body-automated.md` | ||
|
|
||
| **Use for:** Automated PRs created by workflows | ||
|
|
||
| - Shorter, more concise | ||
| - Includes auto-merge warning at the top | ||
| - Links to README for detailed configuration | ||
| - Used by `.github/workflows/onboard-new-repo.yml` | ||
|
|
||
| ## Variables | ||
|
|
||
| Both templates support variable substitution: | ||
|
|
||
| - `{{SECURITY_SCANNING_URL}}` - Repository-specific code scanning alerts URL | ||
|
|
||
| ## Usage | ||
|
|
||
| **Manual PRs:** | ||
|
|
||
| ```bash | ||
| # Copy and paste from onboarding-pr-body-manual.md | ||
| # Replace {{SECURITY_SCANNING_URL}} with actual URL | ||
| ``` | ||
|
|
||
| **Automated workflow:** | ||
| The workflow automatically reads `onboarding-pr-body-automated.md` and substitutes variables. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| ## ⚠️ Important Notice - Action Required | ||
|
|
||
| **This PR may be auto-merged in the future if not configured.** | ||
|
|
||
| If your team does not need the security scanner: | ||
|
|
||
| 1. **Add a comment on this PR** explaining why your team is opting out | ||
| 2. **Close this PR** to prevent auto-merge | ||
| 3. **Add a `.github/no-security-scanner` file** to your repository to prevent future onboarding attempts | ||
|
|
||
| If you need the scanner but want to customize it: | ||
|
|
||
| 1. Complete the checklist below | ||
| 2. Review and modify the workflow file as needed | ||
| 3. Approve and merge this PR when ready | ||
|
|
||
| If no action is taken, this PR may be automatically merged after a grace period to ensure baseline security coverage across all repositories. | ||
|
|
||
| --- | ||
|
|
||
| ## Required Action | ||
|
|
||
| Prior to merging this pull request, please ensure the following has been completed: | ||
|
|
||
| - [ ] The lines specifying `branches` correctly specify this repository's default branch (usually `main` or `master`). | ||
| - [ ] Any paths you would like to ignore have been added to the `paths-ignored` configuration option (see [setup](https://github.com/MetaMask/action-security-code-scanner/blob/main/README.md#setup)) | ||
| - [ ] Language configuration has been reviewed - ignore falsely detected languages or add build commands for Java/Kotlin if needed (see Configuration section below) | ||
| - [ ] Any existing CodeQL configuration has been disabled. | ||
|
|
||
| ## What is the Security Code Scanner? | ||
|
|
||
| This pull request enables the [MetaMask Security Code Scanner](https://github.com/MetaMask/action-security-code-scanner) GitHub Action. This action runs on each pull request, and will flag potential vulnerabilities as a review comment. It will also scan this repository's default branch, and log any findings in this repository's [Code Scanning Alerts Tab]({{SECURITY_SCANNING_URL}}). | ||
|
|
||
| <img width="500" alt="Security Scanner Screenshot" src="https://github.com/user-attachments/assets/41c87b70-79b7-44dd-a444-791b142fbbe1"> | ||
|
|
||
| The action itself runs various static analysis engines behind the scenes. Currently, it is only running GitHub's CodeQL engine. For this reason, we recommend disabling any existing CodeQL configuration your repository may have. | ||
|
|
||
| ## How do I interact with the tool? | ||
|
|
||
| Every finding raised by the Security Code Scanner will present context behind the potential vulnerability identified, and allow the developer to fix, or dismiss it. | ||
|
|
||
| The finding will automatically be dismissed by pushing a commit that fixes the identified issue, or by manually dismissing the alert using the button in GitHub's UI. If dismissing an alert manually, please add any additional context surrounding the reason for dismissal, as this informs our decision to disable, or improve any poor performing rules. | ||
|
|
||
| <img width="983" alt="Alert Dismissal Screenshot" src="https://github.com/user-attachments/assets/114219d5-4b4c-4d9d-8bfe-f4666012b73e"> | ||
|
|
||
| ## Configuration | ||
|
|
||
| ### Language Configuration | ||
|
|
||
| The scanner auto-detects languages in your repository. If you need to customize language-specific settings, you can modify the `languages-config` section in the workflow file. | ||
|
|
||
| **Common use cases:** | ||
|
|
||
| 1. **Ignore falsely detected languages:** | ||
|
|
||
| ```yaml | ||
| languages-config: | | ||
| [ | ||
| { | ||
| "language": "ruby", | ||
| "ignore": true | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
| 2. **Configure Java/Kotlin builds:** | ||
|
|
||
| ```yaml | ||
| languages-config: | | ||
| [ | ||
| { | ||
| "language": "java-kotlin", | ||
| "build_mode": "manual", | ||
| "build_command": "./gradlew build", | ||
| "version": "21", | ||
| "distribution": "temurin" | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
| **Supported languages:** `javascript-typescript`, `python`, `java-kotlin`, `go`, `cpp`, `csharp`, `ruby` | ||
|
|
||
| **Build modes:** `none`, `autobuild`, `manual` | ||
|
|
||
| ### Additional Configuration | ||
|
|
||
| For more configuration options, please review the tool's [README](https://github.com/MetaMask/action-security-code-scanner/blob/main/README.md). | ||
|
|
||
| Optional secrets that can be configured: | ||
|
|
||
| - `SECURITY_SCAN_METRICS_TOKEN` - for metrics collection | ||
| - `APPSEC_BOT_SLACK_WEBHOOK` - for Slack notifications | ||
|
|
||
| For any additional questions, please reach out to `@app-sec` in Slack. | ||
|
witmicko marked this conversation as resolved.
Outdated
|
||
|
|
||
| --- | ||
|
|
||
| 🤖 _This PR was automatically created by the MetaMask Security onboarding system_ | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| name: MetaMask Security Code Scanner | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - { DEFAULT_BRANCH } | ||
| pull_request: | ||
| branches: | ||
| - { DEFAULT_BRANCH } | ||
| workflow_call: | ||
| secrets: | ||
| SECURITY_SCAN_METRICS_TOKEN: | ||
| required: false | ||
| APPSEC_BOT_SLACK_WEBHOOK: | ||
| required: false | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| security-scan: | ||
| uses: MetaMask/action-security-code-scanner/.github/workflows/security-scan.yml@v2 | ||
| permissions: | ||
| actions: read | ||
| contents: read | ||
| security-events: write | ||
| with: | ||
| repo: ${{ github.repository }} | ||
| scanner-ref: 'v2' | ||
| paths-ignored: | | ||
| node_modules | ||
| **/node_modules/** | ||
| **/__snapshots__/** | ||
| __snapshots_linux__ | ||
| **/__stories__/** | ||
| .storybook/ | ||
| **/*.test.ts | ||
| **/*.test.tsx | ||
| **/*.test.js | ||
| **/*.test.jsx | ||
| **/*.spec.ts | ||
| **/*.spec.tsx | ||
| **/*.spec.js | ||
| **/*.spec.jsx | ||
| **/test*/** | ||
| **/e2e/** | ||
| **/tests/** | ||
| languages-config: | | ||
| [ | ||
| ] | ||
| secrets: | ||
| project-metrics-token: ${{ secrets.SECURITY_SCAN_METRICS_TOKEN }} | ||
| slack-webhook: ${{ secrets.APPSEC_BOT_SLACK_WEBHOOK }} |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| name: 'Onboard New Repository with SAST' | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| organization: | ||
| description: 'Organization name (e.g., MetaMask)' | ||
| required: true | ||
| type: string | ||
| repository: | ||
| description: 'Repository name (e.g., snaps)' | ||
| required: true | ||
| type: string | ||
| repository_dispatch: | ||
| types: [new_repository_created] | ||
|
|
||
| jobs: | ||
| create-sast-pr: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| steps: | ||
| - name: Checkout scanner action repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| path: scanner-repo | ||
|
|
||
| - name: Determine target repository | ||
| id: target | ||
| run: | | ||
| if [ "${{ github.event_name }}" = "repository_dispatch" ]; then | ||
| ORG="${{ github.event.client_payload.organization }}" | ||
| REPO_NAME="${{ github.event.client_payload.repository }}" | ||
|
cursor[bot] marked this conversation as resolved.
Outdated
|
||
| REPO="$ORG/$REPO_NAME" | ||
|
cursor[bot] marked this conversation as resolved.
Outdated
|
||
| else | ||
| REPO="${{ inputs.organization }}/${{ inputs.repository }}" | ||
|
cursor[bot] marked this conversation as resolved.
Outdated
|
||
| fi | ||
|
|
||
| # Auto-detect default branch from the repository | ||
| echo "Detecting default branch for $REPO..." | ||
| BASE_BRANCH=$(gh api "repos/$REPO" --jq '.default_branch' 2>/dev/null || echo "") | ||
|
|
||
| # If repo is empty or API call failed, default to 'main' | ||
| if [ -z "$BASE_BRANCH" ] || [ "$BASE_BRANCH" = "null" ]; then | ||
| echo "Repository is empty or default branch not found. Defaulting to 'main'" | ||
| BASE_BRANCH="main" | ||
| fi | ||
|
|
||
| echo "repository=$REPO" >> "$GITHUB_OUTPUT" | ||
| echo "base_branch=$BASE_BRANCH" >> "$GITHUB_OUTPUT" | ||
|
cursor[bot] marked this conversation as resolved.
|
||
| shell: bash | ||
| env: | ||
| GH_TOKEN: ${{ secrets.ONBOARDING_TOKEN }} | ||
|
|
||
| - name: Check if target repository is empty | ||
| id: check_empty | ||
| run: | | ||
| REPO="${{ steps.target.outputs.repository }}" | ||
| # Try to get repository info | ||
| REPO_INFO=$(gh api "repos/$REPO" 2>/dev/null || echo "") | ||
|
|
||
| if [ -z "$REPO_INFO" ]; then | ||
| echo "Failed to get repository info" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Check if repository has commits (size will be 0 if empty) | ||
| IS_EMPTY=$(echo "$REPO_INFO" | jq -r '.size == 0') | ||
|
|
||
| echo "is_empty=$IS_EMPTY" >> "$GITHUB_OUTPUT" | ||
|
witmicko marked this conversation as resolved.
|
||
| echo "Repository empty status: $IS_EMPTY" | ||
| shell: bash | ||
| env: | ||
| GH_TOKEN: ${{ secrets.ONBOARDING_TOKEN }} | ||
|
cursor[bot] marked this conversation as resolved.
witmicko marked this conversation as resolved.
|
||
|
|
||
| - name: Checkout target repository | ||
| if: steps.check_empty.outputs.is_empty == 'false' | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| repository: ${{ steps.target.outputs.repository }} | ||
| token: ${{ secrets.ONBOARDING_TOKEN }} | ||
| path: target-repo | ||
| ref: ${{ steps.target.outputs.base_branch }} | ||
|
cursor[bot] marked this conversation as resolved.
|
||
|
|
||
| - name: Initialize empty repository locally | ||
| if: steps.check_empty.outputs.is_empty == 'true' | ||
| run: | | ||
| mkdir -p target-repo | ||
| cd target-repo | ||
| git init | ||
| git remote add origin "https://x-access-token:${{ secrets.ONBOARDING_TOKEN }}@github.com/${{ steps.target.outputs.repository }}.git" | ||
| shell: bash | ||
|
|
||
| - name: Create branch and add SAST workflow | ||
| working-directory: target-repo | ||
| run: | | ||
| git config user.name "MetaMask Security Bot" | ||
| git config user.email "security-bot@metamask.io" | ||
|
|
||
| IS_EMPTY="${{ steps.check_empty.outputs.is_empty }}" | ||
| BASE_BRANCH="${{ steps.target.outputs.base_branch }}" | ||
|
|
||
| if [ "$IS_EMPTY" = "true" ]; then | ||
| # For empty repos, create initial commit on main | ||
| BRANCH_NAME="$BASE_BRANCH" | ||
| else | ||
| # For existing repos, create a feature branch | ||
| BRANCH_NAME="security/add-sast-scanner" | ||
| git checkout -b "$BRANCH_NAME" | ||
| fi | ||
|
cursor[bot] marked this conversation as resolved.
|
||
|
|
||
| # Create .github/workflows directory if it doesn't exist | ||
| mkdir -p .github/workflows | ||
|
|
||
| # Copy the security scanner workflow template and replace placeholders | ||
| sed "s/{ DEFAULT_BRANCH }/$BASE_BRANCH/g" \ | ||
| ../scanner-repo/.github/templates/security-code-scanner.yml \ | ||
| > .github/workflows/security-code-scanner.yml | ||
|
witmicko marked this conversation as resolved.
cursor[bot] marked this conversation as resolved.
cursor[bot] marked this conversation as resolved.
|
||
|
|
||
| git add .github/workflows/security-code-scanner.yml | ||
| git commit -m "chore: add MetaMask Security Code Scanner workflow | ||
|
|
||
| This PR adds the MetaMask Security Code Scanner workflow to enable | ||
| automated security scanning of the codebase. | ||
|
|
||
| The scanner will run on: | ||
| - Push to $BASE_BRANCH branch | ||
| - Pull requests to $BASE_BRANCH branch | ||
| - Manual workflow dispatch | ||
|
|
||
| To configure the scanner for your repository's specific needs, | ||
| please review the workflow file and adjust as necessary." | ||
|
|
||
| git push -u origin "$BRANCH_NAME" | ||
| shell: bash | ||
|
|
||
| - name: Create Pull Request | ||
| if: steps.check_empty.outputs.is_empty == 'false' | ||
| working-directory: target-repo | ||
| env: | ||
| GH_TOKEN: ${{ secrets.ONBOARDING_TOKEN }} | ||
| REPO_NAME: ${{ steps.target.outputs.repository }} | ||
| run: | | ||
| # Extract owner and repo name for URL construction | ||
| OWNER=$(echo "$REPO_NAME" | cut -d'/' -f1) | ||
| REPO=$(echo "$REPO_NAME" | cut -d'/' -f2) | ||
| BASE_BRANCH="${{ steps.target.outputs.base_branch }}" | ||
| SECURITY_URL="https://github.com/${OWNER}/${REPO}/security/code-scanning" | ||
|
|
||
| # Read PR body template and substitute variables | ||
| PR_BODY=$(cat ../scanner-repo/.github/templates/onboarding-pr-body-automated.md) | ||
| PR_BODY="${PR_BODY//\{\{SECURITY_SCANNING_URL\}\}/$SECURITY_URL}" | ||
|
|
||
| gh pr create \ | ||
| --title "🔒 Add MetaMask Security Code Scanner" \ | ||
| --body "$PR_BODY" \ | ||
| --base "$BASE_BRANCH" \ | ||
| --head "security/add-sast-scanner" | ||
| shell: bash | ||
|
|
||
| - name: Output PR URL | ||
| if: steps.check_empty.outputs.is_empty == 'false' | ||
| working-directory: target-repo | ||
| env: | ||
| GH_TOKEN: ${{ secrets.ONBOARDING_TOKEN }} | ||
| run: | | ||
| PR_URL=$(gh pr view security/add-sast-scanner --json url -q .url) | ||
| echo "✅ Pull Request created: $PR_URL" | ||
| echo "PR_URL=$PR_URL" >> "$GITHUB_OUTPUT" | ||
| shell: bash | ||
|
|
||
| - name: Output commit info for empty repo | ||
| if: steps.check_empty.outputs.is_empty == 'true' | ||
| run: | | ||
| REPO="${{ steps.target.outputs.repository }}" | ||
| BASE_BRANCH="${{ steps.target.outputs.base_branch }}" | ||
| echo "✅ Initial commit pushed to https://github.com/$REPO/tree/$BASE_BRANCH" | ||
| echo "Repository was empty - workflow file added directly to $BASE_BRANCH branch" | ||
| shell: bash | ||
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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.