Back to glossary

Application Security Testing (AST)

Application security testing (AST) finds software vulnerabilities with automated SAST, DAST, IAST, and SCA tools, each reading a different part of the code.

Also known as AppSec Testing

Application security testing (AST) is the set of automated techniques, including SAST, DAST, IAST, and SCA, that analyze or exercise an application to find security vulnerabilities before release. Static tools read source code without running it, dynamic tools attack a running build, and software composition analysis matches dependencies against known-vulnerability databases.

What is application security testing?

#

Application security testing is the practice of finding security vulnerabilities in software with automated tools, grouped into four families by what they read and whether they run the code. Each family answers a different question, and the questions do not overlap.

Static application security testing (SAST) reads source, bytecode, or binaries without executing them. Dynamic application security testing (DAST) attacks the running application over HTTP. Interactive application security testing (IAST) instruments the running application and watches input reach dangerous calls from inside. Software composition analysis (SCA) inventories the dependencies and checks each against vulnerability databases.

NIST codified the split in SP 800-218, the Secure Software Development Framework, published February 2022. It names two separate practices: PW.7, "Review and/or Analyze Human-Readable Code," and PW.8, "Test Executable Code to Identify Vulnerabilities and Verify Compliance with Security Requirements." SAST and code review satisfy the first; DAST, IAST, and fuzzing satisfy the second.

We think the four families share a design assumption worth stating plainly: each was built to find accidental bugs in code the team can see. That assumption held when an application was mostly first-party code. It no longer describes where the code comes from, and the gap it leaves is the subject of this page.

Static · code not run
Dynamic · code runs
Code you wrote

SAST

Reads your source, bytecode, or binaries. Traces untrusted input to dangerous calls. No execution.

DAST · IAST · pentest

Attacks the running app from outside (DAST) or instruments it from inside (IAST). Needs a deployed build.

Code you imported

SCA · SBOM

Reads the dependency manifest and lockfile, matches names and versions to a known-vulnerability database.

The blind spot

Dependency code executing at install and import time. No classic AST technique watches here — but install scripts and malicious packages run here first.

The matrix above sorts the techniques by two axes: whether the tool runs the code, and whether the code is yours or imported. Three quadrants are well covered. SAST and secret scanning read first-party source statically. DAST, IAST, and penetration testing exercise the running app. SCA and SBOM generation read the dependency manifest statically. The fourth quadrant, dependency code executing at install and import time, has no mainstream AST technique in it, and that is exactly where install scripts and malicious packages run first.

What are application security testing tools?

#

Application security testing tools fall into four families, plus manual penetration testing, and each answers one question about one kind of code. The table compares what each one reads, whether it runs the code, and what it cannot see.

TechniqueReadsRuns code?Best atBlind to
SASTFirst-party source, bytecode, binariesNoInjection and unsafe API use in code you wroteRuntime-only flaws; dependency code it never scans
DASTThe running app, over HTTPYesAuth, config, and injection visible from outsideSource-level bugs on unreached paths; needs a deployed build
IASTThe running app, instrumentedYesConfirming exploitability with few false positivesOnly paths the test traffic exercises; limited language support
SCADependency manifest and lockfileNoKnown CVEs in declared dependenciesMalicious packages with no CVE; code pulled outside the lockfile
Penetration testingThe whole system, by handYesChained and business-logic flaws a scanner missesCost and cadence; a point-in-time snapshot

The scale on the dynamic side is real. As of May 2025, Google reports that OSS-Fuzz "has helped identify and fix over 13,000 vulnerabilities and 50,000 bugs across 1,000 projects" through continuous fuzzing alone. Our verdict: run SAST and code review on every pull request for code you write, DAST or IAST against staging for anything internet-facing, and SCA plus package behavior analysis for code you import. The common mistake is treating CVE-based SCA as the supply chain answer, which leaves the install stage unguarded.

One application, three AST tools, and the flaw none of them report

#

To show where the families agree and where they share a hole, we wrote a four-route Flask application with one deliberate SQL injection bug, then ran a static analyzer, a dependency scanner, and a dynamic scanner against it. Every tool and command below is open source and reproducible. The application builds its query by string interpolation:

Python
@app.get("/user")
def user():
    name = request.args.get("name", "")
    query = f"SELECT email FROM users WHERE name = '{name}'"
    rows = db.execute(query).fetchall()
    return {"emails": [r[0] for r in rows]}

SAST reads the source and flags the pattern. Bandit reports one medium-severity issue, B608, mapped to CWE-89 (SQL injection), pointing at the f-string on line 12. It never runs the app:

Plain text
$ bandit app.py
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection
   vector through string-based query construction.
   Severity: Medium   CWE: CWE-89
   Location: ./app.py:12:14

SCA ignores our code and reads the dependency list. pip-audit resolves the pinned versions and matches them against the advisory database, returning known CVEs in the framework we imported, not in anything we wrote:

