August 17, 2026 · appsec.training
How to Identify Software Vulnerabilities

A production vulnerability rarely begins as an obvious security failure. More often, it starts as a normal engineering decision: a new API endpoint, an authorization check copied from another service, a third-party package added to meet a deadline, or an error handler that exposes too much information. Learning how to identify software vulnerabilities means examining those decisions in context before an attacker does.
For an Application Security Engineer, vulnerability identification is not a single testing activity. It is a repeatable process that combines architecture analysis, threat modeling, secure code review, automated testing, and manual validation. Each method detects different classes of weakness. Strong AppSec practice comes from knowing where each method fits and how to interpret its results.
Start With the Application's Attack Surface
Before reviewing code or running a scanner, establish what the application exposes and what it protects. An attack surface inventory should identify internet-facing endpoints, authenticated user workflows, administrative functions, APIs, data stores, background jobs, cloud services, third-party integrations, and privileged trust boundaries.
This step prevents a common failure mode: finding low-impact issues while missing the workflows that can expose customer data or enable account takeover. A reflected cross-site scripting finding in a low-traffic marketing page may deserve remediation, but a broken authorization control in a billing API deserves immediate attention.
Document the application's assets and entry points in terms engineering teams recognize. Identify where untrusted input enters the system, where sensitive data is stored or processed, and where the application makes security decisions. Those points become the foundation for focused testing.
Use Threat Modeling to Find Likely Failure Paths
Threat modeling turns a broad attack surface into testable hypotheses. Map the major data flows, then ask what can happen when an attacker controls an input, assumes another user's identity, bypasses an expected workflow, or reaches a service across a trust boundary.
For example, a file-upload feature is not just an endpoint that accepts a file. It may involve client-side validation, object storage, malware scanning, image processing, metadata extraction, download authorization, and content delivery. Each transition creates a potential weakness: unrestricted file types, path manipulation, public object access, malicious file processing, or insecure direct object references.
Useful threat modeling questions include: What asset is being protected? Who should be authorized to perform this action? What input can an attacker control? What assumptions does this component make about another component? What happens if those assumptions are false?
Threat modeling is most effective early, when architecture and requirements are still flexible. It should also be revisited when teams add integrations, change authentication flows, or introduce new data-processing paths.
Identify Vulnerabilities Through Secure Code Review
Secure code review is where many high-value flaws become visible. Automated tools can identify suspicious patterns, but a reviewer can determine whether a security control actually matches the business rule.
Focus first on code that handles authentication, authorization, input processing, deserialization, cryptography, file operations, database access, redirects, and external service calls. Reviewers should trace data from its source to its sensitive sink. If a request parameter reaches a database query, shell command, template engine, file path, or HTTP client, determine whether the application applies the right validation and context-specific encoding.
Authorization deserves special attention because it frequently requires manual reasoning. Do not assume a route-level authentication check protects every object within that route. Verify that the application checks whether the current user is permitted to access, modify, or delete the specific resource requested. This is how reviewers identify insecure direct object references and other broken object-level authorization flaws.
Look for security controls that are inconsistent across similar workflows. An application may correctly enforce role checks in its web interface while exposing the same action through an undocumented API endpoint. It may validate uploaded filenames but fail to validate the actual file content. These gaps often emerge when features evolve independently.
Use SAST as a Triage and Coverage Tool
Static application security testing, or SAST, analyzes source code, bytecode, or build artifacts without executing the application. It is effective at finding patterns associated with injection, insecure cryptographic use, hardcoded secrets, path traversal, unsafe deserialization, and weak input handling.
SAST is valuable because it can run early in the development lifecycle and review large codebases consistently. However, it does not understand every business rule or runtime condition. A SAST finding is evidence to investigate, not an automatic vulnerability declaration.
To get useful results, tune rules to the languages, frameworks, and coding patterns used by the organization. Establish a triage process that distinguishes true positives, false positives, accepted risks, and findings requiring deeper manual review. Suppressions should be documented and time-bounded where possible. Otherwise, teams accumulate silent exceptions that hide future risk.
The trade-off is clear: aggressive rules increase coverage but may overwhelm developers with noise. Conservative rules improve signal but can miss relevant patterns. The right configuration depends on code maturity, team capacity, and the organization's risk tolerance.
Test Running Applications With DAST and API Testing
Dynamic application security testing, or DAST, examines a running application from the outside. It can identify issues such as missing security headers, reflected input, weak session handling, exposed administrative interfaces, misconfigurations, and some injection vulnerabilities.
DAST is particularly useful for validating whether deployed controls behave as expected. A secure code review may show that an authorization check exists, while API testing reveals that a different HTTP method bypasses it. Similarly, a scanner may detect a debug endpoint or verbose error response that was not apparent in the source repository.
Modern applications require more than browser-focused scanning. Test APIs directly, including REST, GraphQL, and service-to-service interfaces. Exercise authenticated roles, modify object identifiers, change request methods, replay requests, alter content types, and test field-level permissions. For business-logic flaws, manual testing is usually essential because scanners cannot infer whether a user should be allowed to apply a discount repeatedly, approve their own transaction, or access another tenant's report.
Use production-like test environments whenever possible. Scanning a development environment with placeholder authentication and incomplete integrations produces a misleading picture of risk.
Validate Findings Before Escalating Them
A finding becomes actionable when it is reproducible, understood, and tied to realistic impact. Validation confirms that the issue is reachable, identifies affected components, and establishes the conditions required for exploitation.
Capture clear evidence: the affected endpoint or code location, the vulnerable behavior, reproduction steps, the expected security control, and the observed result. Avoid reporting a generic "possible SQL injection" when you can show whether attacker-controlled input reaches a query and whether it can alter query behavior.
Prioritization should consider more than a severity score. Evaluate exploitability, exposure, required privileges, affected data, blast radius, compensating controls, and business context. A medium-severity issue in an unauthenticated endpoint handling sensitive records may warrant faster action than a higher-scored issue that requires rare administrative access in an isolated internal system.
Make Vulnerability Identification Part of Engineering Work
The goal is not to create a long list of findings. The goal is to establish feedback loops that help teams prevent recurring classes of defects. Build security review into design discussions, run SAST in pull requests, test deployed applications continuously, and use remediation trends to improve coding standards and threat models.
Developers need findings they can act on. Security teams need enough technical depth to explain root cause and verify fixes. That combination is central to the Application Security Engineer role: translating application behavior into security risk, then working with engineering teams to reduce it.
Practical competence develops through repeated analysis of real code, real requests, and real failure modes. Structured, lab-based training such as appsec.training can help engineers practice secure code review, threat modeling, SAST, DAST, and vulnerability validation as connected operational skills. The strongest vulnerability identification process is the one your team can perform consistently before a release turns an overlooked assumption into an incident.