Safeguard
Product•

SAST for JavaScript and TypeScript in Safeguard

Safeguard SAST traces untrusted input from source to sink in JavaScript and TypeScript and maps each finding to a CWE and OWASP category.

Safeguard Security Team
39 min read

Safeguard SAST is generally available, and JavaScript and TypeScript are among its first three languages. It reads your source without a build, follows untrusted input from where it enters your code (a request parameter, a command line argument, a file read) to where it can do harm (a SQL query, a shell command, a file path), and reports each finding with that source to sink trace, a CWE and OWASP mapping, a severity and a code location. You can run it in your pipeline or on a local runner so source never leaves your network, and you read the results in the project Findings tab.

This post explains what that means for a Node.js or TypeScript codebase, how to run your first scan step by step, how to read and triage a trace, and what the engine does not do yet.

Key takeaways

  • SAST is GA. Safeguard's docs say SAST and DAST are rolling out: the platform wiring and the unified findings model are in place, and detection depth expands over time. Plan a pilot, not a mandate.
  • JavaScript and TypeScript are phase 1 languages, alongside Python and Java. The docs do not list individual frameworks, so test the engine on your own stack before you rely on it.
  • Every finding carries a dataflow trace: the ordered hops from source to sink, so a developer sees why the line was flagged and not only where.
  • CWE and OWASP mapping comes with each finding, which lets you report against the CWE Top 25 and the OWASP Top 10:2025 without hand tagging.
  • Where it runs: in your pipeline, or on the local runner (GA) so source stays inside your perimeter. The Safeguard CLI (GA) has a safeguard appsec sast command.
  • Where you read results: the project Findings tab with the Scanner filter set to SAST, and the SAST sub tab of the Application Security panel. There is no CLI command for listing SAST findings yet.
  • SCA (GA) still owns your npm, Yarn and pnpm dependencies. SAST looks at the code your team writes. You want both.
  • Policies and gates (GA) can act on findings, but start in report only mode before you block merges on it.
  • Autonomous remediation (GA) ships switched off with every category set to Manual. Fixing a SAST finding is a code change your developers own.

Why JavaScript and TypeScript need static analysis of your own code

Most of the security tooling a JavaScript team adopts first is about dependencies. That makes sense: a typical Node service pulls in hundreds of packages, and software composition analysis tells you which of them carry known CVEs. Our post on SCA, reachability, EPSS and KEV covers that side.

But a clean dependency tree says nothing about the route handler your team wrote last sprint. If that handler builds a SQL string from req.query, passes a filename from req.body to fs.readFile, or hands a user supplied value to child_process.exec, the vulnerability is in first party code. No CVE will ever be published for it, because it is yours. Static application security testing exists to find that class of problem before it ships.

What the standards expect

Several primary sources make first party code analysis an expectation rather than a nice extra.

  • OWASP Top 10:2025. The 2025 edition, now the current release on owasp.org, lists Injection as A05:2025 and Software Supply Chain Failures as A03:2025. Injection is the category most SAST rules for web code map into. Supply chain failures are what SCA covers. The split is a useful reminder that one scanner does not cover both.
  • CWE Top 25 (2025). MITRE's 2025 list puts CWE-79 (cross site scripting) at number 1 and CWE-89 (SQL injection) at number 2. CWE-22 (path traversal), CWE-78 (OS command injection), CWE-94 (code injection), CWE-502 (deserialization of untrusted data) and CWE-918 (server side request forgery) all appear in the 25 as well. Every one of those is a source to sink weakness that can live in a JavaScript or TypeScript service.
  • NIST SP 800-218, the Secure Software Development Framework (SSDF). Published in February 2022, SSDF organises its practices into four groups. In the Produce Well-Secured Software group, PW.7 covers reviewing and analysing human readable code for vulnerabilities, and PW.7.1 explicitly allows code analysis by tools as well as review by people. PW.8 covers testing executable code. SAST is a direct way to meet and evidence PW.7.
  • CISA Secure by Design. CISA asks software makers to treat customer security as a core business requirement rather than a feature. Eliminating whole classes of defects, such as injection, is central to that guidance, and you cannot eliminate a class you do not measure.
  • OWASP ASVS 5.0.0. The Application Security Verification Standard is the requirement catalogue many teams use to define "secure enough" for a web application. Its input handling and output encoding requirements are exactly the controls a SAST finding tells you are missing.

