
Research
SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains
An emerging npm supply chain attack that infects repos, steals CI secrets, and targets developer AI toolchains for further compromise.
This is not an officially supported Google product.
tsec is a wrapper for the official TypeScript compiler tsc with additional checks on the codebase's compatibility with Trusted Types.
tsec supports most compilation flags as tsc does. For code pattern patterns that is potentially incompatible with Trusted Types, tsec emits compilation errors.
tsec perform a basket of security checks to find possible XSS issues in your code. In particular, the checks ban using dangerous DOM sink APIs with plain string values. Any violation of the checks can hinder Trusted Types adoption either directly or indirectly. To fix the violations, you should construct Trusted Types values to feed into these sinks. At the moment, tsec covers most of the Trusted Types sinks that are enforced by the browser. See here for the complete list of available checks. We will be adding the missing ones soon.
First add tsec as a dev dependency of your TypeScript project.
yarn add tsec --dev
Then choose the right configuration file to build the project with tsec and check its Trusted Types compatibility.
yarn tsec -p tsconfig.json
Add --noEmit flag to skip emitting JS code from compilation.
Using Trusted Types in TypeScript has
a limitation and
currently you must use workarounds to TS compiler to bypass its checks. We've
implemented various patterns you can use in order to satisfy both tsc and
tsec rules.
For example:
declare const trustedHTML: TrustedHTML;
// the next line will be allowed by both tsc and tsec
document.body.innerHTML = trustedHTML as unknown as string;
For example:
// such value can be created if application uses string as a fallback when
// Trusted Types are not enabled/supported
declare const trustedHTML: TrustedHTML | string;
// the next line will be allowed by both tsc and tsec
document.body.innerHTML = trustedHTML as string;
The first argument to the unwrapper function must be the Trusted Type that is required by the specific sink and must return value accepted by the sink (string). The unwrapper function can have additional arguments or even accept TS union of values for the first parameter.
For example:
declare const trustedHTML: TrustedHTML;
declare const unwrapHTML: (html: TrustedHTML, ...other: any[]) => string;
// the next line will be allowed by both tsc and tsec
document.body.innerHTML = unwrapHTML(trustedHTML);
Note: All of these variants must be at the assignment/call of the particular sink and not before. For example:
declare const trustedHTML: TrustedHTML;
// cast before the actual usage in sink
const castedTrustedHTML = trustedHTML as unknown as string;
// tsec is flow insensitive and treats `castedTrustedHTML` as a regular string
document.body.innerHTML = castedTrustedHTML; // tsec violation!
Tsec can be integrated as a plugin to your TypeScript project allowing you to see the violations directly in your IDE. For this to work you need to:
Use workspace version of TypeScript
Add the plugin via plugins compiler option in the tsconfig. If you are using tsec as a package then the path to the plugin might look like this:
{
"compilerOptions": {
"plugins": [
{
"name": "tsec"
}
]
}
}
Restart the editor to reload TS initialization features.
Make sure the LSP is using (requiring) the same workspace version of TS used by the IDE.
Language service plugin is experimental, if it doesn't work, you can create an issue or try to debug locally. If you are using VSCode you can do so by following these steps:
Turn on verbose tsserver logging in the settings.
Restart the IDE. You can use Developer: Reload Window command for this.
Use Developer: Open Logs Folder to open the log folder
Find tsserver.log inside the folder (you can use find command line
utility) and open the file(s). There should be an error somewhere in the
logs which should get you started.
You can configure tsec to exempt certain violations. Add an "exemptionConfig"
option in the configuration for the tsec language service plugin. The value of
that field is a string indicating the path to the exemption list, relative to
the path of tsconfig.json. See an exemption below.
{
"compilerOptions": {
"plugins": [
{
"name": "tsec",
"exemptionConfig": "./exemption_list.json"
}
]
}
}
Note that although this configuration appears to be for the language service plugin, it also works for the command line use of tsec.
The exemption list is a JSON file of which each entry is the name of a rule. The value of the entry is a list of files that you would like to exempt from that rule.
Here is an example. Suppose you have a file src/foo.ts in your project that
triggers the following error from tsec:
src/foo.ts:10:5 - error TS21228: Assigning directly to Element#innerHTML can result in XSS vulnerabilities.
10 element.innerHTML = someVariable;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can exempt it by creating an exemption_list.json file along side your
tsconfig.json with the following content:
{
"ban-element-innerhtml-assignments": ["src/foo.ts"]
}
The exemption list supports the glob syntax. For example, if you want to completely disable a check, you can write:
{
"ban-element-innerhtml-assignments": ["**/*.ts"]
}
Note that exemptions are granted at the file granularity. If you exempt a file from a rule, all violations in that file will be exempted.
You can exempt files from all rules by setting the exemption list for the
wildcard rule name "*". This can be useful when the compiler configuration of
your project include files for testing.
{
"*": ["**/test/*.ts", "**/*.test.ts", "**/*.spec.ts"]
}
We recommend developing using VS Code. We have
preconfigured the project such that debugging works out of the box. If you press
F5 (Debug: Start debugging) tsec will be freshly built and executed on the
project files (files included in tsconfig). Currently, we have tests only
internally at Google, but you can create a test.ts file with some violationg
code anywhere in the project to get started. You can then add breakpoints in any
tsec source file.
See CONTRIBUTING.md.
FAQs
Extended TypeScript compiler checking Trusted Types compatibility.
The npm package tsec receives a total of 17,534 weekly downloads. As such, tsec popularity was classified as popular.
We found that tsec demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
An emerging npm supply chain attack that infects repos, steals CI secrets, and targets developer AI toolchains for further compromise.

Company News
Socket is proud to join the OpenJS Foundation as a Silver Member, deepening our commitment to the long-term health and security of the JavaScript ecosystem.

Security News
npm now links to Socket's security analysis on every package page. Here's what you'll find when you click through.