Plain text
$ pip-audit -r requirements.txt
Found 8 known vulnerabilities in 2 packages
Name   Version  ID               Fix Versions
flask  3.1.2    CVE-2026-27205   3.1.3
jinja2 3.1.4    CVE-2025-27516   3.1.6
jinja2 3.1.4    CVE-2024-56201   3.1.5
jinja2 3.1.4    CVE-2024-56326   3.1.5

DAST confirms the bug from outside, with no access to the source. sqlmap sends crafted query strings to the running server and reports the parameter as injectable by three separate techniques:

Plain text
$ sqlmap -u "http://127.0.0.1:5055/user?name=alice" --batch
GET parameter 'name' is vulnerable.
Type: boolean-based blind
Type: time-based blind
Type: UNION query
back-end DBMS: SQLite

All three findings are real, and all three should be fixed. Now the part that matters. Our requirements file installed one local dependency, fastjsonlog, whose packaging script ran during pip install, before Bandit, pip-audit, or sqlmap ever looked. We gave it a benign payload that only reads token-shaped environment variable names and writes them to a file, where a real stealer would exfiltrate them:

Python
# setup.py, executed by pip during installation
import os, time
hits = [k for k in os.environ
        if any(s in k for s in ("TOKEN","KEY","SECRET"))]
with open("/tmp/fastjsonlog-ran.txt","w") as f:
    f.write(f"{time.ctime()} setup.py ran; saw {hits}\n")

The marker file appeared on every install, including a clean run where we passed dummy credentials: "setup.py ran; saw ['GITHUB_TOKEN', 'AWS_SECRET_ACCESS_KEY', 'NPM_TOKEN']". Running pip install with --only-binary did not help, because pip still built the local source distribution and ran its script. None of the three AST tools reported it, and the reason is structural, not a configuration gap. The hostile code is not in the application source that SAST reads, it has no CVE for SCA to match, and it never answers an HTTP request for DAST to probe. It simply executed, which is the one thing none of these techniques watch for.

Why does application security testing miss supply chain attacks?

#

Application security testing misses supply chain attacks because its techniques evaluate artifacts for flaws, while a malicious dependency's defining move is to run. The demo above is the pattern in miniature: the payload executed at install time, which is where almost every recent registry attack executes, before any test in the pipeline had run.

Malicious package code most often runs through install scripts, the preinstall and postinstall steps a package manager executes the moment a package lands on disk. CVE-based scanning cannot catch it, because a CVE describes an accidental flaw in a known version and a malicious package is neither. CVE scanning alone misses most supply chain attacks; malware does not get a CVE.

The structural fix is to stop running dependency code by default. pnpm blocked lifecycle scripts by default in version 10, released January 2025. npm followed with npm v12, released July 8, 2026, which turns dependency install scripts off unless the project allows them. Default-on lifecycle scripts were a design mistake, and both package managers have now corrected it.

The risk ranking confirms where testing falls short. The OWASP Top 10:2025 placed Software Supply Chain Failures at A03, built from just 11 CVEs, the smallest data footprint of any category, yet exactly 50% of survey respondents ranked it their number one concern. OWASP is blunt about why its data lags: "By the time we can reliably test a weakness at scale, years may have passed." The risk practitioners fear most is the one their existing tests rarely detect.

The volume of untested code is the other half. On the smallest real web app we could write, a four-line Express 5 server, Socket measured one direct dependency pulling in 64 transitive ones, 65 packages holding 30,371 lines of JavaScript owned by 34 distinct npm accounts, as of November 6, 2026. The Shai-Hulud worm showed what that surface costs: its second wave, beginning November 24, 2025, compromised more than 500 packages and 700 versions, running its loader at install time on every machine that pulled them.

Covering the blind spot takes a control that sits where AST does not. A package firewall inspects each package request before the download reaches disk, analyzing what the package actually contains rather than what its metadata claims. For the CVE noise that SCA does produce, reachability analysis ranks findings by whether your code can reach the vulnerable function; Socket reports its reachability cuts up to 80% of alerts. Reachability, not severity score, should drive triage.

Socket Basics bundles the open-source scanners for the other quadrants, SAST, secret detection, and container scanning, into one pass, so the AST coverage and the supply chain coverage report in the same place. Provenance and signatures are necessary here but not sufficient: the Shai-Hulud and Miasma waves published through legitimate pipelines, some with valid provenance.

What application security testing still cannot prove

#

Edsger Dijkstra set the boundary of all testing in 1970: "Program testing can be used to show the presence of bugs, but never to show their absence." Every AST technique inherits that limit. A clean SAST run, a passing DAST scan, and an empty CVE report together prove only that the specific flaws those tools look for were not found this time.

The deeper problem is not false negatives within a technique but the quadrant none of them cover. Compromise now arrives as one new version from one hijacked maintainer account, and AST evaluates the artifact, not the trust in the person who published it. npm 12 pins script approvals to exact versions, which forces a human to look, but the reviewer asked to approve the next release sees the same install step whether the file behind it changed or became a credential stealer. Until registries and package managers surface what changed in a version and what it does when it runs, application security testing will keep scanning the code it can read and trusting the far larger body of code it cannot.