None of these documents names a tool. They describe outcomes. SAST is a way to produce evidence that you looked for injection class defects in your own code, on every change, and fixed what you found.

Why JavaScript is a special case

JavaScript and TypeScript make injection both easy to write and easy to miss in review.

  • Everything is a string until it is not. Request parameters, headers, cookies and JSON bodies arrive as strings or loosely typed objects. A value that looks like a number in a test may be an array or an object in an attacker's request.
  • Many sinks look harmless. Template literals that build SQL, exec with an interpolated argument, res.send with HTML built by concatenation, fetch with a URL from a query string, a recursive merge over a parsed JSON body. Each reads like ordinary application code.
  • Dataflow crosses files. A value is read in a router, validated (or not) in a middleware, transformed in a service and used in a repository module. A reviewer reading one file sees no problem. That is the gap SAST closes: Safeguard's docs describe its SAST as tracing input across functions and files.
  • TypeScript types do not sanitise anything. Declaring const id: number = req.params.id as unknown as number tells the compiler a story. At runtime the value is still whatever the client sent. Types are erased when TypeScript compiles to JavaScript, so they cannot stop a hostile string from reaching a query. A static analyser has to treat a typed value from a request as untrusted until real validation or encoding happens.
  • Prototype pollution is a JavaScript native weakness. MITRE's CWE-1321 describes code that lets input set attributes on an object prototype, usually through __proto__, constructor or prototype keys. It is not in the 2025 Top 25, but it is the kind of flaw that only shows up when you follow a parsed body into a merge or assignment helper.

The OWASP community page on source code analysis tools sums up the trade-off fairly. Static analysis scales well and can run on every build, but it is known for high numbers of false positives. A trace that shows exactly how input reaches a sink is the best defence against that weakness, because it lets a developer confirm or dismiss a finding in minutes.

How source to sink analysis works in a Node or TypeScript codebase

Before the product walkthrough, it helps to be precise about the model. Safeguard's docs describe SAST as analysing source code without running it, tracing untrusted input from a source to a dangerous sink across functions and files. The three terms matter.

Sources: where untrusted data enters

In a typical Node.js or TypeScript service, sources include:

  • HTTP inputs: req.query, req.params, req.body, req.headers, req.cookies, and the equivalents in other web frameworks.
  • Process inputs: process.argv and environment values that an operator or a deployment system can set.
  • File and stream reads: fs.readFile, uploaded files, message queue payloads.
  • Responses from other services you do not control.

The docs give request parameters, command line arguments and file reads as examples of sources.

Sinks: where data can do harm

Sinks are the calls where untrusted data changes behaviour:

  • Database calls that accept raw query text, such as a driver's query method given a template literal.
  • Process execution: child_process.exec, execSync, and anything that hands a string to a shell.
  • Dynamic code: eval, new Function, vm.runInNewContext.
  • File system paths: fs.readFile, fs.createReadStream, res.sendFile with a path built from input.
  • Outbound requests: fetch, http.request or a client library given a URL from input.
  • HTML output: string built HTML sent with res.send, innerHTML in browser code, and framework escape hatches that skip encoding.

The docs give a SQL query, command execution and a file path as examples of sinks. They do not publish a full rule list, so treat the longer list above as the classes of problem source to sink analysis is designed for, and confirm during your pilot which of them the engine flags in your code.

Sanitisers and the path between

A finding is only interesting if no adequate check sits between source and sink. Parameterised queries, execFile with an argument array instead of a shell string, path normalisation with a check against an allowed base directory, URL allow lists, and context aware output encoding all break the chain. A trace that ends at a sink after passing through one of those is a candidate for dismissal; a trace that passes through nothing is the one to fix first.

A small example

Here is a deliberately simple Express handler with a command injection weakness:

// routes/thumbnail.js
const { exec } = require('child_process');

