Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate eval (new Function) from sourceCode generation (CodeGen) #2527

Open
mirismaili opened this issue Jan 12, 2025 · 1 comment
Open

Comments

@mirismaili
Copy link

mirismaili commented Jan 12, 2025

What version of Ajv are you using?

8.17.1

What problem do you want to solve?

Currently, using AJV on sites with Content Security Policy (CSP) rules that disallow unsafe-eval is not feasible due to its reliance on new Function. This limitation is documented here: https://ajv.js.org/security.html#content-security-policy

And the suggested approach around this limitation is a two-step process:

  1. Generate the sourceCode for the schema validation.
  2. Serve the sourceCode as a standard .js file, which can then be included alongside other JavaScript assets on the site.

However, unfortunately, purely doing the first step—JUST generating the sourceCode—is currently impossible too. Because compileSchema() generates the sourceCode but immediately attempts to create the validate function using new Function(), which violates CSP rules:

ajv/lib/compile/index.ts

Lines 167 to 172 in 82735a1

sourceCode = `${gen.scopeRefs(N.scope)}return ${validateCode}`
// console.log((codeSize += sourceCode.length), (nodeCount += gen.nodeCount))
if (this.opts.code.process) sourceCode = this.opts.code.process(sourceCode, sch)
// console.log("\n\n\n *** \n", sourceCode)
const makeValidate = new Function(`${N.self}`, `${N.scope}`, sourceCode)
const validate: AnyValidateFunction = makeValidate(this, this.scope.get())

While in this two-step process, the validate function isn't needed at all, during the first step. (Additionally, this is an extra work).

And the problem is in our case, we do the job in a service-worker which is subject to CSP regulations itself and so it can't execute eval() (or new Function()).

What do you think is the correct solution to the problem?

Introduce a dedicated, pure function that generates only the sourceCode. This function should work independently of compileSchema and should not attempt to create a validate function. Such a function would be compatible with CSP-bound environments and could be used by both compileSchema and developers needing sourceCode generation.

Will you be able to implement it?

Probably yes.

@mirismaili
Copy link
Author

mirismaili commented Jan 12, 2025

Temporary workaround I found:

Mock global Function to make validate function CSP-safe (and does nothing in step 1):

// Workaround for this issue: https://github.com/ajv-validator/ajv/issues/2527
// @ts-expect-error // TS2322: Type `() => () => () => boolean` is not assignable to type `FunctionConstructor`
globalThis.Function = function () {
  return function mockMakeValidate() {
    return function mockValidate() {
      return true
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

1 participant