No subscriptions — Pay only for the PRs you review

Every PR reviewed.
Every risk caught.

Getdiffense connects to your GitHub repos and automatically detects security vulnerabilities, database performance issues, and logic flaws — before the merge button is pressed.

No monthly fees. No credit card required to start. GitHub OAuth only.

Getdiffense — PR #142 auth-refactor
Critical
IDOR in src/routes/documents.ts:47

Document lookup uses req.params.id without verifying ownership against req.user.id. Any authenticated user can access any document.

High
N+1 query in src/services/project.service.ts:83

findMany() followed by per-item user.findUnique() inside loop. Will fire N+1 queries for N projects.

Medium
Missing pagination in src/routes/feed.ts:21

findMany() with no take limit. Will return entire table as dataset grows.

Built for TypeScript backends

Node.js APIsPrisma + PostgresExpressTypeScriptGitHub PRsREST APIs

The problem

Code review catches style.
It misses production risks.

Human reviewers are great at logic and readability. They are not trained to spot every IDOR pattern, every N+1 query, or every missing auth guard across hundreds of changed lines. That's what machines are for.

68%

of security incidents trace back to a code change that was reviewed and approved

4.5×

more expensive to fix a vulnerability post-deployment than pre-merge

12 min

average time a developer spends reviewing a pull request — not enough for deep security analysis

How it works

Zero friction. Fully automatic.

Your team keeps working the same way. Getdiffense runs silently in the background.

01

Install the GitHub App

Select the repos you want covered. No code changes, no CI config, no YAML. Just select and go.

02

Open a pull request

The webhook fires the moment a PR is opened or updated. Your team works exactly as before.

03

Three agents run in parallel

Security, Database, and Code agents each analyse the diff independently — simultaneously — in under 30 seconds.

04

Findings land on the PR

Every finding includes the exact file path, line number, severity, and a plain-English explanation of the risk.

PR #142 · auth-refactor · 2.4s total

0mswebhook received
12msjob enqueued
38msbilling checked
210msdiff fetched
215msagents started
1840mssecurity agent done
2100msdb agent done
2380mscode agent done
2390msresults merged
2440msPR comment posted
2460msemail sent

Real findings

What it catches

Three real vulnerability classes, with the code pattern that triggers them and the exact finding Getdiffense produces.

CRITICAL · Security Agent

IDOR — Broken Object Level Authorization

A route that fetches a resource by ID from the URL without checking whether the requesting user owns it. Any authenticated user can read or mutate any other user's data.

src/routes/invoices.tsvulnerable
router.get('/invoices/:id', requireAuth, async (req, res) => {
  const invoice = await prisma.invoice.findUnique({
    where: { id: req.params.id },   // ID comes from the URL
  });

  if (!invoice) return res.status(404).json({ error: 'Not found' });

  // No ownership check — any logged-in user can access this
  res.json(invoice);
});
src/routes/invoices.ts — fixedfixed
router.get('/invoices/:id', requireAuth, async (req, res) => {
  const invoice = await prisma.invoice.findUnique({
    where: {
      id: req.params.id,
      userId: req.currentUser.id,   // ownership enforced at DB level
    },
  });

  if (!invoice) return res.status(404).json({ error: 'Not found' });

  res.json(invoice);
});
Finding

IDOR: Invoice lookup at line 2 uses req.params.id without filtering by req.currentUser.id. Any authenticated session can enumerate and read all invoices.

HIGH · DB Agent

N+1 Query — Silent Performance Bomb

Fetching a list of records then querying the database once per record inside a loop. Works fine in development with 10 rows. Destroys performance in production with 10,000.

src/services/project.service.tsvulnerable
async function getProjectsWithOwners(orgId: string) {
  const projects = await prisma.project.findMany({
    where: { orgId },
  });

  // N database queries for N projects
  for (const project of projects) {
    project.owner = await prisma.user.findUnique({
      where: { id: project.ownerId },
    });
  }

  return projects;
}
src/services/project.service.ts — fixedfixed
async function getProjectsWithOwners(orgId: string) {
  // 1 query total — Prisma joins the relation
  const projects = await prisma.project.findMany({
    where: { orgId },
    include: { owner: true },
  });

  return projects;
}
Finding

N+1 query: prisma.user.findUnique() called inside loop at line 8 after findMany() at line 2. Will execute N+1 queries for N projects. Use include: { owner: true } instead.

HIGH · Security Agent

Missing Auth Guard — Exposed Admin Route

An admin endpoint that performs a privileged action but only checks that the user is logged in — not that they have the admin role.

src/routes/admin.tsvulnerable
router.delete('/admin/users/:id', requireAuth, async (req, res) => {
  // requireAuth only checks the session exists.
  // Any logged-in user can delete any account.
  await prisma.user.delete({ where: { id: req.params.id } });
  res.json({ deleted: true });
});
src/routes/admin.ts — fixedfixed
router.delete(
  '/admin/users/:id',
  requireAuth,
  requireRole('admin'),   // explicit role check
  async (req, res) => {
    await prisma.user.delete({ where: { id: req.params.id } });
    res.json({ deleted: true });
  }
);
Finding

Broken access control: DELETE /admin/users/:id at line 1 uses requireAuth but no role check. Any authenticated user can delete arbitrary accounts. Add requireRole('admin') middleware.

Detection coverage

Three agents. One diff.

Each agent has a focused system prompt and runs at temperature 0. Deterministic, structured JSON output — no hallucinated findings.

Security

Security Agent
  • IDOR / broken object-level auth
  • Missing auth and role checks
  • Sensitive data in API responses
  • JWT algorithm confusion / weak secrets
  • SQL and command injection

Database

DB Agent
  • N+1 queries
  • Missing indexes on filtered columns
  • Unbounded findMany() without pagination
  • Large joins without selective WHERE
  • Non-atomic multi-write sequences

Logic

Code Agent
  • Off-by-one and incorrect conditionals
  • Unhandled promise rejections
  • Missing input validation at API boundaries
  • Unsafe type coercions hiding runtime errors
  • Race conditions on shared state

Pricing

Pure Pay-As-You-Go

No monthly subscriptions. Buy credits, use them on any repo. PR charges are based on the size of the diff.

Per-PR Pricing

Small

$0.10

< 100 lines

Medium

$0.25

100-500 lines

Large

$0.50

500-2k lines

Massive

$0.75

> 2k lines

Buy Credits

Basic
$10

Solo devs

Face Value$10
Bonus+$0
Total Credit$10
Buy Pack
Best Value
Growth
$25

Teams

Face Value$25
Bonus+$3
Total Credit$28
Buy Pack
Pro
$50

Active

Face Value$50
Bonus+$8
Total Credit$58
Buy Pack
Scale
$100

Scale

Face Value$100
Bonus+$20
Total Credit$120
Buy Pack

No surprise charges. Credits never expire. Use across any number of repositories.

Ship with confidence.
Not with fingers crossed.

Every PR. Every repo. Every risk — caught before production.

No monthly fees. No credit card required to start.