router.get('/thumbnail', (req, res) => {
  const file = req.query.file;               // source: query string
  const out = buildOutputPath(file);         // helper in another module
  exec(`convert ${file} -resize 200x200 ${out}`, (err) => {   // sink: shell command
    if (err) return res.status(500).end();
    res.sendFile(out);
  });
});

The value from req.query.file flows, unchecked, into a shell command. A reviewer can see that in one file. Now move buildOutputPath into a utilities module, add a middleware that "validates" the query by checking it is non empty, and split the exec call into a service class in a third file. The weakness is the same, and much harder to see by reading. That cross file path is what a dataflow trace lays out for you.

The fix is a code change, not a version bump:

// routes/thumbnail.js
const { execFile } = require('child_process');
const path = require('path');

const UPLOADS = path.resolve('/srv/uploads');

router.get('/thumbnail', (req, res) => {
  const requested = path.resolve(UPLOADS, String(req.query.file || ''));
  if (!requested.startsWith(UPLOADS + path.sep)) return res.status(400).end();
  const out = buildOutputPath(requested);
  execFile('convert', [requested, '-resize', '200x200', out], (err) => {
    if (err) return res.status(500).end();
    res.sendFile(out);
  });
});

Two changes break the chain: the path is resolved and checked against an allowed base directory, and the process is started with execFile and an argument array, so no shell parses the input. A rescan should no longer report the trace.

What Safeguard SAST does today (GA)

Everything in this section comes from Safeguard's Application Security Testing docs page and the offering reference, which both describe SAST as rolling out.

AspectWhat the docs say
MaturityGA. The docs note SAST and DAST are rolling out; detection depth expands over time
InputsA connected repository or a local directory. No build required
Languages (phase 1)JavaScript/TypeScript, Python, Java, with more to follow
What a finding containsThe source to sink dataflow trace, CWE and OWASP mapping, severity and a code location
Where it runsYour pipeline, or a local runner so source never leaves your perimeter
Where results appearThe app's AppSec views and the project Findings tab, with severity, rule, CWE, location and the trace
CLIsafeguard appsec sast runs a scan of a source directory. There is no CLI command for listing findings yet
EngineFirst party, reporting into Safeguard's unified findings model

Two details are worth calling out.

No build required. Some static analysers need a compiled project or a complete type graph. Safeguard's docs say SAST takes a repository or a directory with no build required. For JavaScript and TypeScript teams this means you can point it at src without first getting a monorepo to compile in CI.

One findings model. SAST findings land in the same unified findings model as DAST and the other engines, browsed from a single Findings tab per project. That is what makes correlation possible later in this post.

Step by step: run your first SAST scan on a JavaScript or TypeScript repository

The flow below follows Safeguard's docs. Where the docs do not show a screen or field, we describe the outcome rather than invent one.

1. Confirm SAST is enabled for your tenant

Each first party engine in Safeguard is controlled by its own feature flag, and the docs list SAST's as scanner:sast. Flags are enforced on the server, so a disabled engine is genuinely off, not just hidden. Ask your Safeguard administrator or your Safeguard contact to confirm it is switched on for your tenant before you start. If it is off, the SAST sub tab in the Application Security panel will not appear.

2. Decide where the scan will run

You have two choices, and the decision is mostly about where your source is allowed to go.

  • In your pipeline. The scan runs as part of CI, using the Safeguard CLI. Results flow to your tenant's findings.
  • On a local or on premises runner. The docs describe this as the option that keeps source inside your perimeter. Our post on choosing between a repo connection, the CLI and the local runner walks through the trade-offs in detail.

If your security policy says source code must not leave your network, choose the runner. Safeguard also supports on premises and air gapped deployment (GA) if the whole platform needs to sit inside your boundary.

3. Add a Safeguard SAST integration

In the app, open the Integrations page and add an AppSec integration. Choose Safeguard SAST, then either select a repository you have already connected or point it at a source directory. This is the same pattern you use to add a repository or a registry. Once the integration exists, scans trigger through the standard integration, pipeline and CLI flow.

