PT0-002Chapter 87 of 104Objective 5.2

Source Code Review for Vulnerabilities

This chapter covers source code review for vulnerabilities, a critical skill for the CompTIA PenTest+ PT0-002 exam. Source code review is a white-box testing technique where the tester has full access to the application's source code to identify security flaws. While not every penetration test includes source code review, it is a powerful method for finding vulnerabilities that are difficult to detect through black-box testing alone. Approximately 10-15% of exam questions relate to this domain, focusing on common vulnerability categories, manual review techniques, and the use of static analysis tools.

25 min read
Intermediate
Updated May 31, 2026

Source Code Review as a Blueprint Audit

Imagine you are an architect auditing the blueprints for a new skyscraper before construction begins. The blueprints contain every detail: structural beams, electrical wiring, plumbing routes, and safety systems. As an auditor, you don't just look at the final building—you examine the plans to find design flaws that could lead to collapse, fire hazards, or code violations. For example, you might spot a load-bearing wall that is undersized for the floor above, or an emergency exit route that passes through a storage closet. These flaws are much cheaper to fix on paper than after concrete is poured. Similarly, source code review for vulnerabilities is a static analysis of the application's blueprint—the source code—before it is compiled and deployed. You examine the code line by line, looking for security weaknesses like SQL injection, buffer overflows, or insecure cryptographic implementations. Just as an architect uses checklists for common structural issues, a penetration tester uses automated tools and manual techniques to identify patterns that historically lead to vulnerabilities. The goal is the same: catch the problem early, when it is still just text on a page, before it becomes a costly exploit in production.

How It Actually Works

What is Source Code Review for Vulnerabilities?

Source code review (also called static analysis or white-box testing) is the process of examining an application's source code to identify security vulnerabilities. Unlike dynamic analysis (penetration testing against a running application), source code review does not require the application to be executed. The reviewer reads the code and identifies potential security issues by looking for dangerous functions, insecure coding patterns, and logic flaws.

Why it Exists

Many vulnerabilities are introduced during development due to programmer error, lack of security awareness, or time pressure. Common vulnerabilities like SQL injection, cross-site scripting (XSS), buffer overflows, and insecure direct object references (IDOR) often have telltale signs in the source code that can be spotted before the application is deployed. By reviewing source code, organizations can catch these issues early, reducing the cost and risk of exploitation.

How Source Code Review Works Internally

Source code review can be performed manually or with automated tools. The process generally follows these steps:

Understand the application architecture: Before diving into code, the reviewer should understand the application's components, data flow, and trust boundaries. This includes identifying entry points (e.g., HTTP request handlers), authentication/authorization mechanisms, database interactions, and external API calls.

Identify high-risk areas: Focus on code that handles user input, authentication, session management, database queries, file operations, and cryptographic functions. These areas are most likely to contain vulnerabilities.

Trace data flows: Follow user input from entry points through processing to output. Look for places where input is used unsafely, such as in SQL queries (SQL injection), HTML output (XSS), or system commands (command injection).

Check for common vulnerability patterns: Use a checklist or knowledge base of common vulnerabilities (e.g., OWASP Top 10) to systematically examine code.

Use automated tools: Static Application Security Testing (SAST) tools can scan the entire codebase quickly and flag potential issues. However, these tools often produce false positives and may miss logic flaws, so manual review is still essential.

Key Components, Values, and Defaults

CWE (Common Weakness Enumeration): A standardized list of software weakness types. The exam may reference CWE IDs such as CWE-89 (SQL Injection), CWE-79 (XSS), CWE-120 (Buffer Overflow), and CWE-22 (Path Traversal).

OWASP Top 10: The most critical web application security risks. While not all apply to source code review, categories like injection, broken authentication, and sensitive data exposure are directly relevant.

CVSS (Common Vulnerability Scoring System): Used to score the severity of vulnerabilities. The exam may test your ability to interpret CVSS scores, but source code review itself is about finding vulnerabilities, not scoring them.

SAST Tools: Examples include Fortify, Checkmarx, SonarQube, and Veracode. These tools parse source code and apply rules to detect potential vulnerabilities. They often have configurable rule sets and can integrate into CI/CD pipelines.

Code Analysis Metrics: Tools may report metrics like "lines of code analyzed," "number of findings," "false positive rate," and "time to scan."

Configuration and Verification Commands

While source code review does not involve running commands on a live system, you may use tools from the command line. For example:

# Using SonarScanner to analyze a project
sonar-scanner \
  -Dsonar.projectKey=my_project \
  -Dsonar.sources=. \
  -Dsonar.host.url=http://localhost:9000 \
  -Dsonar.login=myauthenticationtoken
# Using Flawfinder (open-source C/C++ analyzer)
flawfinder --html my_source.c > results.html

For manual review, common commands to search code for dangerous functions:

# Search for dangerous PHP functions
grep -rn "eval(" .
grep -rn "system(" .
grep -rn "exec(" .

# Search for SQL queries in Python
grep -rn "execute(" .

How It Interacts with Related Technologies

Dynamic Analysis (DAST): Source code review complements dynamic analysis. DAST tests the running application, while source code review catches issues that may not be easily exploitable or reachable through the UI.

Software Composition Analysis (SCA): SCA identifies vulnerabilities in third-party libraries used by the application. Source code review should include checking for known vulnerable components (e.g., using OWASP Dependency-Check).

DevSecOps: Source code review tools are often integrated into CI/CD pipelines to automatically scan code on every commit. This enables "shift left" security, catching vulnerabilities early in the development lifecycle.

Manual Penetration Testing: Findings from source code review can guide manual testing. For example, if a code review reveals an insecure deserialization pattern, the tester can craft specific payloads to exploit it.

Common Vulnerability Patterns in Source Code

SQL Injection - Look for dynamic SQL queries constructed by concatenating user input. - Example vulnerable code (PHP):

$query = "SELECT * FROM users WHERE username = '" . $_GET['username'] . "'";
$result = mysqli_query($conn, $query);

Secure version uses parameterized queries or prepared statements.

Cross-Site Scripting (XSS) - Look for user input reflected in HTML output without proper encoding. - Example vulnerable code (Java):

out.println("<p>Welcome, " + request.getParameter("name") + "</p>");

Secure version uses context-aware encoding (e.g., OWASP Java Encoder).

Buffer Overflow - Common in C/C++ code using unsafe functions like strcpy(), sprintf(), gets(). - Example:

char buffer[10];
strcpy(buffer, user_input); // no bounds checking

Secure version uses strncpy() or snprintf() with size limits.

Insecure Direct Object Reference (IDOR) - Look for endpoints that use user-supplied identifiers without authorization checks. - Example (REST API):

@app.route('/api/user/<int:user_id>')
def get_user(user_id):
    # No check if current user is allowed to access this user_id
    user = db.query("SELECT * FROM users WHERE id = ?", user_id)
    return jsonify(user)

Secure version verifies that the authenticated user has permission to access the requested resource.

Path Traversal - Look for file operations that use user input to construct file paths without sanitization. - Example:

$file = $_GET['file'];
include("/var/www/html/" . $file); // allows ../../etc/passwd

Secure version uses a whitelist of allowed files or validates the path.

Insecure Cryptographic Storage - Look for hardcoded encryption keys, use of weak algorithms (e.g., DES, MD5), or improper initialization vectors. - Example:

String key = "1234567890123456"; // hardcoded 16-byte key for AES

Secure version uses a key management system and strong algorithms like AES-256 with GCM mode.

Manual Review Techniques

Trace user input: Start from input sources (HTTP request parameters, cookies, file uploads) and follow the data through the code. At each step, check if the input is validated, sanitized, or escaped before being used in a sensitive operation.

Review authentication and authorization logic: Look for flaws in how users are authenticated (e.g., weak password policies, session fixation) and how access controls are enforced (e.g., role-based access control implementation).

Check error handling: Ensure that error messages do not leak sensitive information (e.g., stack traces, database schema).

Review configuration files: Look for hardcoded credentials, insecure default settings, or debug modes enabled in production.

Examine third-party libraries: Use SCA tools to identify known vulnerabilities in dependencies.

Automated Tools: Strengths and Weaknesses

Strengths: Speed, coverage, consistency. Tools can scan thousands of lines of code in minutes and flag potential issues based on rules.

Weaknesses: False positives (flagging safe code as vulnerable), false negatives (missing real vulnerabilities, especially logic flaws), inability to understand business context, and limited ability to detect complex vulnerabilities like business logic errors.

Exam Tip: The PT0-002 exam expects you to know that automated source code analysis tools are useful but not sufficient; manual review is still required to validate findings and find subtle issues.

Common Pitfalls in Source Code Review

Over-reliance on tools: Candidates often assume that if a tool doesn't find anything, the code is secure. In reality, tools miss many vulnerabilities.

Ignoring third-party code: Vulnerabilities in libraries are often overlooked. Always check dependencies.

Not understanding the language: Each language has its own security quirks. For example, PHP has many dangerous functions like eval(), system(), preg_replace() with /e modifier (deprecated). JavaScript has eval() and innerHTML for XSS.

Focusing only on input validation: While important, output encoding, authentication, and authorization are equally critical.

Summary

Source code review is a vital component of a comprehensive security assessment. It requires a combination of automated tools and manual expertise. The PT0-002 exam will test your ability to identify common vulnerability patterns in code snippets and understand the role of source code review in the penetration testing lifecycle.

Walk-Through

1

Identify Application Entry Points

Begin by mapping out all ways user input enters the application. This includes HTTP request parameters, headers, cookies, file uploads, and API endpoints. For a web application, review the routing configuration and controller methods. For desktop or mobile apps, look at network communication, file reads, and user interface inputs. Document each entry point and the data it expects. This step is crucial because any input that is not properly validated is a potential attack vector. Use tools like grep to search for functions that handle input, such as `$_GET`, `$_POST`, `request.getParameter()`, or `raw_input()` in Python.

2

Trace Data Flow Through the Code

For each entry point, follow the data as it moves through the application. Create a mental or written data flow diagram. Identify where the data is stored (variables, databases), transformed (encoding, decoding), and used in sensitive operations (queries, output, file operations). At each step, check if proper validation, sanitization, or escaping is applied. For example, if user input is used in a SQL query, verify that parameterized queries are used. If it is echoed back to the browser, check for output encoding. This step often reveals vulnerabilities that span multiple functions or modules.

3

Examine Authentication and Authorization

Review the code that handles user authentication (login, session management) and authorization (access control). Look for hardcoded credentials, weak password hashing algorithms (e.g., MD5, SHA1 without salt), session fixation vulnerabilities (e.g., session ID accepted from URL parameter), and insecure direct object references (IDOR). For authorization, check that every sensitive operation verifies the user's permissions. Common flaws include missing access control checks on API endpoints or allowing privilege escalation through parameter manipulation. Use grep to search for authentication checks like `if (user.role == 'admin')` and ensure they are not bypassed.

4

Identify Dangerous Functions and Patterns

Search the codebase for functions known to be dangerous if used improperly. For example, in PHP: `eval()`, `system()`, `exec()`, `preg_replace()` with `/e` modifier, `include()` with dynamic paths. In C/C++: `strcpy()`, `sprintf()`, `gets()`, `scanf()`. In JavaScript: `eval()`, `innerHTML`, `document.write()`. In SQL: raw query execution functions like `mysqli_query()` with concatenated strings. Flag every occurrence and manually review the context to determine if the function is used safely. For each flagged function, check if input is sanitized and if the function's parameters are properly constrained.

5

Review Error Handling and Logging

Examine how the application handles errors. Look for stack traces, detailed error messages, or debug information that might be displayed to the user. Such information can leak internal paths, database schema, or other sensitive data. Also, review logging practices to ensure that sensitive data (passwords, credit card numbers) is not logged. Check for custom error handlers that might suppress errors but also hide attack attempts. In PHP, look for `ini_set('display_errors', 0);` but also check if error reporting is properly configured. In Java, check for exception handling that prints the stack trace to the response.

6

Check Configuration and Deployment Files

