GITHUB ACTION TUTORIAL

Scan your mobile app on every PR

Wire the appaudix GitHub Action into your repo so every pull request gets a PCI-DSS / OWASP MASVS check before merge. The build fails on critical findings; the PR gets a severity comment with a link to the full report.

~30 seconds per PR

Upload + scan + comment, end to end.

Audit-ready reports

PCI-DSS, OWASP MASVS, HIPAA, GDPR mapping in every result.

Block bad releases

Configurable severity gate — fail the build before merge.

Four steps

STEP 1

Get an API key

Sign in at appaudix.com/Profile. Pick the Enterprise plan (API access is part of Enterprise — Free, Pro, and Team are dashboard-only). Click Generate API key, copy the sk_live_* value once — it's only shown then.

STEP 2

Store the key as a repo secret

In GitHub: Settings → Secrets and variables → Actions → New repository secret. Name it APPAUDIX_API_KEY. Paste the key, save.

STEP 3

Drop the workflow into your repo

Add a file at .github/workflows/mobile-security.yml with the snippet below.

STEP 4

Open a PR

The workflow builds your app, posts it to the appaudix Scan API, polls for completion, and writes a single comment on the PR with the severity table. Subsequent runs update the same comment in place.

Workflow files

Copy, paste, replace the build step with your existing build.

Android (APK / AAB)

.github/workflows/mobile-security.yml
name: Mobile Security
on:
  pull_request:
    paths: ['app/**', 'android/**']

permissions:
  contents: read
  pull-requests: write   # so the action can post (or update) a PR comment

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build APK
        run: ./gradlew assembleRelease

      - name: appaudix Security Scan
        uses: appaudix/scan-action@v2
        with:
          api_key: ${{ secrets.APPAUDIX_API_KEY }}
          app_path: app/build/outputs/apk/release/app-release.apk
          fail_on_severity: critical

iOS (IPA)

.github/workflows/ios-security.yml
name: iOS Security
on:
  pull_request:
    paths: ['ios/**']

permissions:
  contents: read
  pull-requests: write

jobs:
  scan:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build IPA
        run: xcodebuild -workspace MyApp.xcworkspace -scheme MyApp \
                       -configuration Release -archivePath ./build/MyApp.xcarchive archive

      - name: Export IPA
        run: xcodebuild -exportArchive -archivePath ./build/MyApp.xcarchive \
                       -exportOptionsPlist ExportOptions.plist \
                       -exportPath ./build

      - name: appaudix Security Scan
        uses: appaudix/scan-action@v2
        with:
          api_key: ${{ secrets.APPAUDIX_API_KEY }}
          app_path: ./build/MyApp.ipa
          fail_on_severity: high

Action outputs

Every run exposes outputs you can wire into downstream steps — Slack notifications, Jira tickets, custom reporting, anything you build with GitHub Actions.

OutputDescription
scan_idThe scan ID returned by POST /v1/scans.
status`completed`, `failed`, or `timeout`.
passed`true` / `false` based on `fail_on_severity`. Use it to gate other steps.
risk_level`low` / `medium` / `high` / `critical`.
compliance_scoreNumeric (0–100). 0 = severe findings, 100 = clean.
critical_count / high_count / medium_count / low_countFindings per severity bucket.
report_urlFull HTML report. Add `.pdf` or `.json` to the URL for other formats.

Example: post to Slack on failure

yaml
      - name: appaudix Security Scan
        uses: appaudix/scan-action@v2
        with:
          api_key: ${{ secrets.APPAUDIX_API_KEY }}
          app_path: app/build/outputs/apk/release/app-release.apk
          fail_on_severity: critical

      - name: Post to Slack on failure
        if: steps.scan.outputs.passed == 'false'
        run: |
          curl -X POST ${{ secrets.SLACK_WEBHOOK }} -d @- <<EOF
          {"text": "🚨 Mobile scan failed on ${{ github.head_ref }}",
           "blocks": [{"type": "section", "text": {"type": "mrkdwn",
             "text": "Risk: ${{ steps.scan.outputs.risk_level }}\nReport: ${{ steps.scan.outputs.report_url }}"}}]}
          EOF

Webhooks (no polling)

If you'd rather skip the GitHub Action and call the API directly from your own pipeline, pass a callback_url when you submit the scan. appaudix POSTs a signed JSON payload to that URL when the scan completes — no need to poll status.

bash
curl -X POST https://api.appaudix.com/v1/scans \
  -H "Authorization: Bearer $APPAUDIX_API_KEY" \
  -F "file=@app.apk" \
  -F "platform=android" \
  -F "callback_url=https://your-ci.example.com/hooks/appaudix" \
  -F "fail_on_severity=critical" \
  -F 'metadata={"commit":"$GITHUB_SHA","pr":"$PR_NUMBER"}'

Each callback includes an X-Appaudix-Signature HMAC-SHA256 header so you can verify it came from appaudix. Full API reference →

Common questions

Does this require Enterprise?

Yes — API access (and therefore the GitHub Action) is part of the Enterprise plan. Free, Pro, and Team customers can run scans from the dashboard. See pricing →

How long does a scan take?

Typically 5–30 seconds wall-clock for a typical mobile app. The action polls every 10 seconds with exponential backoff up to timeout_minutes (default 30).

What if I want to run async — fire-and-forget?

Set wait_for_results: false. The action submits the scan, sets the scan_id output, and returns immediately. Combine with callback_url for true async pipelines.

Where do I see the full report?

The report_url output is a permanent URL. Add .pdf or .json to fetch other formats. Reports also appear in your dashboard.

Can I gate on specific severity counts, not just risk level?

Yes. The outputs include each severity bucket. Add a step like if: steps.scan.outputs.high_count > 3 for custom policy.

Get a key, ship a workflow, never merge an insecure release

The whole loop takes under five minutes if you already have a build step in your CI.

Cookie preferences

We use necessary storage for security and login. With your permission, we also use analytics to understand page journeys and marketing pixels to measure ad campaigns.