For a JavaScript or TypeScript monorepo, think about scope before you pick the directory:

  • Point at the source folders (src, packages/*/src, apps/*/src), not at dist, build or .next output. Bundled and minified output is hard for any analyser to trace and produces findings in code nobody edits.
  • Leave node_modules out. Third party code is SCA's job, and scanning it with SAST mostly creates noise in files your team does not own.
  • If test fixtures deliberately contain unsafe patterns, keep them out of the first scan so the pilot results reflect production code.

4. Or run it from the CLI

The docs show this command for a static analysis of a source directory:

# Static analysis of a source directory
safeguard appsec sast --dir ./src --tenant-id <tenant> --product-id <product>

The --dir flag sets the directory to analyse, and the tenant and product IDs place the results in the right part of your Safeguard estate. In a CI job, you would run this after checkout, using the same Safeguard CLI authentication you use for other scans. The Safeguard CLI is GA; the SAST engine it calls is generally available.

The docs are explicit that there is no CLI command for listing SAST findings yet. The CLI starts the scan; you read the results in the app.

5. Open the results in the Findings tab

Open the project in the app. On the project Info page, the Scanner Coverage section shows one card per scanner with a live finding count. Clicking the SAST card opens the Findings tab with the SAST scanner already selected.

You can also go straight to the Findings tab and use the Scanner dropdown at the top. "All scanners" is the default. Choosing SAST scopes the table, the summary stats and the underlying queries to SAST findings only.

Below the findings table, the Application Security panel has one sub tab per first party engine. The SAST sub tab appears there when the SAST feature flag is on for your tenant.

If the SAST view is empty, the docs explain that no scan has posted SAST findings for that project yet. Check that a scan ran against the right directory before you conclude the code is clean.

6. Read each finding's trace

Each SAST finding shows its severity, the rule, the CWE, the code location and the dataflow trace: the ordered hops from source to sink. The next section shows how to read one.

7. Triage

Decide for each finding whether it is a real, exploitable path, a real path with a mitigating control outside the code, or a false positive. Record the decision on the finding so the next scan does not reopen the argument. The triage section below has a short checklist.

8. Fix, rescan, and only then gate

Fix the code, push, and let the next scan confirm the trace is gone. Once your team trusts the results on a given repository, consider adding a policy that acts on new high severity SAST findings. Start in report only mode; see the gates section below.

Reading a SAST finding: the dataflow trace

The docs list what every SAST finding includes: severity, rule, CWE, location and the dataflow trace from source to sink. The layout below is illustrative. It uses the fields the docs name to show how to read a trace for the thumbnail example above; it is not a screenshot, and the exact wording in the app may differ.

Severity:  High
Rule:      OS command built from untrusted input
CWE:       CWE-78  (OS Command Injection)
OWASP:     A05:2025 Injection
Location:  src/services/imageService.ts:42

Dataflow trace (source to sink)
  1. src/routes/thumbnail.ts:12        req.query.file            [source: HTTP query]
  2. src/middleware/requireFile.ts:8   value checked non-empty    [not a sanitiser]
  3. src/routes/thumbnail.ts:15        imageService.resize(file)
  4. src/services/imageService.ts:40   cmd = `convert ${file} ...`
  5. src/services/imageService.ts:42   exec(cmd)                  [sink: shell command]

How to read it:

  1. Start at the top. Hop 1 tells you where the untrusted value enters. If that endpoint is internal only, behind authentication, or never exposed, note it, but do not dismiss the finding on that basis alone. Internal endpoints get exposed by accident.
  2. Look for a real sanitiser in the middle. Hop 2 is a check, but a non empty check does not make a filename safe for a shell. A trace that passes through something that looks like validation is a common source of false confidence.
  3. Read the sink last. Hop 5 is the call that does harm. The fix belongs as close to the sink as possible (use execFile with an argument array) and, where you can, at the source too (resolve and constrain the path).
  4. Use the CWE to pick the fix pattern. CWE-78 points at shell avoidance and argument arrays. CWE-89 points at parameterised queries. CWE-22 points at path resolution against an allowed base. CWE-79 points at context aware output encoding.

CWE and OWASP Top 10 mapping in practice

Each Safeguard SAST finding carries a CWE and OWASP mapping. The table below shows the source to sink weaknesses a JavaScript or TypeScript team meets most often, with their 2025 CWE Top 25 position and the OWASP Top 10:2025 category they usually fall under. The CWE and OWASP columns come from MITRE and OWASP; they are not a statement of which rules Safeguard ships today.

