MERGEHOUND™ logo and tagline
Security & coverage

What MERGEHOUND™ scans — and what we never keep.

OWASP Top 10 coverage per PR, read-only on the diff, four GitHub-App permissions and no others, and findings landing inline on the PR — the same four commitments a security lead can verify on a single page.

What gets scanned

OWASP Top 10 coverage, mapped per finding.

Every check is wired against the OWASP Top 10 (2021) and the GitHub Advisory Database. Below is what MERGEHOUND™ emits per category — CWE-tagged inline comments where the diff shows it, advisory cross-reference where in-diff detection is the wrong shape.

A01

Broken Access Control

CWE-862 / CWE-639 inline comments flag missing owner-check, IDOR, and path-traversal sinks.

Cross-references · OWASP ASVS V4 (access control) + V1.4 (architecture).

A02

Cryptographic Failures

Hardcoded keys, weak JWT alg pinning, broken TLS verification, deprecated ciphers — caught before the diff lands.

Cross-references · OWASP ASVS V6 (cryptography) + GitHub Secret Scanning corpus.

A03

Injection

SQL, command, template-injection sinks and tainted-string → eval()-style patterns, CWE-tagged per finding.

Cross-references · OWASP ASVS V5 (input handling) + CWE top-25 injection list.

A04

Insecure Design

Surfaced through dependency advisory hits and missing-control comments — e.g. an auth library on the vulnerable list without a comment flag.

Cross-references · OWASP ASVS V1 (architecture) + advisory database cross-reference.

A05

Security Misconfiguration

CORS allow-any defaults, debug flags enabled in prod paths, IAM policy that grants more than the diff needs.

Cross-references · OWASP ASVS V14 (configuration) + service-specific hardening guides.

A06

Vulnerable & Outdated Components

Every transitive dep cross-checked against the GitHub Advisory Database — severity, fix, exploit, reachability.

Cross-references · GitHub Advisory Database + OSV.dev + npm/pip ecosystem feeds.

A07

Identification & Auth Failures

Auth fallbacks, missing JWT algorithm pinning, broken session rotation, "log everyone in as admin" defaults.

Cross-references · OWASP ASVS V2 (authentication) + V3 (session management).

A08

Software & Data Integrity Failures

Unsigned CI artifacts, missing SBOM lineage, CI workflows that fetch without a pinned commit SHA.

Cross-references · OWASP ASVS V10 (malicious code) + SLSA provenance shape.

A09

Security Logging & Monitoring Failures

No in-diff finding — contribution is via the per-repo audit log itself (who/what/when, CSV-exportable), see the data-handling section below.

Cross-references · OWASP ASVS V7 (error handling and logging).

A10

Server-Side Request Forgery

User-influenced URL → outbound fetch paths, internal-only headers re-enabled after refactors, DNS rebinding sinks.

Cross-references · OWASP ASVS V12 (file and resource handling) + CWE-918.

Severity is graded against the OWASP risk rating and the GitHub Advisory Database — not upward by us to make the review feel louder.

PR-only data handling

Read on the PR diff, never beyond it.

MERGEHOUND™ is read-only on the PR diff. No full-repo clone, no fork-fetch, no reading files outside the diff plus its small context window. Nothing outside the open PR is fetched, and nothing outside the audit log is stored.

Read

PR diff + small context only.

  • PR title, description, the diff, and a small window of surrounding context — just enough to know what the change does.
  • Resolved file paths and the language map. Necessary to route the review, never used to fingerprint your codebase.
  • Reviewer ids on the audit log — who opened, reviewed, and merged. Used only for "SOC2-friendly audit log export".

Retained

The audit log is the trail.

  • Per-repo audit log of who/what/when — exportable as CSV on Team and via the SOC2 evidence endpoint on Enterprise.
  • PR metadata (number, title, author, branch) — kept for the lifetime the PR is open, dropped when it is closed and the audit window is over.
  • Aggregated retry + error buffers — 24h hot, 30d retry, 90d audit. Those windows are surfaced on the audit log export itself.

Never persisted

No training, no resale.

  • No model training on your code — on any plan, including free public repos. The diff is processed for the review and then dropped from the inference path.
  • No code retention beyond the audit window. We don’t sell or share PR data, period.
  • No retention of files you didn’t change. MERGEHOUND™ reads only the diff and the small context window the review needs.
The PR-only commitment

Inference is the only consumer of the diff and processes it only for the lifetime of that one review. No code is stored, no full-repo clone is taken, and no files outside the diff plus its context window are fetched. The audit log records what was read and when — nothing else.

