Code security review

AI code security review that cites file and line

Paste the handlers, routes and middleware. Your model reads them as an attacker who controls every input, traces each entry point from input to effect, and reports what the code proves, with the file and line for every claim.

Opens the workbench with Code security review selected. 1 hosted review per UTC day on your own key. No card.

ExampleExample output · invented codebase

VerdictFix before deploy

One handler returns any organisation’s invoice by id. Its sibling scopes the same lookup by organisation.

  • 0Critical
  • 1High
  • 0Medium
  • 1Hardening
  • 2Checked safe
input-1/src/routes/invoices.tssha256a06d4f19c3b7…96 lines
F-1HighProven in source

GET /invoices/:id returns any organisation’s invoice

  • input-1/src/routes/invoices.ts:41-45
  • input-1/src/routes/invoices.ts:47-50
Impact

Any signed-in user reads the invoices of every other organisation: amounts, line items and billing contacts. Bound: every invoice whose id the caller knows.

Observed
  1. requireAuth checks that the caller is signed in. It does not check which organisation the invoice belongs to.
  2. Line 42 looks the invoice up by id alone and line 44 returns it.
  3. The sibling DELETE handler scopes the same lookup with orgId: req.user.orgId (line 48).
input-1/src/routes/invoices.ts41–50
router.get('/invoices/:id', requireAuth, async (req, res) => {
  const invoice = await db.invoice.findUnique({ where: { id: req.params.id } });
  if (!invoice) return res.status(404).json({ error: 'Not found' });
  res.json(invoice);
});

router.delete('/invoices/:id', requireAuth, async (req, res) => {
  await db.invoice.deleteMany({ where: { id: req.params.id, orgId: req.user.orgId } });
  res.status(204).end();
});
Counterargument

Invoice ids are UUIDs, so they cannot be guessed.

ResolvedThe sibling handler at line 48 adds the organisation predicate to the same lookup. The codebase itself does not treat the id as the permission.

Evidence gap
  • No request was run. Where ids are exposed (emails, exports, logs) was not supplied.
Fix

Use findFirst with where: { id: req.params.id, orgId: req.user.orgId } at line 42.

Next

Apply the predicate, run the test, then check the other handlers that load by id.

What the code security review checks

The profile works from the entry points inward, in any language.

  1. Entry points

    Every externally reachable handler, route, job, command or exported function, and who reaches it: anyone, a signed-in user, a named role, another service.

  2. Input to effect

    Data followed into queries, shell commands, file paths, templates, deserialisers, outbound requests and cryptographic calls.

  3. Authorization on every lookup

    The tenant or owner predicate belongs inside the query. A check that runs after the fetch is reported.

  4. Sibling diff

    A check one handler performs and its sibling skips, when both guard the same asset.

  5. Secrets and failure paths

    Secrets and personal data in responses, logs and errors. Failure paths that fail open.

  6. State and resources

    Replay, races and check-then-use gaps on state changes. Resource exhaustion from attacker-sized input.

What to paste in

Start with the files that accept input.

  • Source files for the code under review

    Handlers, controllers, resolvers, jobs. Import a pull request from GitHub to review exactly what changed.

  • The routes, config or middleware they rely onOptional

    A control an unsupplied layer provides is reported as depending on that layer, by name.

Up to 50 files, 120 KB per file, 240 KB and 20,000 lines in total. Paste, drop files, or import a repository, pull request or commit from GitHub at a pinned commit.

What comes back

One review in a fixed format, built to be checked against the source.

  • A verdict: fix-before-deploy or no-blocking-issues for your own code, or one of the five bounty verdicts.
  • A finding card per issue: severity, basis, file and line, impact and the path.
  • The strongest counterargument to each finding, marked resolved or open.
  • A fix and a test for each finding.
  • An Entry points table: handler, location, who reaches it, what it changes or returns.
  • Hardening and Checked-and-safe lists, and what was not supplied.
  • A packet with the SHA-256 manifest of every file reviewed.

The rest of the same review

The test for the finding above, and the entry points the profile listed for the invented invoices service.

ExampleExample output · invented codebase · invoices service

test/invoices.test.ts
test('GET /invoices/:id is scoped to the caller organisation', async () => {
  const other = await createInvoice({ orgId: orgB.id });

  const response = await request(app)
    .get(`/invoices/${other.id}`)
    .set('Authorization', `Bearer ${tokenFor(userInOrgA)}`);

  expect(response.status).toBe(404);
});
Entry points
HandlerLocationReached byChanges or returns
GET /invoices/:idLocationinput-1/src/routes/invoices.ts:41-45Reached byauthenticatedChanges or returnsReturns one invoice
DELETE /invoices/:idLocationinput-1/src/routes/invoices.ts:47-50Reached byauthenticatedChanges or returnsDeletes an invoice of the caller’s organisation
POST /invoicesLocationinput-1/src/routes/invoices.ts:18-39Reached byrole:billingChanges or returnsCreates an invoice

Questions

Which languages does it review?

Any language that lives in a text file. The profile reads source as text and cites file and line. It reviews what you supply and runs nothing.

What if a control lives in a file I did not paste?

The finding is marked as depending on unsupplied code and names the layer. Add that file and run the review again.

Which model runs the review?

The one you choose, on your own key: OpenRouter, Anthropic, OpenAI, Google Gemini, xAI, DeepSeek, Mistral or Groq. With a chat subscription, export the prompt, paste it into your chat app and paste the answer back. From a coding agent, prepare_review hands the same request to the agent’s own model over MCP.

Where do my files go?

To the model provider you choose, through our server, for that one request. Bounty Operator does not store your files, prompts, keys or results. With an exported prompt they go from your browser to the chat app you paste into. The packet you download carries a SHA-256 manifest of every file reviewed.

Run a code security review on your own model

Every finding with its file, its line and the argument against it.

Opens the workbench with Code security review selected. Free: 1 hosted review per UTC day. Operator: unlimited, US$10 per week.