WeaknessCWE2025 CWE Top 25 rankUsual OWASP Top 10:2025 categoryTypical JS or TS source to sink
Cross site scriptingCWE-791A05 InjectionQuery or body value into HTML built by concatenation, or into innerHTML
SQL injectionCWE-892A05 InjectionRequest value into a template literal passed to a driver's raw query method
Path traversalCWE-226A01 Broken Access ControlRequest value into fs.readFile or res.sendFile without a base directory check
OS command injectionCWE-789A05 InjectionRequest value into exec or execSync
Code injectionCWE-9410A05 InjectionRequest value into eval, new Function or a template engine compile call
Deserialization of untrusted dataCWE-50215A08 Software or Data Integrity FailuresRequest body into a serializer that can rebuild functions or classes
Server side request forgeryCWE-91822A01 Broken Access ControlRequest value used as the URL for fetch or an HTTP client
Command injection (general)CWE-7723A05 InjectionInput into any command interpreter, not only a shell
Prototype pollutionCWE-1321Not in the 2025 Top 25Use the mapping on the findingParsed JSON into a recursive merge or deep set helper

Category placement for a given CWE can differ between OWASP editions, and some CWEs sit in more than one category. Use the mapping on each finding as the starting point and your own risk register as the final word.

What you can do with the mapping

  • Report against a framework your auditors already know. "Open SAST findings by OWASP Top 10:2025 category" is a sentence a security committee understands. So is "no open CWE Top 25 findings in services handling payment data".
  • Pick fix patterns by CWE, not by file. Group open findings by CWE and you often find the same mistake in ten places. One shared helper (a safe query builder, a path resolver, an encoding function) and a lint rule fix the class.
  • Write policy in terms of weakness classes. For example, block a merge only for new CWE-78 or CWE-89 findings on internet facing services, and report everything else. Our post on plain English policies and release gates covers how policies and gates (GA) work.

Triage: deciding which findings are real

Static analysis trades precision for coverage. OWASP's community page on source code analysis tools lists high false positive rates as a known weakness of the approach. Triage is where a SAST programme either earns developer trust or loses it.

Work through each finding with these questions:

  1. Is the source really untrusted? A value from req.query is. A value from a configuration file that only operators can change may not be, but write down why.
  2. Does the path really connect? Follow every hop in the trace. If a hop goes through a function you know returns a constant or a fixed allow list, the finding may be a false positive.
  3. Is there a real sanitiser? Parameterised queries, execFile with argument arrays, path resolution with a base directory check, URL allow lists and output encoding count. Length checks, non empty checks and TypeScript type annotations do not.
  4. Is the sink really dangerous in this context? A file read under a fixed, read only directory of public assets is less serious than a read under the application root.
  5. Is the code deployed? Dead code, scripts that never ship and test helpers are lower priority, but delete them if they are dead rather than suppressing findings forever.

Record the outcome on the finding. Safeguard findings carry a status (the docs list Open, Resolved and Mitigated), so the decision stays visible next to the trace. If you also run DAST, a finding that DAST later confirms at runtime should jump to the top of the queue (see correlation below).

A practical rule for the pilot: if more than a handful of findings on a repository turn out to be false positives of the same shape, send the examples to your Safeguard contact. The engine improves fastest with real false positives from real code.

Where it runs: pipeline, CI or local runner

OptionSource code location during the scanBest forWatch out for
Pipeline or CI job with the Safeguard CLI (GA)Your CI environmentScanning on every pull request or merge to mainScope the directory so the job is not slowed by build output or node_modules
Local or on premises runner (GA)Inside your network; source never leaves your perimeterRegulated code, strict data residency, private networksSomeone has to run and update the runner; see the runner post linked above
On premises or air gapped Safeguard deployment (GA)Entirely inside your boundaryOrganisations that cannot use a hosted platform at allPlan capacity and updates with your Safeguard contact

Whichever you choose, findings land in your tenant scoped findings view, readable in the app.

