VANDAMLet’s talk

VANDAMAdversarial App Audit

Verified security findings.Code fixes included.

A focused security review of your application. For each verified finding, you receive steps to reproduce the issue, the affected code and a proposed fix, together with the checks behind the report.

$4,800 one week

Can one customer open another customer’s order?

GET /api/orders/1043signed in as customer 311

404 Not Found

  1. Browsercustomer 311
  2. APIorders route
  3. Ownership checkadded
  4. Orders
    • 1041customer 311
    • 1042customer 311
    • 1043customer 287

Any signed-in customer can read any order.

HighReproduced 3 of 3api/orders/[id].ts:14

The route loads an order by its number and never compares the order’s owner with the person signed in. Changing 1042 to 1043 in the address returns another customer’s order, with name, address and items.

GET /api/orders/1043   session: customer 311200 OK   order 1043 · customer 287 · 3 items

Look the order up within the signed-in account.

api/orders/[id].ts1 line changed

const { id } = req.paramsconst order = await db.orders.find({ id })const order = await db.orders.find({ id, customerId: session.customerId })if (!order) return notFound()

orders.test.tsregression test

passedanother customer’s order returns 404

passedyour own order still opens

One missing check is the most common flaw on the web.

#1
Broken access control tops the OWASP Top 10, the security industry’s standard list of web app risks, 2025.
#1
Reading another customer’s record by changing an ID tops the OWASP API Security Top 10, rated easy to exploit and widespread.
$10.22M
average cost of a data breach in the US, a record. IBM, Cost of a Data Breach, 2025.

Our research shows models are getting better at coding accurately but are not improving at security.

Jens WesslingCTOVeracodeJuly 2025Source

So no, code that passes its tests can still show one customer another’s data.

Give engineering something it can act on.

A security report that says access control is weak leaves engineering with the real work still to do: find where it fails and decide what to change. A useful finding names the request that breaks it, the code responsible and the fix.

We test sign-in, data access, storage and payments within an agreed scope, the places where one missing check exposes another customer’s records. Every issue is reproduced, then rechecked before it reaches the report. Your engineers get the reproduction, the affected files, a proposed code change and a test that shows the hole is closed.

What engineering works through.

One list of findings, each reproduced before it reaches you. A finding opens on the request that breaks the check, the response it returned, the file and line responsible and the proposed change. Nothing in the list is a guess, and nothing asks your team to repeat our testing to believe it.

Engineers assign a finding, apply the change and mark it ready. We rerun the original reproduction against the fix, together with the test that shows your own records still open. When a release changes the routes we tested, the team sends a retest request naming the release and the findings it touches.

What every report contains.

Your application differs. The structure of the report does not.

  • Scope record

    The environment, accounts and features we agreed to test, and what stayed out.

  • Access map

    Who can sign in, which records each role can reach, and how storage and payments are handled.

  • Misuse cases

    The realistic attempts we made against each boundary, including the ones that held.

  • Reproduction

    The request or action that demonstrates each finding, run more than once.

  • Affected code

    The files and lines responsible, so an engineer can go straight to them.

  • Proposed fix

    Replacement code with the location and the reason for the change.

  • Regression test

    A test that shows the hole is closed and that legitimate access still works.

  • Review record

    The scope, evidence and checks behind the report, kept together.

  1. Agree and map the scope

    We identify the application boundaries to review, including who can sign in, which records they can access and how storage and payments are handled. Testing stays within the agreed environment and scope.

    Scope
    • Sign-in · email + Googlein scope
    • Customer recordsin scope
    • File storagein scope
    • Payments · Striperead only
  2. Reproduce the finding

    We test realistic misuse cases and recheck any suspected issue. A finding includes the request or action that demonstrates it and the relevant files, so another engineer can follow the evidence.

    Finding 03 · reproduced
    • GET /api/invoices/8812
    • signed in as: customer A
    • 200 OK · returns customer B’s invoice
    • file: api/invoices/[id].ts, line 14
  3. Deliver the code change

    We prepare replacement code with the location and reason for the change. The review record keeps the original reproduction, supporting evidence and checks together so your team can assess the fix.

    Fix · api/invoices/[id].ts
    • const invoice = await db.invoice.find(id)
    • const invoice = await db.invoice.find({ id,
    • ownerId: session.user.id })
    • if (!invoice) return notFound()

Tested this week.
Retested after each release.

The report describes your application as it was during the audit week. Every release can add a route or remove a check, so after delivery we can rerun the reproductions and test what changed.

  • Fix verification

    We rerun the original reproduction against each fix your team ships, and record the result in the finding.

  • Release retests

    Before or after a release, we retest the findings and routes it touches.

  • New scope

    New roles, routes, storage or payment flows reviewed with the same method as the first audit.

  • Check-ins

    A short session with engineering on open findings, accepted risks and what the next release changes.

What you
receive.

  • Verified findings

    Reproduced issues linked to the relevant files and lines.

  • Code fixes

    Replacement code for the findings we verify.

  • Review record

    The scope, evidence and checks behind the report.

Developers with an AI assistant wrote significantly less secure code, and were more likely to believe it was secure.Stanford study by Perry, Srivastava, Kumar and Boneh, 2023

Before you ask.

Do you test on our production system?

We agree the environment and the test accounts before we start, and testing stays inside them. Anything outside the agreed scope is left alone.

What if you find nothing serious?

The report says so. The review record shows what we tested and how, so the result can be checked.

Do our engineers apply the fixes?

Yes. We deliver replacement code with the location and reason for each change, and your team reviews and merges it.

Can we share the report in a customer’s security review?

The report is yours to share. It covers the scope we agreed and says so, which matters if the customer asks about other parts of your system.