Skip to content

j$.isError_ is not compatible with Trusted Types #1910

@bjarkler

Description

@bjarkler

The isError_ function is used to identify JS objects that are instances of Error. A simple instanceof check does not capture errors that are constructed e.g. in a different window, but instead the function performs an overzealous heuristic in order to detect this, which involves invoking the Function constructor, passing the string 'return this'.

Trusted Types is a runtime security mechanism which applications can configure in order to restrict usage of security-sensitive DOM APIs. Passing a string to the Function constructor is security-sensitive, and thus blocked by browsers in applications that configure Trusted Types in enforcement mode.

While this mechanism is primarily useful for preventing XSS vulnerabilities in production applications, there is also great value in enforcing Trusted Types in unit tests in order to detect and prevent unexpected breakage when enforcing Trusted Types in those applications.

Expected Behavior

The isError_ detects instances of Error in a way that is compatible with Trusted Types. In particular, it should not call the Function constructor or eval.

Current Behavior

The function currently calls new Function('return this'), which constitutes a Trusted Types violation. The overzealous nature of the current heuristic has also caused other issues in the past (#1623).

Possible Solution

Since the current implementation is after all a heuristic, perhaps a simpler heuristic would suffice. One approach is described on a StackOverflow question, and could be implemented as follows:

j$.isError_ = function(value) {
  return value && value.stack && value.message &&
         typeof value.stack === 'string' &&
         typeof value.message === 'string';
};

Suite that reproduces the behavior (for bugs)

The following test suite needs to be run with Trusted Types enforced.

describe("isError_", function() {
  it("does not cause Trusted Types violations", function() {
    j$.isError_(new Error());
  });
});

To enforce Trusted Types when using Karma, specify the following in karma.conf.js:

module.exports = function(config) {
  config.set({
    customHeaders: [{
      match: ".*",
      name: "Content-Security-Policy",
      value: "trusted-types karma; require-trusted-types-for 'script';"
    }],
  });
};

Context

Angular recently added support for using Trusted Types. The present issue is currently blocking us from enforcing Trusted Types in Angular's test suite, which would help prevent regressions in Trusted Types support.

Your Environment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions