Skip to content

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