When to scan

  • On pull requests, so a developer sees a new trace while the change is still fresh. Keep the scan scoped to the services the change touches if your monorepo is large.
  • On merges to main, so the main branch has a complete, current SAST view.
  • On a schedule, so an untouched repository is rescanned as the engine's detection depth expands.

The Safeguard CLI has scan modes for its scanning in general (--scan-mode fast for quick pre merge feedback, deep for thorough pre release analysis, and progressive, which is generally available). The docs do not describe how those modes change SAST specifically, so do not assume a Fast SAST scan is the same depth as a Deep one; ask, and measure on your own code.

How SAST sits next to SCA and DAST

A JavaScript application has three kinds of risk, and Safeguard has a different engine for each.

QuestionEngineMaturityWhat it looks at
Do my npm, Yarn or pnpm dependencies carry known vulnerabilities?SCAGALockfiles, manifests and the full transitive tree
Does my own code let untrusted input reach a dangerous call?SASTGAYour JavaScript and TypeScript source
Does the running application misbehave when tested from outside?DASTGAA verified, in scope, running target

SCA findings have their own Vulnerabilities tab, which is why SCA does not appear in the Findings tab's Scanner dropdown. SAST and DAST findings sit in the Findings tab.

Correlation across engines

Because SAST, DAST and SCA findings share one model with correlation keys, Safeguard's docs describe linking a DAST confirmed runtime issue to the SAST source code sink that produced it, so the two are prioritised together. A confirmed, reachable, exploitable finding rises to the top. The docs also describe AutoTriage (GA) collapsing cross engine duplicates into one canonical finding.

In practice that means: run SAST on the repository, run DAST against the deployed application on a verified target, and when both point at the same weakness you have the strongest possible case for fixing it this sprint. Our post on DAST scope and verified targets explains how DAST decides what it is allowed to test.

Reachability analysis (GA) is Safeguard's way of ranking dependency vulnerabilities by whether your code actually calls the vulnerable path. The application security docs point to it for prioritising findings by whether they are actually reachable. For SAST, the trace itself is the reachability evidence: it shows the path from input to sink in your code.

Using SAST findings in policies and gates

Policies and gates are GA in Safeguard, and the application security docs point to Guardrails and Enforcement for using findings as policy gates in CI/CD. The engine feeding SAST findings into those gates is generally available. Put those two facts together and the sensible rollout looks like this:

  1. Weeks 1 to 2: observe. Scan a handful of representative repositories. Triage everything. Measure how many findings are real.
  2. Weeks 3 to 4: report. Add a policy that reports new high and critical SAST findings on pull requests without blocking. Developers see the trace on their own change.
  3. Then: block narrowly. Block only new findings in the classes you have confirmed are accurate on your code (for example CWE-78 and CWE-89 on internet facing services). Keep an exception process with an owner and an expiry date.
  4. Review monthly. As the engine's detection depth expands, new rules may fire on old code. Treat that as a backlog, not a broken build.

Never block on the whole historical backlog on day one. That trains developers to bypass the gate.

Fixing what SAST finds

SCA fixes are usually version bumps, which is why Safeguard's autonomous remediation (GA, ships off with every category set to Manual) can open upgrade pull requests for them. A SAST fix is different: it changes your code's logic, so a developer should own it and review it. Our post on autonomous remediation categories and strategies explains what runs automatically and what does not.

The Safeguard CLI's assistant can help with the edit itself. It can read code, propose a change and run your tests, and since CLI v11.10.0 it asks before any command that changes something. You still review the diff and merge it yourself.

Fix patterns that break the most common JavaScript and TypeScript traces:

CWEFix pattern
CWE-89Parameterised queries or a query builder; never interpolate request values into SQL text
CWE-78 and CWE-77execFile or spawn with an argument array and no shell; an allow list for any value that selects a program or flag
CWE-22path.resolve against a fixed base directory, then check the result still starts with that base
CWE-79Let the template engine or framework encode output; avoid raw HTML escape hatches; encode for the right context
CWE-94Remove eval and new Function on input entirely; there is rarely a safe version
CWE-918Allow list destination hosts; resolve and check the address before the request; block internal ranges
CWE-1321Reject __proto__, constructor and prototype keys in merge helpers; use objects without a prototype or a Map for user keyed data
CWE-502Parse untrusted input as plain JSON into validated shapes; avoid serializers that can rebuild code