Review configuration files for hardcoded secrets (API keys, database passwords, encryption keys), debug modes enabled in production (e.g., `DEBUG=True` in Django), and insecure default settings (e.g., directory listing enabled in web server config). Also check for leftover test code, commented-out code, or backup files that might expose sensitive information. In web applications, look for `.git` directories, `robots.txt` that reveals hidden paths, or `web.xml` that shows authentication bypasses. Use automated scanners to find common misconfigurations, but also manually inspect key files.

What This Looks Like on the Job

Enterprise Scenario 1: E-Commerce Platform Code Review

A large e-commerce company hired a penetration testing firm to review the source code of their custom-built shopping cart application before a major release. The application was written in Java and used Spring MVC with Hibernate for database access. The testing team performed a manual source code review focusing on the checkout and payment processing modules. They discovered an SQL injection vulnerability in the order lookup feature where the order ID was taken directly from the URL parameter and concatenated into a SQL query. The fix was to use parameterized queries. They also found that credit card numbers were logged in plaintext in the application logs, which violated PCI DSS. The team recommended encrypting log entries and masking sensitive data. The automated SAST tool (Fortify) had flagged the SQL injection but missed the logging issue because it was a configuration problem, not a code flaw. This highlights the need for manual review to complement automated tools.

Enterprise Scenario 2: Healthcare Application Static Analysis

A healthcare startup needed to ensure their patient portal was compliant with HIPAA. They used SonarQube to perform continuous static analysis on their Python Django codebase. The tool flagged several instances of hardcoded secret keys in settings files and insecure direct object references in API endpoints. However, the development team initially ignored many warnings as false positives. A manual review by a security consultant confirmed that the IDOR findings were real: any authenticated user could access another patient's medical records by changing the patient ID in the URL. The consultant also identified a business logic flaw where user roles were not properly enforced in the admin panel, allowing a regular user to promote themselves to admin. This logic flaw was not detected by SonarQube because it did not have rules for business logic. The company implemented role-based access control and added additional manual review steps to their CI/CD pipeline.

Performance Considerations and Common Issues

In large codebases (millions of lines), automated tools can take hours to scan. To manage this, organizations often run incremental scans on changed files only, or schedule full scans overnight. False positives are a major challenge: tools may flag thousands of issues, but many are not exploitable. A common mistake is to dismiss all tool findings as false positives without manual verification. Conversely, some teams fix every finding without understanding the context, leading to wasted effort. The best practice is to triage findings based on risk, validate each one manually, and prioritize by exploitability and impact.

How PT0-002 Actually Tests This

What PT0-002 Tests on Source Code Review

The exam objectives under Domain 5 (Tools and Scripts) include Objective 5.2: "Given a scenario, analyze a script or code sample for vulnerabilities." This means you will be presented with code snippets (often in Python, PHP, Java, or C) and asked to identify the vulnerability present. Common vulnerabilities tested include SQL injection, XSS, buffer overflow, command injection, path traversal, insecure deserialization, and hardcoded credentials. You may also be asked about the appropriate remediation (e.g., parameterized queries, input validation, output encoding).

Common Wrong Answers and Why Candidates Choose Them

1.

Choosing "Cross-Site Scripting" when the code shows SQL injection: Candidates often confuse XSS and SQL injection because both involve user input. The key is to look at how the input is used: if it's concatenated into a SQL query, it's SQL injection; if it's echoed to the browser without encoding, it's XSS.

2.

Selecting "Buffer Overflow" for a Python script: Buffer overflows are primarily a C/C++ issue due to direct memory manipulation. Python manages memory automatically, so buffer overflows are extremely rare. Candidates may see a large input and assume buffer overflow, but the correct answer is likely another vulnerability like command injection.

3.

Identifying "Insecure Direct Object Reference" when the code has proper authorization checks: IDOR occurs when an object identifier is exposed and the application fails to verify the user's permission to access that object. If the code checks user permissions (e.g., if (user.id == object.owner_id)), it is not an IDOR. Candidates may incorrectly assume any use of an ID is an IDOR.

4.

