SlopCop

This is a synthetic example of a completed review. The repository, its code and its findings are made up, not taken from a real scan.

Analysis complete

example/acme-service

Commit 7b4e2a1

Findings

Review results

28 of 28 deterministic checks finished · Coverage may be incomplete
  1. Source preparation: complete
  2. Deterministic checks: partial coverage
  3. Confidence review: complete
  4. Interpretation and design: complete
  5. Historical replay: complete

Session creation ignores the password check

src/auth/login.tsLine 22
export async function login(username: string, password: string): Promise<Session> {  await rateLimit.check(`login:${username}`, MAX_ATTEMPTS);  const valid = await verifyCredentials(username, password);  audit.record("login-attempt", { username });  return database.createSession(username);···
Problem

login stores the result of verifyCredentials in valid but never reads it, so database.createSession runs whether or not the password matched.

Impact

Unless a caller checks the password again, a wrong password still returns a working session for that username.

Recommended solution

Throw an authentication error when valid is false, before the session is created, and add a test that a wrong password creates no session.

Why this was flagged
Check

Dead code and unused abstractions matched src/auth/login.ts:22. Report this finding as a false positive to suppress it.

Source read for this finding
  • src/auth/login.ts:18-30
Limits
  • 2 of 28 deterministic checks did not complete for this revision, so other signals for these lines may be missing.

Dry-run mode still deletes the account

src/accounts/delete-account.tsLines 16–17
export async function deleteAccount(accountId: string, { dryRun = false } = {}) {  const account = await database.getAccount(accountId);  if (dryRun) logger.info(`Would delete account ${account.id}`);  await database.deleteAccount(account.id);  await audit.record("account-deleted", { accountId });}
Problem

When dryRun is true, deleteAccount logs the preview and carries on to database.deleteAccount, because the dry-run branch never returns.

Impact

A dry run deletes the account it was meant to preview, and the audit log records the deletion as real.

Recommended solution

Return straight after logging the preview, or move the deletion into an explicit else branch, and add a test that a dry run leaves the account in place.

Why this was flagged
Check findings at these lines

No check finding in this report is at these lines. This finding comes from the AI review reading the source below.

Source the review cited
  • src/accounts/delete-account.ts:14-19
Limits
  • The AI review reads selected excerpts of the repository, not every file. This finding is a reviewed judgement about the lines above, not a deterministic match.
  • This finding has no identity that carries across scans, so it can’t be suppressed on its own.
  • 2 of 28 deterministic checks did not complete for this revision, so other signals for these lines may be missing.

Invoice export checks session expiry with its own rule

Two places decide when a session expires

Two places decide when a session expires. 3 reviewed components and 2 reviewed relationships. Export route reads the session cookie (src/routes/billing.ts:22–25) leads to Export handler checks idle time itself (src/billing/export-invoices.ts:27–29): Passes a raw session id (src/routes/billing.ts:23). Export handler checks idle time itself (src/billing/export-invoices.ts:27–29) leads to Auth defines expiry and revocation (src/auth/sessions.ts:13–18): Uses 30 minutes and skips revocation (src/billing/export-invoices.ts:29).

Directed evidence graphUses 30 minutes andskips revocationPasses a raw session idAuth defines expiryand revocationsessions.ts:13–18Export handler checksidle time itselfexport-invoices.ts:27–29Export route reads thesession cookiebilling.ts:22–25
Source evidence
  • Finding: src/billing/export-invoices.ts:27–29Finding sourcesrc/billing/export-invoices.ts:27–29
  • Component: Export route reads the session cookieSourcesrc/routes/billing.ts:22–25
  • Component: Export handler checks idle time itselfSourcesrc/billing/export-invoices.ts:27–29
  • Component: Auth defines expiry and revocationSourcesrc/auth/sessions.ts:13–18
  • Relationship: Export route reads the session cookie → Export handler checks idle time itselfRelationship sourcesrc/routes/billing.ts:23
  • Relationship: Export handler checks idle time itself → Auth defines expiry and revocationRelationship sourcesrc/billing/export-invoices.ts:29
Source 1 of 3
src/billing/export-invoices.tsLines 27–29
  const session = await database.sessions.find(request.sessionId);  const idleMinutes = (Date.now() - session.lastSeenAt.getTime()) / 60_000;  if (idleMinutes > 30) throw new UnauthorizedError("Session expired");
Text alternative
Reviewed components
  1. Export route reads the session cookieSourcesrc/routes/billing.ts:22–25
  2. Export handler checks idle time itselfSourcesrc/billing/export-invoices.ts:27–29
  3. Auth defines expiry and revocationSourcesrc/auth/sessions.ts:13–18
Reviewed relationships
  1. Export route reads the session cookieExport handler checks idle time itself
    Passes a raw session idRelationship sourcesrc/routes/billing.ts:23
  2. Export handler checks idle time itselfAuth defines expiry and revocation
    Uses 30 minutes and skips revocationRelationship sourcesrc/billing/export-invoices.ts:29
Problem

The export route passes the raw session id to the export handler, which reads the session row and applies its own 30-minute idle limit with no revocation check, instead of calling isSessionActive.

Impact

A revoked session, or one idle for 20 to 30 minutes, can still export invoices after the rest of the service has signed it out.

Recommended solution

Check the session with isSessionActive before exporting, and keep the expiry rule, timeout included, in the auth module.

Why this was flagged
Check findings at these lines

No check finding in this report is at these lines. This finding comes from the AI review reading the source below.

Source the review cited
  • src/billing/export-invoices.ts:27-29
  • src/routes/billing.ts:22-25
  • src/auth/sessions.ts:13-18
Limits
  • The AI review reads selected excerpts of the repository, not every file. This finding is a reviewed judgement about the lines above, not a deterministic match.
  • This finding has no identity that carries across scans, so it can’t be suppressed on its own.
  • 2 of 28 deterministic checks did not complete for this revision, so other signals for these lines may be missing.

Exchange rates are fetched once per invoice

src/billing/invoice-totals.tsLines 23–24
export async function invoiceTotals(invoices: Invoice[], currency: Currency) {  const totals = new Map<string, number>();  for (const invoice of invoices) {    const rate = await exchangeRates.fetchRate(invoice.currency, currency);    totals.set(invoice.id, invoice.amount * rate);  }···
Problem

invoiceTotals awaits exchangeRates.fetchRate inside the loop, so it sends one request per invoice and each request waits for the one before it.

Impact

The endpoint slows down as invoice lists grow and asks again for currency pairs it has already fetched. How much that matters depends on typical list sizes and the rate service's limits.

Recommended solution

Fetch each distinct currency pair once before the loop, or use a batch lookup if the rate service has one, then measure the endpoint with a realistic number of invoices.

Why this was flagged
Check

Network requests in a loop matched src/billing/invoice-totals.ts:23-24. Report this finding as a false positive to suppress it.

Source read for this finding
  • src/billing/invoice-totals.ts:21-28
Limits
  • 2 of 28 deterministic checks did not complete for this revision, so other signals for these lines may be missing.
Deterministic checks26 complete2 partialComplete means the server marked a check as fully covered. Coverage may be incomplete; finished checks do not by themselves establish full coverage. Partial checks may still contribute findings despite limits.

Source coverage: complete; no files omitted.

History coverage: complete; 100 of 100 requested commits examined.

Design review2 reviewed
  • Modularity reviewreviewed
  • Coupling reviewreviewed
Source language support100% supportedTypeScript · JavaScript196 recognized source files

File types at this commit indicate language support; they do not measure how much code was indexed or analyzed. Configuration, documentation, and other files are excluded.

  • TypeScript93.9% · Supported
  • JavaScript6.1% · Supported

See what turns up
in your own code.

Create an account, pick a repository, and SlopCop starts indexing it.

Set it up with us.

Leave your email and we’ll arrange a call about running SlopCop in your team’s coding agents and CI, or anything else you’d like to know.

We’ll use your email to respond. No scan or report is needed.