Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 79 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@ providing a more comprehensive security analysis.
## Inputs

- **`repo`**: (Required) The name of the repository you want to scan.
- **`slack_webhook`**: (Required) Slack webhook URL.
- **`slack_webhook`**: (Optional) Slack webhook URL for notifications. Typically set to `${{ secrets.APPSEC_BOT_SLACK_WEBHOOK }}`.
- **`language`**: (Optional) Language to scan. Supported languages include `javascript-typescript`, `typescript`, `go`, and `java-kotlin`. Used for both single-language repos requiring specific language configuration and multi-language matrix scanning.
- **`build_mode`**: (Optional) Build mode for the language. Set to `manual` for compiled languages like `java-kotlin` that require explicit build commands before analysis.
- **`build_command`**: (Optional) Build command for the language. Required when `build_mode` is `manual`. For Java projects, typically `./gradlew build` or similar Gradle/Maven commands.
- **`project_metrics_token`**: (Optional) Token belonging to a mixpanel project that is used to track build passes & failures.
- **`paths_ignored`**: (Optional) Code paths which are to be ignored. Each should be listed on a new line.
- **`rules_excluded`**: (Optional) Code scanning rules to exclude. Each should be listed on a new line.

- **`project_metrics_token`**: (optional) Token belonging to a mixpanel project that is used to track build passes & failures.
- **`paths_ignored`**: (optional) Code paths which are to be ignored. Each should be listed on a new line.
- **`rules_excluded`**: (optional) Code scanning rules to exclude. Each should be listed on a new line.
## Usage Examples

## Setup
### Basic Single Language Scan

To use the Security Code Scanner, create a `security-code-scanner.yml` file in your repository's `.github/workflows/` folder:
For a standard single-language repository, create a `security-code-scanner.yml` file in your repository's `.github/workflows/` folder:

```yaml
name: 'MetaMask Security Code Scanner'
name: MetaMask Security Code Scanner

on:
push:
Expand Down Expand Up @@ -68,6 +72,71 @@ jobs:
slack_webhook: ${{ secrets.APPSEC_BOT_SLACK_WEBHOOK }}
```

### Multi-Language Matrix Scan

For repositories with multiple languages, use a matrix strategy:

```yaml
name: Matrix Security Code Scanner

on:
push:
branches:
- main
pull_request: null
workflow_dispatch:

jobs:
security-scan:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
- language: typescript
- language: go
- language: java-kotlin
build-mode: manual
build-command: "./gradlew :coordinator:app:build"

name: Security Code Scan (${{ matrix.language }})
steps:
- name: Security Code Scanner - ${{ matrix.language }}
uses: MetaMask/action-security-code-scanner@mo-multilang-support
with:
repo: ${{ github.repository }}
language: ${{ matrix.language }}
build_mode: ${{ matrix.build-mode }}
build_command: ${{ matrix.build-command }}
paths_ignored: |
.storybook/
'**/__snapshots__/'
'**/*.snap'
'**/*.stories.js'
'**/*.stories.tsx'
'**/*.test.browser.ts*'
'**/*.test.js*'
'**/*.test.ts*'
'**/fixtures/'
'**/jest.config.js'
'**/jest.environment.js'
'**/mocks/'
'**/test*/'
docs/
e2e/
merged-packages/
node_modules
storybook/
test*/
project_metrics_token: ${{ secrets.SECURITY_SCAN_METRICS_TOKEN }}
slack_webhook: ${{ secrets.APPSEC_BOT_SLACK_WEBHOOK }}
```

## Secrets

Repositories in the MetaMask GitHub organization will pass the following secrets to the scanner to assist with logging and monitoring. However, these values can be replaced if used in other contexts.
Expand All @@ -77,7 +146,10 @@ Repositories in the MetaMask GitHub organization will pass the following secrets

## Features

