GitHub Action vs GitHub App

pompelmi offers two GitHub integrations. Use whichever fits your workflow:

GitHub Action GitHub App
Setup Add a workflow file to .github/workflows/ One-click install — no workflow file needed
Scope Per-repository Organization-wide (one install covers every repo)
Check runs Optional (via comment-on-pr) Native — always shows pass/fail on the PR
Diff annotations Not supported Infected files appear as annotations on the PR diff
Maintenance You own the workflow YAML Managed by the pompelmi team
Best for Individual repos, custom pipelines Organizations wanting zero-config scanning on every PR
The GitHub Action is available at pompelmi/pompelmi on the GitHub Marketplace. This page documents the GitHub App — the zero-config alternative for organizations.

Installing the App

  1. Go to the pompelmi GitHub App page on the GitHub Marketplace.
  2. Click Install and choose the organization or specific repositories to protect.
  3. Review and accept the requested permissions (listed below).
  4. The App begins scanning new and updated pull requests immediately.

No workflow file is needed. No secrets to configure. Scanning starts on the next pull_request event in the selected repositories.

You can limit the App to specific repositories during installation. Return to the App's settings page on GitHub at any time to add or remove repositories.

Required permissions

The App requests the minimum permissions needed to scan PR files and report results. It never reads code outside the pull request diff:

Permission Access level Why it is needed
Contents Read Download the files changed in a pull request for scanning.
Pull requests Read Discover which files were added or modified in the PR.
Checks Write Post check run results and diff annotations back to GitHub.

The App does not store file contents, does not transmit data outside your network, and does not require any API keys or cloud accounts.

How check runs work

When a pull request is opened, updated, or reopened, the App:

  1. Creates a check run on the PR with status In progress.
  2. Fetches the list of changed files from the GitHub API (respects the 50 MB file size limit).
  3. Downloads each changed file and streams it to clamd for scanning — no disk I/O.
  4. Marks the check run Completed:
    • conclusion: success — all files clean (green ✓ on the PR)
    • conclusion: failure — one or more infected files (red ✗ on the PR)

The check run result appears in the Checks tab of the pull request alongside other CI results, and in the merge eligibility section at the bottom.

Diff annotations

When infected files are found, the App posts file-level annotations on the PR diff. Each infected file is annotated with the matched virus name:

⚠ Win.Malware.Agent-1234
    detected in uploads/malware.exe

Annotations appear inline in the Files changed tab of the PR, making it immediately obvious which uploaded file triggered the alert — without needing to read a separate log.

Self-hosting the App server

The App backend is an open-source Probot application that you can run on your own infrastructure:

git clone https://github.com/pompelmi/pompelmi-github-app
cd pompelmi-github-app
npm install

Set the following environment variables (or create a .env file):

APP_ID=<your GitHub App ID>
PRIVATE_KEY=<RSA private key PEM>
WEBHOOK_SECRET=<webhook secret>
CLAMD_HOST=localhost
CLAMD_PORT=3310

Start the server:

npm start

The server listens for pull_request webhook events, scans changed files, and posts check runs and annotations back to GitHub using the GitHub API. Point your GitHub App's webhook URL at this server.

The App server requires a ClamAV daemon (clamd) reachable over TCP or UNIX socket. For production deployments the recommended setup is a clamd Docker sidecar: docker run -d -p 3310:3310 clamav/clamav:stable

App configuration (.github/app.yml)

The .github/app.yml file in the pompelmi repository describes the App's metadata, permission requirements, and webhook event configuration. It is used when registering or updating the App on GitHub — you do not need to add it to your repositories.

# Triggers on pull_request: opened, synchronize, reopened
on:
  pull_request:
    types: [opened, synchronize, reopened]

# Minimum permissions
default_permissions:
  contents: read
  checks: write
  pull_requests: read

See the full app.yml in the repository for the complete reference and implementation notes.