After a fix, rerun the scan. A trace that disappears is your evidence that the change worked.

Decision table: requirement, what Safeguard does, what you still own

Requirement or goalWhat Safeguard does todayWhat you still own
Find injection class weaknesses in first party JS and TS code (OWASP A05:2025, CWE Top 25)SAST (GA) reports source to sink traces with CWE and OWASP mappingTriage, fixing code, deciding which classes to gate on
Analyse code for vulnerabilities as part of development (NIST SSDF PW.7, with PW.8 for testing)Scans in your pipeline or on a local runner; findings recorded per projectDefining when scans run, keeping evidence of fixes, the rest of your SSDF programme
Keep source code inside your networkLocal runner (GA); on premises and air gapped deployment (GA)Operating the runner and the environment
Know which dependencies are vulnerable (OWASP A03:2025)SCA (GA) with reachability, EPSS and KEVUpgrades your autonomous remediation settings do not cover
Confirm a code weakness is exploitable in the running appDAST (GA) on verified targets; correlation with SAST in the unified findings modelVerifying target ownership, choosing scope and safety mode
Stop new high risk code weaknesses from mergingPolicies and gates (GA) acting on findingsChoosing thresholds, running exceptions, deciding when to move from report to block
Show leadership and auditors progressFindings filterable by scanner, severity and CWE in the appThe narrative, the metrics you choose and the risk decisions

What Safeguard does not do

Honest limits, as of today:

  1. SAST is generally available, and detection depth is still expanding. The docs say so directly. Do not present Safeguard SAST to an auditor or a customer as a complete replacement for code review or penetration testing, and do not assume a clean result means clean code.
  2. The docs do not publish a JavaScript or TypeScript rule list or a framework support matrix. We have not seen a list of which CWEs, frameworks (React, Next.js, Express, NestJS and so on) or file types are covered. Test on your own stack and ask your Safeguard contact for specifics before you plan around a particular class.
  3. There is no CLI command for listing SAST findings yet. You start scans from the CLI or CI, and you read results in the app. If you need findings in another system today, plan for that gap.
  4. SAST does not scan your dependencies. Third party code in node_modules is SCA's job. Running SAST over it mostly produces findings you cannot fix.
  5. SAST does not run your application. It cannot see runtime configuration, deployed headers or how a reverse proxy rewrites requests. That is what DAST (GA, verified targets only) is for.
  6. It does not fix your code for you. Autonomous remediation ships off, and SAST fixes are logic changes that need a developer and a reviewer. The CLI assistant can help with the edit, with your approval.
  7. It does not decide your risk. Severity and CWE mapping are inputs. Whether an internal endpoint matters, whether a finding is acceptable for a release, and when to gate are your decisions.
  8. Business logic flaws are mostly out of reach for any source to sink analyser. A missing authorisation check on a route that never touches a dangerous sink will not show up as a trace. Code review, threat modelling and testing still matter.

Common mistakes

  • Scanning build output. Pointing SAST at dist or .next gives you findings in generated code and traces nobody can follow. Scan src.
  • Treating TypeScript types as validation. A number annotation on a request parameter is not a check. Validate at runtime with a schema, then trust the validated value.
  • Gating on day one. Blocking merges on any new scanner before you have measured its accuracy on your code burns developer goodwill. Observe, then report, then block narrowly.
  • Dismissing without a reason. A finding closed as "false positive" with no note will be argued about again next quarter. Write down why.
  • Fixing the line instead of the class. If ten traces end in the same raw query helper, fix the helper and remove the unsafe API, rather than patching ten call sites.
  • Assuming no findings means no flaws. An empty SAST view can mean no scan has posted findings yet, a wrong directory, or a class the engine does not cover. Check the scan ran.
  • Running SAST instead of SCA. They answer different questions. A JavaScript service needs both.
  • Ignoring internal endpoints. "Only reachable from the VPN" is a mitigating factor, not a fix. Internal services get exposed, and attackers who get inside use them.

FAQ

Is Safeguard SAST generally available for JavaScript and TypeScript?