GitHub App permissions

Four permissions, no more, no less.

The App asks for read access to pull requests and repository metadata, and write access to comments and checks. Each one is justified by a specific review behavior; nothing is requested speculatively.

Pull requests — read

Read

Read PR title, description, base/head SHA, the diff hunks, and patch context. Without this the review cannot run at all.

Pull request comments — write

Write

Post inline reviews and the "request changes" / "comment" / "approve" annotations next to the offending file. This is the only write surface.

Repository metadata — read

Read

Resolve file paths, default branch, and the per-language map. Used to route the review; never used to fingerprint or score the repo.

Checks — read + write

Read + write

Read the existing CI annotations to avoid duplicate lines and write its own PR check so the review shows up in the branch protection gate.

Issues — read + write

Read + write

Used only as a fallback when a finding is too wide for an inline comment — the App files a tracker issue on the same repo so the detail is one click away.

What the App cannot do
  • cannot merge, close, or reopen pull requests
  • cannot push, edit, or delete files in the repository
  • cannot install webhooks on issue repositories
  • cannot act outside the comment thread it owns
How findings surface

Inline on the PR, plus an end-of-day digest.

Every finding lands as an inline comment from mergehound-bot and a matching CI annotation. The Slack/Teams digest is a complement, never the source of truth.

Track 1 — Inline PR comment + CI annotation

The review, right where the diff is.

acme/checkout-servicePR #482 · feat: JWT hardening + rate-limit alert
mergehound · 3 findings
  • src/lib/auth/session.tsTS
  • src/lib/rate-limit.tsTS

@@ -42,7 +42,9 @@ export async function verifySession

  • 42
  • const token = req.headers.get('authorization')?.slice(7)
  • if (!token) throw new SessionError('missing token')
  • return jwt.verify(token, process.env.JWT_SECRET)
  • }
    Alert

    Pin the JWT algorithm to HS256.

    Without an explicit algorithms list, jwt.verify will accept any algorithm the token advertises — including "none" on misconfigured libs. Pin to an allow-list before merging.

  • const decoded = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] })
  • if (Date.now() - decoded.iat * 1000 > MAX_TOKEN_AGE_MS) {
    Info

    Token age check looks right.

    Comparing decoded.iat against MAX_TOKEN_AGE_MS prevents replay of long-lived session tokens. Verified against the OWASP ASVS V3 session-timeout control.

  • throw new SessionError('token too old')
  • }
  • return decoded
  • }

@@ -110,4 +114,6 @@ export async function enforceRateLimit

  • 114
  • const count = await redis.incr(key)
  • if (count > limit) throw new RateLimitError()
  • if (count === limit + 1) {
  • await notifyOncall(key, count)
    Alert

    Pin the JWT algorithm to HS256.

    Without an explicit algorithms list, jwt.verify will accept any algorithm the token advertises — including "none" on misconfigured libs. Pin to an allow-list before merging.

  • }
  • return { count, remaining: Math.max(0, limit - count) }
    Info

    Token age check looks right.

    Comparing decoded.iat against MAX_TOKEN_AGE_MS prevents replay of long-lived session tokens. Verified against the OWASP ASVS V3 session-timeout control.

3 inline commentsmergehound-bot · posted ~30s after PR opened

Every finding ships as an inline PR comment mergehound-bot posts next to the offending file, AND a CI annotation in the format your existing pipeline already acts on. No second dashboard, no second login — the review lives where the code lives.

The inline review is the source of truth; every other surface is a convenience on top of it.

Track 2 — Slack / Teams digest

One rollup, end of day.

One end-of-day rollup to the channel you pick on install. New regressions, merge-blockers, and stalled PRs land in a single thread so standup already has the headline when it opens.

Timezone-aware — no digest is posted after 22:00 local or on weekends, so the rollup stays out of out-of-office windows. The digest doesn't replace the inline review; it's the magazine, the review is the newspaper.

Compare to linter aggregators

Head-to-head matrices, same eight dimensions.

See MERGEHOUND™ weighed against the linter-aggregator peer set on coverage model, OWASP / SAST scans, baseline regression, Slack digest, timezone coverage, install scope, pricing, and data handling — each peer page cites the vendor's public surface so the comparison stays a verifiable reference.

Want the audit packet?

Email us for the controls map / DPA / status letter.

No invented certs, no fabricated pen-test results — just the controls map, SOC2 status letter (audit in progress), DPA, and subprocessor list, on request.