A GitHub App that automatically scans pull requests for security threats and evaluates contributor trust profiles using the Brin API.
When installed on a repository, the app reacts to pull request events and runs two parallel checks:
PR Security Scan -- Analyzes the PR diff for security threats (credential leaks, obfuscated payloads, dependency attacks, etc.) and reports a score from 0-100 with a verdict.
Contributor Trust Check -- Evaluates the PR author's GitHub profile across identity, behavior, content, and social graph dimensions to flag accounts that warrant additional review.
Results are surfaced as:
- Check runs on the PR commit (pass/fail/neutral) that integrate with branch protection rules
- PR comments with detailed findings and dimension breakdowns
- Labels (
pr:verified,pr:flagged,contributor:verified,contributor:flagged)
| Verdict | Check run | Label | Comment | Blocks merge |
|---|---|---|---|---|
| clean / safe | success | pr:verified / contributor:verified |
removed | no |
| suspicious / caution | neutral | pr:flagged / contributor:flagged |
posted | no |
| dangerous / score < 30 | failure | pr:flagged / contributor:flagged |
posted | yes |
| pending deep scan | neutral | -- | -- | no |
Create a new GitHub App at https://github.com/settings/apps/new with these settings:
Permissions:
- Checks: Read & Write
- Pull requests: Read & Write
- Issues: Read & Write (for PR comments)
- Contents: Read (for
.github/brin.ymlconfig) - Metadata: Read
Webhook events:
- Pull request
- Check run
- Check suite
- Installation
Set the webhook URL to https://<your-host>/api/github/webhook.
Copy .env.example to .env and fill in:
APP_ID=<your GitHub App ID>
PRIVATE_KEY=<contents of your .pem file, with literal \n for newlines>
WEBHOOK_SECRET=<the secret you set when creating the app>
npm install
npm run dev # development with hot reload
npm run build # compile TypeScript
npm start # run compiled outputThe server starts on port 3000 by default (override with PORT env var).
Go to your app's installation page and install it on the repositories you want to protect.
Repositories can optionally add a .github/brin.yml file to customize behavior:
prScan:
enabled: true
blockBelowScore: 30
suspiciousVerdicts: [suspicious]
tolerance: conservative
contributorTrust:
enabled: true
safeVerdicts: [safe]
trustedAuthors: [dependabot[bot], renovate[bot]]
comments:
mode: detailed # or "minimal"All fields are optional. Missing fields fall back to the defaults shown above.
src/
├── index.ts # Hono server, webhook route, health check
├── app.ts # GitHub App instance (octokit)
├── events/
│ ├── index.ts # Event handler registration
│ ├── pullRequest.ts # pull_request event handler
│ ├── checkRun.ts # check_run.rerequested handler
│ └── installation.ts # installation.created handler
├── services/
│ ├── prScan.ts # PR scan orchestration
│ ├── contributorTrust.ts # Contributor trust orchestration
│ ├── checkRuns.ts # GitHub Check Runs API wrapper
│ ├── comments.ts # Marker-based comment management + rendering
│ ├── labels.ts # Label ensure/set logic
│ └── config.ts # .github/brin.yml loader
└── lib/
├── env.ts # Environment variable validation
├── logger.ts # Structured logging (pino)
├── types.ts # Shared types, constants, label/marker defs
├── brinApi.ts # Brin API HTTP client
└── policy.ts # Verdict evaluation and threshold logic
Maintainers can re-run any Brin check from the GitHub UI by clicking "Re-run" on the check run. The app handles check_run.rerequested events and re-executes the corresponding scan.
npm run dev # start with tsx watch (hot reload)
npm run typecheck # type-check without emitting
npm run build # compile to dist/For local webhook testing, use a tunnel like smee.io or ngrok to forward GitHub webhooks to localhost:3000/api/github/webhook.