Skip to main content

GitHub Actions

Integrate Musha into GitHub Actions to scan every push and pull request.

Full workflow

Create .github/workflows/musha.yml in your repository:

name: Musha Security Scan

on:
push:
branches: [main, master, develop]
pull_request:

jobs:
musha-scan:
name: Security scan
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2 # needed to detect changed files vs HEAD~1

- name: Package repository
run: |
tar -czf scan.tar.gz \
--exclude='.git' \
--exclude='node_modules' \
--exclude='vendor' \
--exclude='.terraform' \
--exclude='target' \
--exclude='dist' \
--exclude='build' \
.

- name: Upload to Musha
run: |
curl -fsS -X POST "${{ vars.MUSHA_API_URL }}/v1/scans" \
-H "Authorization: Bearer ${{ secrets.MUSHA_API_KEY }}" \
-F "files=@scan.tar.gz" \
-F "project_id=${{ vars.MUSHA_PROJECT_ID }}" \
-F "branch=${{ github.head_ref || github.ref_name }}" \
-F "pr_id=${{ github.event.pull_request.number }}" \
-F "commit_hash=${{ github.sha }}" \
-F "scan_type=full"

Variables and secrets

Configure these in GitHub → Repository settings → Secrets and variables → Actions:

NameTypeDescription
MUSHA_API_URLVariablehttps://api.mushasec.com
MUSHA_PROJECT_IDVariableYour project UUID from the Musha dashboard
MUSHA_API_KEYSecretAPI key created in Settings → API Keys

PR comment behavior

When the workflow runs on a pull request (github.event.pull_request.number is set), Musha posts a comment to the PR with the scan results. The comment is updated on each new push to the PR branch.

The comment includes:

  • Overall pass ✅ / fail ❌ based on your block_severity setting
  • Count of blocking, non-blocking, accepted, and technical debt findings
  • Direct links to the Security dashboard for triage

Customizing what gets scanned

Scan type

scan_type=full runs SCA + IaC + Secrets. You can narrow it down:

ValueWhat runs
fullSCA + IaC + Secrets (recommended)
scaDependencies only
iacInfrastructure only
secretsSecrets only
sca,iacDependencies + Infrastructure

To avoid blocking PRs for pre-existing vulnerabilities, package only the files changed in the PR:

- name: Get changed files
if: github.event_name == 'pull_request'
run: |
CHANGED=$(git diff --name-only HEAD~1 HEAD | jq -R . | jq -s . -c)
echo "CHANGED_FILES=$CHANGED" >> $GITHUB_ENV

- name: Package changed files only
if: github.event_name == 'pull_request'
run: |
git diff --name-only HEAD~1 HEAD | xargs tar -czf scan.tar.gz --

- name: Package full repo
if: github.event_name != 'pull_request'
run: tar -czf scan.tar.gz --exclude='.git' --exclude='node_modules' .

- name: Upload to Musha
run: |
curl -fsS -X POST "${{ vars.MUSHA_API_URL }}/v1/scans" \
-H "Authorization: Bearer ${{ secrets.MUSHA_API_KEY }}" \
-F "files=@scan.tar.gz" \
-F "project_id=${{ vars.MUSHA_PROJECT_ID }}" \
-F "branch=${{ github.head_ref || github.ref_name }}" \
-F "pr_id=${{ github.event.pull_request.number }}" \
-F "commit_hash=${{ github.sha }}" \
-F "scan_type=full" \
-F "changed_files=${CHANGED_FILES:-[]}"
tip

When changed_files is provided, Musha only analyzes manifests in or near the changed files. Vulnerabilities in files you didn't touch are marked as Technical Debt and never block the PR.

Troubleshooting

curl: (22) The requested URL returned error: 401 — The API key is invalid or expired. Regenerate it in Settings → API Keys.

curl: (22) The requested URL returned error: 403 — The API key doesn't have access to this project, or your subscription is expired.

curl: (22) The requested URL returned error: 429 — You've hit the scan rate limit (50 scans/hour per tenant). Wait and retry.