Confusing "Static Analysis" with "Dynamic Analysis": The exam may ask about the type of analysis. Static analysis reviews source code without execution; dynamic analysis tests a running application. Candidates may mix them up, especially when the question describes a tool that scans code.

Specific Numbers, Values, and Terms

CWE IDs: Be familiar with CWE-89 (SQL Injection), CWE-79 (XSS), CWE-120 (Buffer Overflow), CWE-22 (Path Traversal), CWE-798 (Hardcoded Credentials).

OWASP Top 10: Know the categories, especially A1: Injection, A3: Sensitive Data Exposure, A7: Cross-Site Scripting.

SAST vs DAST: Static Application Security Testing (SAST) vs Dynamic Application Security Testing (DAST). SAST is white-box, DAST is black-box.

Common dangerous functions: eval(), system(), exec(), strcpy(), sprintf(), gets(), include(), require(), mysqli_query().

Remediation terms: "Parameterized query," "prepared statement," "output encoding," "input validation," "allow list."

Edge Cases and Exceptions the Exam Loves to Test

Second-order SQL injection: Where user input is stored in the database and later used unsafely. The exam may show code that appears safe because it uses parameterized queries on initial insert, but later retrieval uses concatenation.

Blind SQL injection: Not usually directly tested in code review, but the code pattern (e.g., using sleep() based on input) might be shown.

Reflected vs Stored XSS: The exam may ask you to identify the type based on code. Reflected XSS echoes input immediately; stored XSS saves it to a database and later displays it.

Business logic flaws: These are hard to detect with tools and often appear in manual review scenarios. The exam may present a scenario where the code logic allows privilege escalation (e.g., missing role check).

How to Eliminate Wrong Answers

Identify the vulnerability category first: Determine if the issue is injection, XSS, buffer overflow, etc. Then match the answer choices.

Look at the function used: If you see strcpy(), it's likely buffer overflow. If you see eval(), it's code injection. If you see mysqli_query() with concatenation, it's SQL injection.

Check the context: If the code is in a web application, focus on web vulnerabilities. If it's a C program, focus on memory corruption.

Remember the language: Python code is unlikely to have buffer overflow; Java code is unlikely to have format string vulnerabilities.

Use the process of elimination: Cross off answers that don't match the code pattern. For example, if no SQL is present, eliminate SQL injection. If no HTML output, eliminate XSS.

Key Takeaways

Source code review is a static analysis technique that examines source code without executing it.

Common vulnerabilities found in source code review include SQL injection, XSS, buffer overflow, command injection, path traversal, and hardcoded credentials.

Automated SAST tools are fast but produce false positives and miss logic flaws; manual review is essential for validation.

The exam tests ability to identify vulnerabilities in code snippets (Python, PHP, Java, C) and suggest remediation.

Key dangerous functions include eval(), system(), strcpy(), sprintf(), and mysqli_query() with concatenation.

Parameterized queries/prepared statements are the primary defense against SQL injection.

Output encoding (e.g., HTML entity encoding) prevents XSS.

Buffer overflow vulnerabilities are most common in C/C++ due to unsafe functions like strcpy(), gets(), and sprintf().

Source code review should be integrated into the development lifecycle (DevSecOps) for continuous security.

CWE IDs (e.g., CWE-89, CWE-79) are used to classify vulnerabilities and may appear on the exam.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

Manual Source Code Review

Requires human expertise and time; expensive for large codebases.

Can detect complex logic flaws, business logic errors, and context-dependent vulnerabilities.

Produces fewer false positives but may miss some issues due to reviewer fatigue.

Scalability limited by team size; typically focuses on high-risk areas.

Best for deep analysis of critical components or after automated scanning.

Automated Static Analysis (SAST)

Fast and scalable; can scan entire codebase in minutes to hours.

Limited to predefined rules; cannot detect logic flaws or business logic issues.

High false positive rate; may flag safe code as vulnerable.

Consistent and repeatable; ideal for integration into CI/CD pipelines.

Best for initial broad scanning to identify common vulnerability patterns.

Watch Out for These

Mistake

Source code review is only needed for custom-developed applications, not for open-source or third-party software.