Yes. Safeguard's docs describe SAST and DAST as rolling out, with the platform wiring and unified findings model in place and detection depth expanding over time. JavaScript and TypeScript are phase 1 languages alongside Python and Java.

Does Safeguard SAST need my project to build?

No. The docs say SAST takes a connected repository or a local directory with no build required. That is helpful for TypeScript monorepos that are slow or awkward to compile in CI.

What is a source to sink dataflow trace?

It is the ordered list of hops untrusted data takes from where it enters your code (a source such as a request parameter) to where it can cause harm (a sink such as a SQL query or shell command). Each Safeguard SAST finding includes one, so a developer can see why a line was flagged and which hop to change.

Does Safeguard map SAST findings to OWASP Top 10 and CWE?

Yes. Each SAST finding carries a CWE and OWASP mapping along with severity and a code location. You can use that mapping to report against the OWASP Top 10:2025 and the CWE Top 25.

Can I run Safeguard SAST without sending source code to the cloud?

Yes. The docs say SAST can run on a local runner so source never leaves your perimeter. Safeguard also supports on premises and air gapped deployment for organisations that need the whole platform inside their boundary.

How do I run a SAST scan from the command line?

The docs show safeguard appsec sast --dir ./src --tenant-id <tenant> --product-id <product>. The CLI starts the scan; there is no CLI command for listing findings yet, so you read results in the app's Findings tab.

Where do I see SAST findings in Safeguard?

Open the project, then the Findings tab, and set the Scanner dropdown to SAST. You can also click the SAST card in the Scanner Coverage section on the project Info page, or use the SAST sub tab in the Application Security panel below the findings table.

Does SAST replace SCA for npm packages?

No. SCA (GA) analyses your dependencies through lockfiles and manifests and matches them to known vulnerabilities. SAST analyses the code your team writes. They find different problems, and a JavaScript application needs both.

Will Safeguard automatically fix SAST findings?

Not on its own. Autonomous remediation ships switched off, with every category set to Manual, and SAST fixes are code logic changes that need a developer and a reviewer. The Safeguard CLI's assistant can help draft the edit and asks before any command that changes something.

Get started

To try SAST on a JavaScript or TypeScript repository, ask your Safeguard contact to enable SAST for your tenant, install the CLI from safeguard.sh/download, and follow the Application Security Testing page in the Safeguard docs. If you want the full picture of what is available across the platform, see what Safeguard does today.

A SAST trace shows you a weakness in code you own and can fix today. Much of a JavaScript application's exposure, though, sits in the npm packages underneath that code, where you depend on someone else's fix, and the section below covers how Safeguard closes that gap.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.

3. Gold Registry: start from components that are already fixed

Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingSafeguard policies and gates in CI
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

These demos show the Safeguard CLI and local runner, which are the same tools you use to run SAST. Neither demo shows a SAST scan; they show the surrounding workflow.

The first demo is a real CLI session. You install the CLI, run safeguard to open the interactive terminal and ask it to fix a lodash CVE in a repository. It reads the finding and advisory, asks before any command that changes something, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, prints a summary and pushes nothing, then shows /permissions, /model and /scan. That is an SCA fix, but the same assistant and approval model is how you would work through a SAST trace in your own code.

Click through it at your own pace, or open it full screen.

The second demo sets up the local runner on your own machine, approves it with its device code, and then scans from the terminal. The runner is the option Safeguard's docs describe for keeping source inside your perimeter, which is the setup most teams want for SAST on private code.

Click through it at your own pace, or open it full screen.

Quick check

Does a TypeScript type annotation on a request parameter stop SQL injection?

No. Types are erased when TypeScript compiles to JavaScript, so at runtime the value is whatever the client sent. Only real runtime validation, parameterised queries or encoding break a source to sink path.

Where do you read Safeguard SAST findings, and is there a CLI command to list them?

In the project Findings tab with the Scanner dropdown set to SAST, or the SAST sub tab of the Application Security panel. The CLI can start a scan with safeguard appsec sast, but there is no CLI command for listing findings yet.

Sources

Last reviewed: 25 October 2026. Product capabilities change; check docs.safeguard.sh for the current state.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.