Vulnerability Assessment vs Penetration Testing
In India you will hear the word VAPT constantly: in job adverts, in tenders and in audit requirements from regulators. It stands for Vulnerability Assessment and Penetration Testing, two related but different activities that together give an organisation a realistic picture of its security.
In this lesson you will learn how a vulnerability assessment differs from a penetration test, the phases of a professional VAPT engagement, how scoping and rules of engagement keep a test safe and legal, and how testers turn raw scanner output into verified findings.
VA and PT are different jobs
| Vulnerability assessment (VA) | Penetration test (PT) | |
|---|---|---|
| Question it answers | "What known weaknesses do we have?" | "What could a real attacker actually achieve?" |
| Approach | Broad, mostly automated scanning plus verification | Narrower, mostly manual, goal-driven |
| Depth | Lists vulnerabilities, usually without exploiting them | Safely exploits weaknesses to prove impact, chaining small issues together |
| Typical output | A prioritised list of vulnerabilities | A narrative of attack paths with evidence |
| How often | Often (monthly, after every big change) | Less often (yearly, before a major launch) |
A scanner might report "outdated Apache version" and "login form without rate limiting". A penetration tester checks whether the outdated version is actually exploitable in this configuration, tries (within the agreed limits) to show what the missing rate limit allows, and explains the real business impact. Many Indian regulators and large clients ask for periodic VAPT, and government bodies often require auditors from CERT-In's list of empanelled security auditing organisations.
Types of test
- Black box: the tester gets only a URL or IP range, like an outside attacker. Realistic, but time is spent on discovery.
- Grey box: the tester gets normal user accounts and some documentation. The most common choice for web apps, because it tests what logged-in users could do.
- White box: the tester gets source code, architecture diagrams and admin access. The deepest coverage per hour.
Tests are also named by target: external network, internal network, web application, API, mobile app, cloud configuration and wireless.
The VAPT process
Professional methods such as PTES (Penetration Testing Execution Standard), the OWASP Web Security Testing Guide (WSTG) and NIST SP 800-115 describe similar phases:
- Pre-engagement: agree scope, rules of engagement, test accounts and written authorisation.
- Reconnaissance: gather information (see Information Gathering).
- Scanning and enumeration: find hosts, ports, services, pages and parameters (see Network Scanning with Nmap).
- Vulnerability analysis: run scanners and manual checks, then verify every result.
- Exploitation: safely demonstrate verified vulnerabilities with the smallest proof that shows impact.
- Post-exploitation: only if allowed, show what access leads to (for example reading one test record), without harming data.
- Reporting: explain findings, risk, evidence and fixes for both managers and developers.
- Remediation and retest: the client fixes issues; the tester confirms the fixes work.
Scoping and rules of engagement
Scope says what may be tested. Rules of engagement (RoE) say how. Writing them down protects the client, protects the tester and prevents surprises. A simple RoE for a lab exercise might look like this:
engagement: Juice Shop lab assessment
client_contact: Ananya Rao (lab owner), +91 98xxxxxx10
tester: Farhan Sheikh
authorised_by: Ananya Rao
scope:
in: ["http://192.168.56.101:3000", "http://192.168.56.101:4280"]
out: ["192.168.56.1", "any internet address"]
window: "2026-11-02 10:00 to 2026-11-06 18:00 IST"
allowed: [recon, port scanning, web application testing, test accounts provided]
not_allowed: [denial of service, social engineering, deleting data, testing other users' real data]
max_request_rate: 10 per second
on_critical_finding: stop and call the client contact within 1 hour
data_handling: evidence stored encrypted, deleted 30 days after the final reportGood scoping questions to ask any client:
- Which systems, URLs, IP ranges and environments (production or staging) are in scope, and which are excluded?
- Who hosts them? A cloud provider or hosting company may have its own testing rules.
- Which test accounts and roles will you provide?
- Are there times when testing must pause, such as month-end billing?
- What should happen if we find a critical issue or evidence of a past breach?
Turning scanner output into findings
Automated scanners such as Greenbone/OpenVAS, Nessus and Nuclei check thousands of known issues quickly. In your lab you might run:
nuclei -u http://192.168.56.101:4280 -severity medium,high,criticalScanners produce false positives (reports of problems that do not exist) and miss many logic flaws (false negatives). A tester's job is to remove duplicates, verify each result by hand, and record evidence. This script does the first two steps for a scanner export:
raw = [
{"id": "outdated-apache", "host": "192.168.56.101", "port": 4280, "severity": "medium"},
{"id": "missing-csp", "host": "192.168.56.101", "port": 3000, "severity": "low"},
{"id": "outdated-apache", "host": "192.168.56.101", "port": 4280, "severity": "medium"},
{"id": "sql-error-message", "host": "192.168.56.101", "port": 4280, "severity": "high"},
{"id": "missing-csp", "host": "192.168.56.101", "port": 4280, "severity": "low"},
]
verified_false_positive = {("outdated-apache", 4280)} # vendor backported the fix
unique = {}
for f in raw:
unique[(f["id"], f["port"])] = f
order = {"critical": 0, "high": 1, "medium": 2, "low": 3}
for (fid, port), f in sorted(unique.items(), key=lambda kv: order[kv[1]["severity"]]):
status = "FALSE POSITIVE" if (fid, port) in verified_false_positive else "to verify manually"
print(f'{f["severity"]:<7} {fid:<18} port {port:<5} {status}')
print(f"{len(raw)} raw results -> {len(unique)} unique")high sql-error-message port 4280 to verify manually medium outdated-apache port 4280 FALSE POSITIVE low missing-csp port 3000 to verify manually low missing-csp port 4280 to verify manually 5 raw results -> 4 unique
"Backported fix" is a common reason for false positives: Linux distributions often patch security bugs without changing the main version number, so a scanner that only reads the version string is wrong.
Tracking test coverage
The OWASP WSTG groups web tests into areas such as information gathering, configuration, identity, authentication, authorisation, session management, input validation and error handling. Tracking which areas you have covered prevents gaps:
plan = {
"Information gathering": "done",
"Configuration and deployment": "done",
"Authentication": "finding",
"Authorisation": "in progress",
"Session management": "not started",
"Input validation": "finding",
"Error handling": "not started",
}
for area, status in plan.items():
mark = {"done": "[x]", "finding": "[!]", "in progress": "[~]"}.get(status, "[ ]")
print(mark, area)
done = sum(s in ("done", "finding") for s in plan.values())
print(f"Coverage: {done}/{len(plan)} areas complete")[x] Information gathering [x] Configuration and deployment [!] Authentication [~] Authorisation [ ] Session management [!] Input validation [ ] Error handling Coverage: 4/7 areas complete
Common mistakes
- Delivering raw scanner output as a "VAPT report". Without verification and context, it is mostly noise.
- Starting before the paperwork is signed. No authorisation, no testing.
- Exploiting more than needed. Prove impact with the smallest safe step, such as reading one record, never dumping a whole database.
- Forgetting the retest. A finding is closed only when the fix has been verified.
Key points
- A vulnerability assessment lists known weaknesses broadly; a penetration test proves what an attacker could achieve.
- Black, grey and white box tests differ in how much the tester is told.
- VAPT phases run from pre-engagement through recon, scanning, analysis, exploitation, reporting and retest.
- Scope says what may be tested; rules of engagement say how, when and what to do if something goes wrong.
- Scanner results must be deduplicated and verified; false positives and false negatives are both common.
Exercise
Add two more raw results to the scanner triage script: a critical result default-admin-password on port 3000, and a duplicate of sql-error-message on port 4280. Run it and check that the critical finding is printed first and the count of unique findings is correct.
Show solution
raw = [
{"id": "missing-csp", "port": 3000, "severity": "low"},
{"id": "sql-error-message", "port": 4280, "severity": "high"},
{"id": "default-admin-password", "port": 3000, "severity": "critical"},
{"id": "sql-error-message", "port": 4280, "severity": "high"},
]
order = {"critical": 0, "high": 1, "medium": 2, "low": 3}
unique = {(f["id"], f["port"]): f for f in raw}
for (fid, port), f in sorted(unique.items(), key=lambda kv: order[kv[1]["severity"]]):
print(f["severity"], fid, port)
print(len(raw), "raw ->", len(unique), "unique")The critical default password appears first, and four raw results become three unique findings because the duplicate shares the same ID and port.
Quick Quiz
1. What is the main difference between a vulnerability assessment and a penetration test?
VA is broad and mostly automated; PT is deeper, manual and goal-driven.
2. In a grey box web application test, what does the tester usually receive?
Grey box sits between black box (nothing) and white box (everything).
3. What should a rules of engagement document say?
RoE describe how the test is carried out safely within the agreed scope.
4. Why might a scanner report an outdated Apache version that is not actually vulnerable?
Version-only checks miss backported patches, which is a classic false positive.
Learn Cyber Security with a mentor
Free lessons get you started. Our Ethical Hacking & Cyber Security training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
