Semgrep javascript, typescript rules¶
rules_lgpl_javascript_eval_rule-grpc-insecure-connection¶
Summary:
Deserialization of Untrusted Data
Severity: Critical
CWE: CWE-502
Description:
The application uses grpc.credentials.createInsecure() to establish an unencrypted
gRPC connection, transmitting all data in plaintext without TLS/SSL protection. This
allows network attackers to intercept and read sensitive data being transmitted between
the gRPC client and server, including authentication credentials, API keys, personal
information, and business data. Additionally, attackers can perform man-in-the-middle
attacks to modify gRPC messages in transit, potentially injecting malicious payloads or
altering application behavior. Insecure gRPC connections are particularly dangerous in
production environments and microservice architectures where services communicate over
untrusted networks.
Remediation:
Replace grpc.credentials.createInsecure() with grpc.credentials.createSsl() to
enable TLS encryption for all gRPC connections. For production environments, use
proper TLS certificates from a trusted Certificate Authority (CA) and configure
certificate validation to prevent man-in-the-middle attacks. You can create secure
credentials with grpc.credentials.createSsl(rootCerts, privateKey, certChain) where
rootCerts validates the server's identity. For development and testing environments,
use self-signed certificates but never deploy them to production. Consider implementing
mutual TLS (mTLS) authentication using grpc.credentials.createSsl() with both client
and server certificates for enhanced security in microservice architectures. Always
verify that gRPC connections use TLS 1.2 or higher and disable insecure cipher suites.
OWASP:
- A8:2017-Insecure Deserialization
- A08:2021-Software and Data Integrity Failures
rules_lgpl_javascript_eval_rule-node-deserialize¶
Summary:
Deserialization of Untrusted Data
Severity: Critical
CWE: CWE-502
Description:
The application uses the node-serialize library's unserialize() function to
deserialize data, which is vulnerable to remote code execution attacks. The
node-serialize package uses JavaScript's eval() internally during deserialization,
allowing attackers to inject malicious code through specially crafted serialized objects
containing Immediately Invoked Function Expressions (IIFEs). When untrusted data is
deserialized, attackers can execute arbitrary JavaScript code on the Node.js server,
leading to complete system compromise. This vulnerability is particularly severe because
it requires no special conditions - any deserialization of attacker-controlled data will
execute the embedded code.
Remediation:
Immediately remove the node-serialize package from your application as it is
inherently insecure and has no safe usage mode. Replace it with JSON.parse() for
deserializing JSON data, which is safe and cannot execute arbitrary code. If you need
to serialize complex JavaScript objects including functions or circular references,
consider using structured data formats like JSON with a predefined schema instead. For
session data or cached objects, use secure serialization libraries like serialize-javascript
(note: different from node-serialize) which properly escapes code, or better yet, store
only primitive data types and reconstruct complex objects after deserialization. Never
deserialize any data from untrusted sources without strict validation and type checking.
Implement integrity checking using HMAC signatures to detect tampering of serialized
data before deserialization.
OWASP:
- A8:2017-Insecure Deserialization
- A08:2021-Software and Data Integrity Failures
rules_lgpl_javascript_eval_rule-serializetojs-deserialize¶
Summary:
Deserialization of Untrusted Data
Severity: Critical
CWE: CWE-502
Description:
The application uses the serialize-to-js library's deserialize() function, which can
execute arbitrary code during deserialization. The serialize-to-js package serializes
JavaScript objects including functions and can reconstruct them during deserialization,
but this functionality allows attackers to inject malicious code through specially
crafted serialized data. When untrusted input is deserialized, embedded functions or
code expressions are executed in the Node.js server context, allowing remote code
execution. This is particularly dangerous because the library is designed to preserve
executable code across serialization boundaries, making it unsuitable for handling any
data from untrusted sources.
Remediation:
Never use serialize-to-js to deserialize data from untrusted sources. Replace it with
JSON.parse() for safe deserialization that cannot execute code. If you currently use
serialize-to-js to serialize functions or complex objects, redesign your architecture
to use plain data structures that can be safely serialized to JSON. For application
state that includes behavior, separate the data (serialized as JSON) from the code
(stored as static application logic). If you absolutely must serialize executable code
for trusted internal use only, ensure data integrity using cryptographic HMAC signatures
and never deserialize data that hasn't been verified. Consider that even with signatures,
if an attacker compromises your signing key they can execute arbitrary code. The safest
approach is to eliminate code serialization entirely from your application architecture.
OWASP:
- A8:2017-Insecure Deserialization
- A08:2021-Software and Data Integrity Failures
rules_lgpl_javascript_eval_rule-yaml-deserialize¶
Summary:
Deserialization of Untrusted Data
Severity: Critical
CWE: CWE-502
Description:
The application uses the js-yaml library's load() function to parse YAML data, which
can execute arbitrary JavaScript code during deserialization. By default, js-yaml's
load() method supports custom YAML tags that can instantiate JavaScript objects and
execute functions, allowing attackers to craft malicious YAML payloads that execute
arbitrary code on the Node.js server. When untrusted YAML data is parsed using load(),
attackers can achieve remote code execution by exploiting YAML's ability to represent
executable constructs. This is a critical vulnerability particularly dangerous when parsing
YAML configuration files, API requests, or any user-provided YAML content.
Remediation:
Replace all uses of yaml.load() with yaml.safeLoad() (js-yaml v3) or yaml.load(data, {schema: yaml.SAFE_SCHEMA})
(js-yaml v4+) when parsing any YAML data. The safeLoad() function or SAFE_SCHEMA
option restricts YAML parsing to basic data types and prevents execution of arbitrary
code through custom tags. Never use yaml.load() without the safe schema, even for
data you consider trusted, as it's easy for untrusted data to enter your parsing flow.
For configuration files, consider switching to JSON format which has no code execution
capabilities and can be safely parsed with JSON.parse(). If you must support advanced
YAML features, carefully audit what custom tags are necessary and create a minimal
custom schema that only allows those specific safe tags, never the full default schema
that enables code execution.
OWASP:
- A8:2017-Insecure Deserialization
- A08:2021-Software and Data Integrity Failures
javascript_eval_rule-eval-with-expression¶
Summary:
Improper neutralization of directives in dynamically evaluated code ('Eval Injection')
Severity: High
CWE: CWE-95
Description:
The application uses dangerous code execution functions including eval(), the
Function() constructor, or string-based setTimeout()/setInterval() calls with
user-controlled input. These JavaScript functions execute arbitrary code at runtime,
allowing attackers to inject malicious JavaScript that runs with the application's
privileges. In Node.js applications, this can lead to complete server compromise and
remote code execution. In browser applications, this creates Cross-Site Scripting (XSS)
vulnerabilities that allow attackers to steal credentials, perform unauthorized actions,
or compromise user sessions.
Remediation:
Remove all uses of eval(), Function() constructor, and string-based timer functions,
replacing them with safer alternatives. For dynamic property access, use bracket notation
(e.g., obj[userInput]) combined with allowlisting to validate property names against a
predefined set of safe values. For parsing JSON data, use JSON.parse() instead of
eval(). For setTimeout() and setInterval(), always pass function references instead
of strings. Consider implementing Content Security Policy (CSP) headers with
script-src 'self' to prevent inline script execution and provide defense-in-depth
protection. If dynamic code execution is absolutely necessary, isolate it in a sandboxed
environment with restricted capabilities and thoroughly validate all inputs against a
strict allowlist. For more information, see
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval!
OWASP:
- A1:2017-Injection
- A03:2021-Injection
javascript-rule-xss-angular¶
Summary:
Use of bypassSecurityTrust* method in Angular ('Cross-site Scripting')
Severity: Medium
CWE: CWE-79
Description:
The application uses Angular's bypassSecurityTrust*() family of methods which
explicitly disables Angular's built-in Trusted Types and XSS protection mechanisms.
These methods include bypassSecurityTrustHtml(), bypassSecurityTrustScript(),
bypassSecurityTrustStyle(), bypassSecurityTrustUrl(), and
bypassSecurityTrustResourceUrl(). When user-controlled data flows through these
methods, it bypasses Angular's DomSanitizer and can lead to Cross-Site Scripting
(XSS) vulnerabilities. XSS attacks allow attackers to execute arbitrary JavaScript
in the victim's browser, potentially stealing session tokens, performing unauthorized
actions, or defacing the application.
Remediation:
Consider removing the use of bypassSecurityTrust*() methods entirely and rely
on Angular's automatic sanitization which applies context-aware escaping to template
bindings. If dynamic HTML rendering is absolutely necessary, sanitize user input
using DOMPurify before passing it to Angular's [innerHTML] binding, or better yet,
refactor the code to use Angular's component composition and safe template syntax.
For cases where you must render trusted HTML from a known-safe source (like static
CMS content), ensure the data source itself is secured and consider implementing
Content Security Policy (CSP) headers with strict-dynamic to limit the impact of
potential XSS. Always validate that data passed to bypass methods originates from
controlled, trusted sources and never directly from user input or URL parameters.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
javascript-rule-xss-react¶
Summary:
Improper neutralization of input during web page generation ('Cross-site Scripting')
Severity: Medium
CWE: CWE-79
Description:
The application uses React's dangerouslySetInnerHTML prop which bypasses React's
built-in XSS protection and DOM sanitization. By default, React automatically escapes
all values in JSX expressions before rendering them, preventing script injection.
However, dangerouslySetInnerHTML explicitly disables this protection and renders
raw HTML markup directly into the DOM. If user-controlled data flows into the
__html property of dangerouslySetInnerHTML, attackers can inject arbitrary
JavaScript that executes in the victim's browser context, leading to session
hijacking, credential theft, or unauthorized actions. This vulnerability affects
both DOM-based XSS (where untrusted data comes from client-side sources like URL
parameters) and stored/reflected XSS (where malicious content is persisted or
echoed from the server).
Remediation:
Consider refactoring the component to avoid dangerouslySetInnerHTML entirely by
using React's standard JSX syntax which automatically escapes content. If you must
render HTML from a trusted source (like a markdown parser or rich text editor),
sanitize it first using DOMPurify with a strict configuration that strips event
handlers and script tags: DOMPurify.sanitize(html, { ALLOWED_TAGS: ['p', 'b', 'i',
'em', 'strong'] }). For markdown content, consider using react-markdown which
renders markdown safely without innerHTML. Additionally, implement Content Security
Policy (CSP) headers with script-src 'self' to provide defense-in-depth against
XSS even if sanitization is bypassed. Never pass user input, URL parameters, or
data from external APIs directly to dangerouslySetInnerHTML without rigorous
server-side validation and sanitization.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
javascript-rule-xss-svelte¶
Summary:
Use of {@html * } in Svelte ('Cross-site Scripting')
Severity: Medium
CWE: CWE-79
Description:
The application uses Svelte's {@html ...} directive which renders raw HTML content
directly into the DOM without any sanitization or encoding. By default, Svelte
automatically escapes values in standard bindings like {variable} to prevent XSS
attacks. However, the {@html} directive explicitly bypasses this protection and
treats the content as trusted HTML markup. If user-controlled data flows into an
{@html} expression, attackers can inject malicious scripts that execute in the
victim's browser, potentially stealing authentication tokens, performing unauthorized
actions, or exfiltrating sensitive data. This is particularly dangerous in Svelte
applications because the framework's reactive nature can make it easy to accidentally
bind user input to {@html} expressions.
Remediation:
Consider using Svelte's standard text binding syntax {variable} instead of
{@html}, which automatically escapes HTML entities and prevents script injection.
If you must render rich HTML content from a trusted source (such as markdown
converted to HTML), sanitize it first using DOMPurify: {@html DOMPurify.sanitize
(content)} with a restrictive configuration that removes event handlers and script
tags. For markdown rendering, consider using a Svelte markdown component that safely
converts markdown to DOM nodes without innerHTML. Additionally, implement Content
Security Policy (CSP) headers to provide defense-in-depth protection. Never use
{@html} with data from URL parameters, form inputs, localStorage, or any external
API without rigorous server-side validation and client-side sanitization.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
javascript-rule-xss-vuejs¶
Summary:
Usage of v-html in Vue js ('Cross-site Scripting')
Severity: Medium
CWE: CWE-79
Description:
The application uses Vue's v-html directive which renders raw HTML content directly
into the DOM without sanitization, or has disabled the ESLint rule vue/no-v-html
which warns about this dangerous practice. Vue's standard interpolation syntax
{{ variable }} automatically escapes HTML entities to prevent XSS, but v-html
explicitly bypasses this protection. When user-controlled data flows through v-html,
attackers can inject malicious JavaScript that executes in the victim's browser
context, potentially stealing session cookies, accessing local storage, or performing
unauthorized API calls. Disabling the vue/no-v-html ESLint rule further increases
risk by removing static analysis warnings that alert developers to potential XSS
vulnerabilities during development.
Remediation:
Consider using Vue's standard mustache syntax {{ variable }} instead of v-html,
which automatically escapes HTML and prevents script injection. If rendering rich
HTML is absolutely necessary (such as user-generated content from a WYSIWYG editor),
sanitize it first using DOMPurify with strict settings: v-html="$sanitize(content)"
where $sanitize is a global method wrapping DOMPurify. Re-enable the ESLint rule
vue/no-v-html in your configuration to catch unsafe usage during code review.
For markdown content, use a Vue markdown component that safely renders to DOM nodes.
Implement Content Security Policy (CSP) headers with script-src 'self' to limit
XSS impact. Never use v-html with URL parameters, route params, Vuex state
populated from user input, or data from external APIs without server-side validation
and robust client-side sanitization.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
javascript_buf_rule-detect-new-buffer¶
Summary:
Allocation of resources without limits or throttling
Severity: Medium
CWE: CWE-770
Description:
The application is using the new Buffer() constructor which has been deprecated
since Node.js 8. By passing in a non-literal value to this constructor, an
adversary could allocate large amounts of memory leading to denial of service.
Additionally, older versions of Node.js would return uninitialized memory when
using new Buffer(size), which could leak sensitive information such as
passwords, tokens, or encryption keys that previously occupied that memory region.
The new Buffer() constructor is also ambiguous because it behaves differently
depending on the argument type, making it difficult to determine what data a
Buffer contains when passed a non-literal value.
Remediation:
Consider migrating to Buffer.alloc() for creating zero-filled buffers or
Buffer.from() for creating buffers from existing data. Use Buffer.alloc(size)
when you need a buffer of a specific size filled with zeros, which is safe and
prevents information leakage. Use Buffer.from(array) or Buffer.from(string)
when converting existing data into a Buffer. For applications that need to
support older Node.js versions, consider using the safe-buffer package which
provides a polyfill for the safe Buffer methods. Note that Buffer.allocUnsafe()
should be avoided unless you have specific performance requirements and
immediately overwrite all buffer contents, as it returns uninitialized memory.
Detailed migration guidance is available at
https://nodejs.org/en/docs/guides/buffer-constructor-deprecation
OWASP:
- A9:2017-Using Components with Known Vulnerabilities
- A06:2021-Vulnerable and Outdated Components
javascript_dos_rule-non-literal-regexp¶
Summary:
Regular expression with non-literal value
Severity: Medium
CWE: CWE-185
Description:
The RegExp() constructor or new RegExp() is being called with a non-literal
value, or string methods like match() and search() are being invoked with
non-literal patterns. When adversaries can supply malicious regular expressions
containing catastrophic backtracking patterns, they can cause Regular Expression
Denial of Service (ReDoS) attacks that make the application unresponsive. In
Node.js applications, this blocks the event loop and prevents the entire
application from serving other users' requests, effectively taking down the
service.
Remediation:
Recommended to always use hardcoded literal regular expressions (e.g.,
/pattern/flags) instead of accepting user-supplied regex patterns. If dynamic
pattern matching is absolutely required, consider migrating to the node-re2
package (npm install re2), which implements Google's RE2 engine that does not
support backtracking and provides linear-time guarantees. When using RE2, create
instances with new RE2(pattern) instead of new RegExp(pattern). Note that
RE2 does not support all JavaScript regex features like lookaheads and
backreferences, so test compatibility carefully. For search/match use cases,
consider using simple string operations like indexOf(), includes(), or
startsWith() when pattern matching complexity is not required. Can also
implement strict validation on user input to reject patterns containing
dangerous constructs, though this is complex and error-prone compared to using
RE2.
OWASP:
- A1:2017-Injection
- A03:2021-Injection
javascript_pathtraversal_rule-non-literal-fs-filename¶
Summary:
Improper limitation of a pathname to a restricted directory ('Path Traversal')
Severity: Medium
CWE: CWE-22
Description:
Non-literal file paths are used with Node.js fs module functions like
readFile(), writeFile(), readdir(), or similar operations. If these paths
are constructed from user input, attackers can use path traversal sequences like
../ to escape intended directories and access arbitrary files on the system.
This can lead to unauthorized file disclosure, modification, or deletion.
Remediation:
Consider using path.join() to construct file paths with a fixed base
directory, then validate that path.normalize(fullPath) still starts with the
base directory using fullPath.startsWith(basePath). Recommended to avoid
using user input directly as filenames; instead, use randomly generated
identifiers like crypto.randomUUID() and map them to user-supplied names in
a database. Always resolve and normalize paths before file operations.
OWASP:
- A5:2017-Broken Access Control
- A01:2021-Broken Access Control
javascript_random_rule-pseudo-random-bytes¶
Summary:
Use of cryptographically weak pseudo-random number generator (PRNG)
Severity: Medium
CWE: CWE-338
Description:
The deprecated crypto.pseudoRandomBytes() function is being used, which generates
cryptographically weak random data. This function uses a non-cryptographic PRNG
that can be predictable and is unsuitable for security-sensitive operations like
generating tokens, session IDs, nonces, or cryptographic keys. Predictable random
values can lead to session hijacking, token forgery, or cryptographic failures.
Remediation:
Consider replacing crypto.pseudoRandomBytes() with crypto.randomBytes(),
which provides cryptographically strong random data suitable for security
operations. Recommended to use crypto.randomBytes(size) for generating
tokens, session identifiers, nonces, or any cryptographic keys. The
randomBytes() function uses the system's cryptographic PRNG and is the
standard for all security-sensitive random number generation in Node.js.
OWASP:
- A3:2017-Sensitive Data Exposure
- A02:2021-Cryptographic Failures
javascript_xss_rule-mustache-escape¶
Summary:
Improper neutralization of input during web page generation (XSS)
Severity: Medium
CWE: CWE-79
Description:
The application disables Mustache's HTML escaping by either overriding the
mustache.escape function to return unescaped text, or using the triple-mustache
syntax {{{variable}}} or ampersand syntax {{&variable}} which render raw HTML
without escaping. Mustache's default double-brace syntax {{variable}} automatically
escapes HTML entities like <, >, and & to prevent Cross-Site Scripting (XSS).
By overriding the escape function to simply return text; or using unescaped
interpolation syntax, the application removes this critical security protection.
When user-controlled data flows through these unescaped contexts, attackers can
inject malicious scripts that execute in the victim's browser, potentially stealing
session tokens, accessing sensitive data, or performing unauthorized actions.
Remediation:
Consider removing the mustache.escape function override and relying on Mustache's
default HTML escaping behavior which uses double-brace syntax {{variable}}. If
you need to render trusted HTML in specific places, use the triple-brace syntax
{{{variable}}} or ampersand {{&variable}} selectively and only with data from
known-safe sources, never with user input. For user-generated content that requires
HTML formatting, sanitize it first using DOMPurify before passing to the template:
mustache.render(template, { content: DOMPurify.sanitize(userInput) }). Implement
server-side input validation and Content Security Policy (CSP) headers to provide
defense-in-depth protection. Review all Mustache templates to ensure unescaped
interpolations are only used with static trusted content or properly sanitized data,
not with request parameters, form inputs, or data from external APIs.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
rules-javascript-xss-generic¶
Summary:
Improper neutralization of input during web page generation ('Cross-site Scripting')
Severity: Medium
CWE: CWE-79
Description:
The application passes unsanitized user input to dangerous DOM manipulation methods
or HTTP response functions that can lead to Cross-Site Scripting (XSS). This rule
detects data flowing from untrusted sources like req.query, req.body, location.href,
document.querySelector().value, and function arguments into sensitive sinks including
innerHTML, outerHTML, document.write(), document.writeln(), jQuery methods
like $.html(), $.append(), and Express response methods like res.send(). These
sinks render content directly into the DOM or HTTP responses without automatic escaping.
When user-controlled data flows through these paths, attackers can inject malicious
JavaScript that executes in the victim's browser, potentially stealing session cookies,
accessing local storage, hijacking user accounts, or performing unauthorized API calls.
This vulnerability affects both DOM-based XSS (client-side sources like URL fragments),
reflected XSS (server-echoed input), and stored XSS (persisted malicious content).
Remediation:
Consider using safe DOM manipulation methods that don't interpret HTML: replace
element.innerHTML with element.textContent or element.innerText which automatically
escape content. For jQuery, use $.text() instead of $.html(). If you must render
HTML from user input (such as markdown or rich text), sanitize it first using DOMPurify
with a strict allowlist: element.innerHTML = DOMPurify.sanitize(userInput, {
ALLOWED_TAGS: ['p', 'b', 'i', 'em'] }). For server responses, use templating engines
with automatic escaping like Pug, EJS (with <%= syntax), or Handlebars. Implement
Content Security Policy (CSP) headers with script-src 'self' and avoid unsafe-inline.
For URL contexts, use encodeURIComponent() to escape special characters. Never
pass user input to eval(), setTimeout(string), Function(), or document.write().
Validate and sanitize all input on the server side before storing or rendering.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
rules_javascript_xss_bad_csp¶
Summary:
Unsafe CSP header
Severity: Medium
CWE: CWE-79
Description:
The application configures a Content Security Policy (CSP) header with insecure
directives that significantly weaken XSS protection. The rule detects dangerous CSP
values including unsafe-eval (which allows JavaScript execution via eval(),
setTimeout(string), and Function()), unsafe-inline (which permits inline
<script> tags and event handler attributes like onclick), data: and blob:
URIs (which allow loading resources from potentially attacker-controlled data URLs),
and wildcard * sources (which permit loading content from any origin). These
permissive directives undermine CSP's primary purpose of preventing XSS by restricting
where scripts can load from and how they execute. A weak CSP provides false security
confidence while leaving the application vulnerable to script injection attacks,
especially when combined with other vulnerabilities like DOM-based XSS or reflected XSS.
Remediation:
Consider implementing a strict Content Security Policy that removes unsafe directives.
Replace unsafe-inline with nonce-based or hash-based script allowlisting:
script-src 'nonce-{random}' where each script tag includes the matching nonce
attribute. Remove unsafe-eval entirely and refactor code to avoid eval() and
string-based timers. Replace * wildcards with explicit trusted domains:
script-src 'self' https://trusted-cdn.example.com. Prohibit data: and blob:
URIs in script-src, object-src, and worker-src directives. Use
default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self';
frame-ancestors 'none' as a baseline secure policy. For modern applications,
implement script-src 'strict-dynamic' with nonces which allows CSP to work with
dynamically loaded scripts while maintaining security. Test CSP changes carefully
using Content-Security-Policy-Report-Only header first to avoid breaking functionality.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
rules_lgpl_javascript_xss_rule-handlebars-noescape¶
Summary:
Improper neutralization of script-related HTML tags in a web page (basic XSS)
Severity: Medium
CWE: CWE-80
Description:
The application compiles Handlebars templates using Handlebars.compile() with the
insecure configuration option {noEscape: true}, which disables the template engine's
default HTML entity escaping. Handlebars automatically escapes template variable
interpolations using {{variable}} syntax to prevent Cross-Site Scripting (XSS)
attacks by converting characters like <, >, &, and " into their HTML entity
equivalents. Setting noEscape: true removes this critical security protection,
allowing raw HTML and JavaScript to be rendered into the DOM. When user-controlled
data flows through unescaped Handlebars templates, attackers can inject malicious
scripts that execute in the victim's browser, potentially stealing session cookies,
accessing sensitive data, or performing unauthorized actions on behalf of the user.
Remediation:
Consider removing the {noEscape: true} option from Handlebars.compile() calls
to restore automatic HTML escaping, which is the secure default behavior. If you
need to render trusted HTML in specific places, use the triple-brace syntax
{{{variable}}} selectively for known-safe content while keeping the default
escaping for all other variables. For user-generated content that must include
formatting, sanitize it first using DOMPurify before passing to Handlebars:
Handlebars.compile(template)({ content: DOMPurify.sanitize(userInput) }).
Additionally, implement Content Security Policy (CSP) headers to provide
defense-in-depth protection against XSS. Review all Handlebars templates to ensure
that triple-brace syntax and noEscape are only used with data from trusted,
controlled sources, never with user input or data from external APIs.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
rules_lgpl_javascript_xss_rule-handlebars-safestring¶
Summary:
Improper neutralization of input during web page generation (Cross-site Scripting)
Severity: Medium
CWE: CWE-79
Description:
The application uses new Handlebars.SafeString() to wrap content that will be
rendered without HTML escaping in Handlebars templates. The SafeString constructor
explicitly marks content as trusted and safe for direct HTML rendering, bypassing
Handlebars' default protection against Cross-Site Scripting (XSS). When user-controlled
data flows into a SafeString without proper sanitization, attackers can inject
malicious JavaScript that executes in the victim's browser context. This is particularly
dangerous because SafeString is designed to disable escaping, and if untrusted data
reaches it (for example, from req.query, req.body, or URL parameters), the
application becomes vulnerable to XSS attacks that can steal authentication tokens,
access local storage, or perform unauthorized actions on behalf of the victim.
Remediation:
Consider avoiding SafeString entirely and rely on Handlebars' default {{variable}}
syntax which automatically escapes HTML entities. If you must construct HTML strings
programmatically (such as in Handlebars helpers), always escape user-controlled
portions using Handlebars.escapeExpression() before wrapping in SafeString:
new Handlebars.SafeString('<div>' + Handlebars.escapeExpression(userInput) +
'</div>'). For rich content that requires HTML formatting, sanitize it using
DOMPurify before creating the SafeString. Better yet, refactor the code to use
Handlebars partials and block helpers which allow composing templates safely without
raw HTML construction. Implement input validation on the server side and Content
Security Policy (CSP) headers to provide additional XSS protection. Review all
SafeString usage to ensure it only wraps static trusted content or properly escaped
dynamic data.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
rules_lgpl_javascript_xss_rule-squirrelly-autoescape¶
Summary:
Improper neutralization of input during web page generation ('Cross-site Scripting')
Severity: Medium
CWE: CWE-79
Description:
The application calls Sqrl.autoEscaping(false) which disables automatic HTML escaping
in the Squirrelly template engine. By default, Squirrelly (often aliased as Sqrl)
automatically escapes template variable interpolations using {{variable}} syntax to
prevent Cross-Site Scripting (XSS) by converting characters like <, >, &, and "
into HTML entities. Calling autoEscaping(false) globally disables this protection
for all subsequent template renders, allowing raw HTML and JavaScript to be injected
into the DOM. When user-controlled data from sources like req.query, req.body,
URL parameters, or form inputs flows through templates with autoEscaping disabled,
attackers can inject malicious scripts that execute in the victim's browser, potentially
stealing session cookies, accessing sensitive application data, or performing unauthorized
actions on behalf of the user.
Remediation:
Consider removing the Sqrl.autoEscaping(false) call and rely on Squirrelly's
default autoEscaping(true) behavior which provides automatic HTML entity escaping.
If you need to render trusted HTML in specific template sections, use Squirrelly's
raw filter {{variable | raw}} selectively for known-safe content while keeping
auto-escaping enabled globally. For user-generated content that requires HTML
formatting (such as rich text editor output), sanitize it first using DOMPurify
before passing to the template: Sqrl.Render(template, { content: DOMPurify.sanitize
(userInput) }). Implement server-side input validation, Content Security Policy
(CSP) headers, and ensure that any use of the raw filter is limited to data from
trusted, controlled sources. Review all Squirrelly templates to verify that
user input is never rendered with auto-escaping disabled.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
rules_lgpl_javascript_xss_rule-xss-serialize-javascript¶
Summary:
Improper neutralization of script-related HTML tags in a web page (basic XSS)
Severity: Medium
CWE: CWE-80
Description:
The application uses the serialize-javascript library with the configuration option
{unsafe: true}, which disables the library's XSS protection mechanisms. The
serialize-javascript package is designed to safely serialize JavaScript objects into
strings that can be embedded in HTML (typically in <script> tags for server-side
rendering). By default, it escapes dangerous characters like <, >, and / to
prevent XSS attacks when the serialized output is injected into HTML. Setting
unsafe: true disables this escaping, allowing raw JavaScript code and HTML tags
to pass through unmodified. When user-controlled data is serialized with the unsafe
flag and then embedded in HTML, attackers can inject malicious JavaScript that
executes when the page loads, potentially stealing authentication tokens, accessing
sensitive data, or performing unauthorized actions in the victim's browser.
Remediation:
Consider removing the {unsafe: true} option from serialize-javascript calls and
rely on the library's default safe serialization behavior which escapes HTML special
characters. The default configuration protects against XSS when embedding serialized
data in <script> tags: <script>window.__DATA__ = ${serialize(data)}</script>.
If you're certain the data being serialized comes from a fully trusted source with
no user input, document this assumption clearly in code comments and consider
implementing runtime assertions to verify data sources. For modern applications,
consider alternative approaches like passing data via JSON in data attributes
(<div data-config='${JSON.stringify(config)}'>) or using a proper state management
solution that doesn't require embedding JavaScript in HTML. Implement Content
Security Policy (CSP) headers and ensure all user input is validated on the server
before serialization.
OWASP:
- A7:2017-Cross-Site Scripting (XSS)
- A03:2021-Injection
javascript_require_rule-non-literal-require¶
Summary:
Improper neutralization of directives in dynamically evaluated code ('Eval Injection')
Severity: Low
CWE: CWE-95
Description:
The application dynamically imports modules using require() with a non-literal
string argument. This enables potential code injection attacks where an adversary
could manipulate the module path to read arbitrary file contents or, with filesystem
write access, execute malicious code. Dynamic module loading breaks static analysis
and creates unpredictable security boundaries.
Remediation:
Consider using static ES6 import statements instead of require() to enable
compile-time module resolution. If dynamic imports are necessary, recommended to
validate the module path against a strict allowlist of permitted modules before
loading. Never pass user-controlled input directly to require(). For dynamic
code loading scenarios, consider using a mapping object where user input selects
a key that maps to a hardcoded module path.
OWASP:
- A1:2017-Injection
- A03:2021-Injection