- **Multi-Language Support**: Supports scanning JavaScript/TypeScript, Go, Java/Kotlin, and other languages with customizable build configurations.
- **CodeQL Analysis**: Leverages [MetaMask/Appsec-CodeQL](https://github.com/MetaMask/codeql-action), a wrapper around GitHub's [CodeQL engine](https://codeql.github.com/), to identify vulnerabilities in the codebase.
- **Matrix Scanning**: Allows scanning multiple languages in parallel using GitHub Actions matrix strategy.
- **Flexible Build Configuration**: Supports automatic and manual build modes with custom build commands.

## Disclaimer

Expand Down
17 changes: 15 additions & 2 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ inputs:
slack_webhook:
description: "Slack webhook for notifications"
required: false
language:
description: "Language to scan"
required: false
build_mode:
description: "Build mode for the language"
required: false
build_command:
description: "Build command for the language"
required: false
default: null

runs:
using: "composite"
Expand Down Expand Up @@ -53,11 +63,14 @@ runs:
- name: CodeQL Scan
id: codeql-scan
continue-on-error: true
uses: MetaMask/CodeQL-action@main
uses: MetaMask/CodeQL-action@mo-multilang-support
with:
repo: ${{ inputs.repo }}
paths_ignored: ${{ inputs.paths_ignored }}
rules_excluded: ${{ inputs.rules_excluded }}
language: ${{ inputs.language }}
build_mode: ${{ inputs.build_mode }}
build_command: ${{ inputs.build_command }}

- name: Semgrep Scan
id: semgrep-scan
Expand All @@ -70,7 +83,7 @@ runs:
shell: bash
env:
CODEQL_SCAN_RESULT: ${{ steps.codeql-scan.outcome }}
SEMGREP_SCAN_RESULT: ${{ steps.semgrep-scan.outcome }}
# SEMGREP_SCAN_RESULT: ${{ steps.semgrep-scan.outcome }}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Undefined Variable Affects Scan Success Logic

The SEMGREP_SCAN_RESULT environment variable is commented out but still referenced in the overall scan success determination logic. This makes the variable undefined, causing its failure check to always evaluate to false and effectively ignore Semgrep scan failures.

Fix in Cursor Fix in Web

run: |
if [[ "$CODEQL_SCAN_RESULT" == "failure" || "$SEMGREP_SCAN_RESULT" == "failure" ]]; then
SCAN_RESULT='failure'
Expand Down
58 changes: 58 additions & 0 deletions examples/security-code-scanner-matrix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Matrix Security Code Scanner

on:
push:
branches:
- main
pull_request: null
workflow_dispatch:

jobs:
security-scan:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
- language: typescript
- language: go
- language: java-kotlin
build-mode: manual
build-command: "./gradlew :coordinator:app:build"

name: Security Code Scan (${{ matrix.language }})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the whole MetaMask/action-security-code-scanner run multiple times will mean that semgrep scans will also upload multiple times. Do we know if GitHub's API is smart enough to know these are duplicates? Ideally, we only need to run individual jobs for certain Code Scanning Engines (e.g CodeQL) as its not necessary to do so for things like semgrep which scan all languages at once.

steps:
- name: Security Code Scanner - ${{ matrix.language }}
uses: MetaMask/action-security-code-scanner@mo-multilang-support
with:
repo: ${{ github.repository }}
language: ${{ matrix.language }}
build_mode: ${{ matrix.build-mode }}
build_command: ${{ matrix.build-command }}
paths_ignored: |
.storybook/
'**/__snapshots__/'
'**/*.snap'
'**/*.stories.js'
'**/*.stories.tsx'
'**/*.test.browser.ts*'
'**/*.test.js*'
'**/*.test.ts*'
'**/fixtures/'
'**/jest.config.js'
'**/jest.environment.js'
'**/mocks/'
'**/test*/'
docs/
e2e/
merged-packages/
node_modules
storybook/
test*/
project_metrics_token: ${{ secrets.SECURITY_SCAN_METRICS_TOKEN }}
slack_webhook: ${{ secrets.APPSEC_BOT_SLACK_WEBHOOK }}
46 changes: 46 additions & 0 deletions examples/security-code-scanner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: MetaMask Security Code Scanner

on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

jobs:
run-security-scan:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: MetaMask Security Code Scanner
uses: MetaMask/action-security-code-scanner@v1
with:
repo: ${{ github.repository }}
paths_ignored: |
.storybook/
'**/__snapshots__/'
'**/*.snap'
'**/*.stories.js'
'**/*.stories.tsx'
'**/*.test.browser.ts*'
'**/*.test.js*'
'**/*.test.ts*'
'**/fixtures/'
'**/jest.config.js'
'**/jest.environment.js'
'**/mocks/'
'**/test*/'
docs/
e2e/
merged-packages/
node_modules
storybook/
test*/
rules_excluded: example
project_metrics_token: ${{ secrets.SECURITY_SCAN_METRICS_TOKEN }}
slack_webhook: ${{ secrets.APPSEC_BOT_SLACK_WEBHOOK }}
Loading