Correct

Source code review is valuable for any application where you have access to the source code, including open-source software. Many organizations perform code reviews on open-source libraries to ensure they don't introduce vulnerabilities. Even if you trust the developer, code review can catch unintentional flaws.

Mistake

Automated static analysis tools are sufficient for finding all vulnerabilities in source code.

Correct

Automated tools are effective at finding common patterns but miss many vulnerabilities, especially logic flaws, business logic errors, and context-dependent issues. Manual review is essential to validate findings and discover subtle vulnerabilities that tools cannot detect.

Mistake

If a code snippet uses parameterized queries, it is completely immune to SQL injection.

Correct

Parameterized queries prevent SQL injection in most cases, but there are exceptions. For example, if the parameterized query is used for dynamic table or column names (which cannot be parameterized), concatenation may still be needed. Additionally, stored procedures that use dynamic SQL inside them can still be vulnerable.

Mistake

Buffer overflow vulnerabilities only exist in C and C++ code.

Correct

While buffer overflows are most common in C/C++ due to manual memory management, they can occur in any language that allows direct memory manipulation or unsafe constructs. For example, unsafe use of `unsafe` code in C# or `ctypes` in Python can lead to buffer overflows. However, for the exam, focus on C/C++.

Mistake

Source code review is a one-time activity performed before deployment.

Correct

Source code review should be an ongoing process integrated into the development lifecycle (DevSecOps). Code changes are continuously reviewed, either manually or through automated scanning in CI/CD pipelines. This 'shift left' approach catches vulnerabilities early and reduces remediation costs.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

What is the difference between static analysis and dynamic analysis?

Static analysis (source code review) examines the code without executing it, typically using automated tools or manual review. Dynamic analysis tests the running application, often through penetration testing. Static analysis can find vulnerabilities early in development, while dynamic analysis finds issues that are exploitable in a live environment. For the PT0-002 exam, static analysis is white-box testing, and dynamic analysis is black-box or gray-box testing.

How do I identify SQL injection in source code?

Look for SQL queries that are constructed by concatenating user input directly into the query string. For example, in PHP: `$query = "SELECT * FROM users WHERE username = '" . $_GET['username'] . "'";`. The presence of functions like `mysqli_query()` or `query()` with concatenated strings is a red flag. Secure code uses parameterized queries or prepared statements, such as `$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");`.

What tools are commonly used for source code review?

Common SAST tools include Fortify, Checkmarx, SonarQube, Veracode, and Flawfinder (open-source). These tools scan source code for known vulnerability patterns. Manual review often uses grep or IDE search features to find dangerous functions. For the exam, you should know that tools are helpful but not perfect.

Can source code review find all vulnerabilities?

No. Source code review cannot find vulnerabilities that arise from runtime configuration, network-level attacks, or interactions between components that are not visible in the code. It also cannot detect vulnerabilities in third-party services or APIs. However, it is excellent for finding coding flaws and logic errors.

What is a false positive in SAST?

A false positive is when a tool flags a piece of code as vulnerable when it is actually safe. For example, a tool might flag a parameterized query as SQL injection because it sees the word 'query' and user input, but the parameterization prevents injection. False positives waste time and can lead to alert fatigue.

How should I prioritize findings from a source code review?

Prioritize based on the risk: exploitability, impact, and likelihood. Use CVSS scores if available. Critical vulnerabilities like SQL injection in authentication or remote code execution should be fixed immediately. Lower-risk issues like information disclosure in error messages can be scheduled. Also consider the affected component's exposure to untrusted users.

What is the difference between stored and reflected XSS in code?

Reflected XSS occurs when user input is immediately echoed back in the response without proper encoding, e.g., `echo $_GET['name'];`. Stored XSS occurs when user input is saved to a database and later displayed to other users, e.g., saving a comment and later retrieving it. In code review, look for input being stored (e.g., INSERT query) and later output without encoding.

Terms Worth Knowing

Ready to put this to the test?

You've just covered Source Code Review for Vulnerabilities — now see how well it sticks with free PT0-002 practice questions. Full explanations included, no account needed.

Done with this chapter?