In short
- A scan reports what might be wrong; a pentest proves what an attacker can do. NIST's testing guide warns that application scanners typically have high false positive rates, and that they miss flaws too.
- On a typical AI-built app, the critical leaks (an open table, one user reading another's invoices, an unsigned Stripe webhook) answer with a normal
200 OK, so a scanner has nothing to flag. - A version in a CVE's range is a lead, not a finding. The advisory for CVE-2025-29927 says Next.js deployments hosted on Vercel are automatically protected, and the flaw only bypasses auth checks that run in middleware.
- PCI DSS v4.0.1 asks most e-commerce sites for quarterly external scans, and for a yearly pentest only when your SAQ includes requirement 11.4, which SAQ A (Stripe Checkout or Elements) does not. SOC 2 names both only as points of focus, but enterprise customers often ask for a pentest report anyway.
- Proof-based automated testing sits in between: it attacks on every deploy and reports only what worked, but it does not replace a person who reads your business rules.
On this page
- Pentest vs vulnerability scan: the short answer
- Scan, manual pentest and automated pentest compared
- The same app, scanned and then attacked
- Vulnerability assessment vs penetration testing
- When you need a scan, a pentest, or both
- What SOC 2, ISO 27001 and PCI DSS ask for
- Where proof-based automation fits
- How to check your own app this week
- Questions
- Sources
Pentest vs vulnerability scan: the short answer
A vulnerability scan asks what looks wrong. A pentest asks what someone can actually do. The scanner compares what it can see from outside (version numbers, response headers, files it can fetch) with a database of known problems, and lists every match. Nothing is exploited, so nothing is proven. A penetration test is an authorized attack: a tester tries to use the weaknesses, combines them, and reports the ones that worked, with the request as proof.
NIST's testing guide, SP 800-115, defines penetration testing as security testing in which evaluators "mimic real-world attacks in an attempt to identify ways to circumvent the security features of an application, system, or network". It is blunt about scanners: "application vulnerability scanners typically have high false positive rates", and they also suffer from high false negative rates. In plain words, they report problems you do not have and miss some you do.
- Vulnerability scan: an automated check, done in minutes, that matches versions, headers and configuration against known weaknesses. ZAP, a free and open source project, is a common example. To pick one, see the guide to website vulnerability scanners.
- Vulnerability assessment: the scan plus a review. Someone removes the false positives, ranks what is left and plans the fixes. NIST defines it as a systematic examination to "identify security deficiencies". It still attacks nothing.
- Penetration test (pentest): an attack on a live system, within an agreed scope, by people, software or both. A scan is often its first step. What you get is what an attacker could reach, and how.
Scan, manual pentest and automated pentest compared
The PCI Security Standards Council, which writes the card industry's security rules, sums up the split in its penetration testing guidance. A scan's purpose is to "identify, rank, and report vulnerabilities"; a pentest's is to "identify ways to exploit vulnerabilities to circumvent or defeat the security features of system components". A scan takes "several seconds to several minutes per scanned host"; a pentest "may last days or weeks". The last column is the option most founders now meet.
| What you compare | Vulnerability scan | Manual pentest | Proof-based automated pentest |
|---|---|---|---|
| Goal | List known weaknesses that might be exploitable | Prove what an attacker can reach, including multi-step chains and logic flaws | Prove the common attacks on your stack, again on every deploy |
| How it works | Matches versions, headers and files against signatures | A tester attacks within an agreed scope, with tools and by hand | Software runs real attacks and drops every attempt that failed |
| Depth | What responses reveal from the outside | The deepest: roles, business rules, chained flaws | Access control, exposed data, leaked keys, known CVEs; no judgment of business rules |
| Proof | None: "this version is affected" | Requests and screenshots in the report | The request and response behind each finding |
| False positives | Common: NIST calls them high for application scanners | Rare: the tester checks each finding by hand | Rare: a finding needs an attack that worked |
| Frequency | As often as you like, even on every deploy | Yearly, and after major changes | Every deploy |
| Time | Minutes | 1 to 3 weeks for a SaaS or web app | Unattended, after each deploy |
| Cost | Free (ZAP) to a subscription | $5,000 to $30,000 for a SaaS or web app test | Keybrum: €49 for one app, plans from €29 a month (excluding VAT) |
| Counts as a pentest for an audit | No | Usually | Depends on the auditor: ask first |
The same app, scanned and then attacked
Take a typical app built with an AI coding tool: a Next.js 15.1.0 frontend with the App Router, hosted on Vercel, Supabase for the database and sign-in, Stripe for payments. The app is made up; each critical finding below is a pattern Keybrum has an attack for. First, what a scanner reports:
Content Security Policy (CSP) Header Not Set
Missing Anti-clickjacking Header
Vulnerable JS Library
next 15.1.0 matches CVE-2025-55182 (critical, CVSS 10.0)
next 15.1.0 matches CVE-2025-29927 (critical, CVSS 9.1)Every line is accurate, and two are rated critical. Only one of those two is an emergency for this app. Here is what attacking the same app shows, finding by finding:
| Finding | Scanner | What the attack showed | Priority |
|---|---|---|---|
| Next.js 15.1.0 is in the range of CVE-2025-55182, React2Shell | Flagged as critical | Reachable on this App Router app, proven without running any code on the server. | Critical: upgrade to the latest 15.x or 16.x today |
| Next.js 15.1.0 is in the range of CVE-2025-29927 | Flagged as critical | Not reachable: the advisory says deployments hosted on Vercel are automatically protected, and pages that redirect to sign-in still redirected. | Also fixed by that upgrade |
| No Content-Security-Policy header | Flagged | True. It makes other bugs, like cross-site scripting, easier to exploit, but exposes nothing on its own. | Low |
| No anti-clickjacking header | Flagged | True. Another site could load your pages in a frame. It matters on pages with one-click actions. | Low |
| JavaScript library with known CVEs | Flagged | Real only if your code reaches the affected function. The library's advisory tells you which one. | Check, then upgrade |
orders table readable with the public key | Not flagged | Signed out, with the key from the JavaScript bundle, the database API returned customers' emails and order totals. | Critical |
| Other users' invoices | Not flagged | A second account opened the first account's invoice by changing the number in the API request. | Critical |
| Stripe webhook without a signature check | Not flagged | The route accepted an event with no Stripe-Signature header, so a forged "payment succeeded" event would be processed. | Critical |
The scanner caught one emergency, raised a critical that cannot be reached here, and missed the three critical flaws in the app's own code and rules. An open table, an IDOR (insecure direct object reference: one user reaching another's data by changing an id) and an unsigned webhook all answer with a normal 200 OK. Nothing in the response says the data belongs to someone else. To know that, a tester needs two accounts and an idea of who should see what. OWASP's testing guide says it plainly: "Automated tools find it hard to understand context."
A proven finding for the open table looks like this:
Finding orders: readable by anyone, signed out
Attack supabase.table-read
Request GET https://<project>.supabase.co/rest/v1/orders?select=*&limit=10
apikey: <the public key from the JavaScript bundle>
Response 200 OK, 10 rows returned, more counted
Means RLS is off on public.orders, or a policy lets anon read it
Fix enable RLS, add a policy that limits reads to the owner, retestVulnerability assessment vs penetration testing
Many vendors sell a vulnerability assessment: a scan with a person in the loop. PCI's guidance describes even its scans that way, as "a variety of automated tools combined with manual verification of identified issues", with a report of "potential risks posed by known vulnerabilities" ranked by CVSS score (the 0 to 10 severity scale used in CVE records). A pentest report goes further: it describes "specific methods how and to what extent" each weakness may be exploited.
Both are worth paying for, as long as you know which one you bought. Signs that a "pentest" is a scan with a new cover:
- The report is a list of CVEs and missing headers sorted by CVSS score, with no requests or responses.
- Nobody asked you for two test accounts, so nothing checked whether one user can reach another's data.
- No finding says what an attacker could read, change or delete.
- The offer includes no retest of your fixes.
The penetration test report sample shows what a finding with proof should contain, from the request to the retest.
When you need a scan, a pentest, or both
| Your situation | What to run |
|---|---|
| Just shipped, no real user data yet | A passive scan and the free check before launch, then on every deploy |
| Users sign in and store data, or you take payments | Proof-based tests on every deploy, starting with access control and leaked keys |
| An enterprise customer sends a security questionnaire or asks for a pentest report | A manual pentest with a formal report, scoped to the product they will use |
| A SOC 2 or ISO 27001 audit is coming | Ask your auditor what evidence they accept, then plan scans and a pentest around it |
| You take card payments | Depends on your SAQ: external scans for most sites, a yearly pentest only if requirement 11.4 applies. See the PCI DSS penetration testing guide |
| A big change: new roles, a new payment flow, teams or multi-tenancy | Test again before release: that is when access control breaks |
If you are not sure which row you are in, start with access control. In the scan behind CVE-2025-48757, 170 of 1,645 apps built with Lovable, about one in ten, had missing or weak RLS that let unauthenticated visitors read or write data (Lovable disputes the CVE). No header or version scan would have flagged them.
For the enterprise row: in an article republished by the Cloud Security Alliance, a CPA calls a pentest "the most common requirement we hear as the last component to close a deal with an enterprise customer". If a questionnaire is waiting in your inbox, the security questionnaire guide covers what you can answer honestly.
What SOC 2, ISO 27001 and PCI DSS ask for
| Framework | Vulnerability scans | Penetration tests |
|---|---|---|
| SOC 2 | A point of focus under CC7.1: the entity "conducts vulnerability scans" periodically and after any significant change | A point of focus under CC4.1 lists penetration testing among the "ongoing and separate evaluations" management can use |
| ISO 27001:2022 | Annex A control 8.8, management of technical vulnerabilities; guides to the ISO 27002 text list vulnerability scanning tools | The same guides list periodic, documented penetration tests |
| PCI DSS v4.0.1 | Requirement 11.3: internal and external scans at least once every three months, external ones by an Approved Scanning Vendor (ASV) | Requirement 11.4: internal and external pentests at least once every 12 months and after significant changes, for merchants and service providers whose SAQ or assessment includes it |
SOC 2 points of focus are examples, not requirements. The same CPA puts it this way: "there are no explicit requirements for penetration testing (or any controls) within a SOC 2 report".
Where proof-based automation fits
Between the scanner and the consultant sits software that attacks like a pentester, at the price and speed of a scan. One rule separates it from a scanner: no attack that worked, no finding.
Keybrum works this way. It runs more than 100 attacks against the live app: Supabase tables, RPC and storage, Firebase rules, secrets in the JavaScript bundle, unprotected AI endpoints, unsigned Stripe webhooks, exposed .env files, and known Next.js and React CVEs. It tests IDOR across two accounts, and it never sends remote code execution or denial-of-service payloads.
It only attacks apps whose owner proved ownership. Each fix goes to your coding agent (Cursor, Claude Code) through Keybrum's MCP server, and Keybrum attacks again after the fix and on every deploy.
What it does not replace: a person who reads your business rules and asks what happens if a coupon is applied twice, or a refund is requested after a plan change. Nor a report signed by a human tester, which an auditor or enterprise buyer may require. The automated pentest guide goes through its limits, and the web app pentest guide covers what a manual engagement adds.
How to check your own app this week
- 1
Run a passive scan of your own site
ZAP's baseline scan crawls your site for a minute and reads the responses without sending attacks:
docker run -t ghcr.io/zaproxy/zaproxy:stable zap-baseline.py -t https://your-app.com. For the header findings, the security headers checker gives the exact fix for Next.js, Vercel and Netlify. - 2
Triage each finding with one question
Can you show the request that abuses it? If not, it is a lead. For a version match, read the advisory's conditions: hosting, configuration, and whether your code reaches the flawed path.
- 3
Test what scanners miss, with two accounts
Sign up twice on your own app. As account A, note the ids in the pages and in the API calls of the browser's network tab. As account B, request the same ids. If B sees A's data, you have an IDOR: the IDOR guide shows the fix.
- 4
Check the database rules
On Supabase, run the query from the RLS checker to list tables with row level security off. On Firebase, paste your rules into the Firebase rules checker.
- 5
Retest after every fix
A fix is done when the attack that proved the finding fails again on the deployed app.
Questions
Is a vulnerability scan the same as a penetration test?
No. A scan matches what it sees against known weaknesses and reports possible problems without exploiting anything. A pentest attacks the system and reports what actually worked, with proof. Selling a scan under the name pentest is common, so check what the report contains.
What is the difference between a vulnerability assessment and penetration testing?
A vulnerability assessment is a scan plus a review: false positives removed, the rest ranked by severity. A penetration test goes on to exploit the weaknesses and shows what an attacker could reach. Use the assessment to keep track of known issues, and the pentest to learn what they let someone do.
Does SOC 2 require a penetration test?
Not explicitly. The SOC 2 criteria name penetration testing in a point of focus under CC4.1, and vulnerability scans under CC7.1, and points of focus are examples rather than requirements. In practice many auditors and enterprise customers expect a recent pentest report, so ask your auditor early.
How often should you run vulnerability scans and pentests?
PCI's guidance sets a common baseline: scans at least quarterly and after significant changes, pentests at least yearly and after significant changes. For an app that ships every week, that is too slow on its own. Run scans or proof-based tests on every deploy, and book a manual pentest yearly or before a major release.
Can automated penetration testing replace a manual pentest?
For the common attacks on your stack, repeated on every deploy, it covers ground a yearly test cannot. It cannot judge business rules, and some auditors and customers want a report from a human tester. Many teams use both: automation between releases, a manual test when an audit or a deal asks for one.
Why do vulnerability scanners report false positives?
Most scanners match versions and signatures. A version can sit in a CVE's range while the flaw is out of reach: the host blocks it, the vulnerable function is never called, or the fix was backported. NIST's testing guide says application scanners typically have high false positive rates and that someone has to interpret the results.
Sources
- 1.Information Supplement: Penetration Testing Guidance (v1.1, section 2.1), PCI Security Standards Council
- 2.SP 800-115, Technical Guide to Information Security Testing and Assessment, NIST
- 3.Glossary: penetration testing, NIST CSRC
- 4.Glossary: vulnerability assessment, NIST CSRC
- 5.Authorization bypass in Next.js middleware (GHSA-f82v-jwr5-mffw, CVE-2025-29927), GitHub Advisory Database
- 6.Critical Security Vulnerability in React Server Components (CVE-2025-55182), React
- 7.Introduction to business logic testing, OWASP Web Security Testing Guide
- 8.ZAP baseline scan, ZAP
- 9.Content Security Policy (CSP) Header Not Set (scan rule 10038), ZAP
- 10.Anti-clickjacking Header (scan rule 10020), ZAP
- 11.Vulnerable JS Library (alert 10003), ZAP
- 12.CVE-2025-48757, CVE Program
- 13.Statement on CVE-2025-48757, Matt Palmer
- 14.Vulnerability Assessment vs Penetration Testing for SOC 2 Audits, Linford & Co
- 15.SOC 2 Reports and Penetration Tests, Cloud Security Alliance
- 16.ISO 27001:2022 Annex A 8.8, Management of Technical Vulnerabilities, ISMS.online
- 17.PCI DSS Requirement 11: Test Security of Systems and Networks Regularly, Basis Theory
- 18.How much does penetration testing cost?, Blaze Information Security