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

Use with CSP & Unsafe-Eval #406

Closed
TheKidCoder opened this issue Jan 30, 2017 · 13 comments
Closed

Use with CSP & Unsafe-Eval #406

TheKidCoder opened this issue Jan 30, 2017 · 13 comments
Labels

Comments

@TheKidCoder
Copy link

TheKidCoder commented Jan 30, 2017

I see that AJV uses eval in the source to compile the Schema object. Is it possible to provide AJV with some sort of precompiled version of the schema to avoid using eval? We are working towards removing 'unsafe-eval' in our CSP headers and this is the last blocker.

@epoberezkin
Copy link
Member

Ajv uses Function constructor indeed, not eval. You can do it with ajv-cli - the pre-compilation feature is BETA though, it doesn't support all cases of schema references and has limited support of custom keywords.

@jdmswong
Copy link

jdmswong commented Feb 7, 2017

'unsafe-eval' is preventing the use of ajv in my app. how do I get around this?

you mentioned ajv-cli but that is for the command line.

@TheKidCoder
Copy link
Author

@jdmswong AJV uses the Function constructor to take your json-schema in the browser and compile a function at "run-time". The idea with using ajv-cli is to to "precompile" the function before runtime. You can then store that function somewhere and pass it to AJV instead/along-side of your json-schema object. The real tool you would be using is: https://github.com/epoberezkin/ajv-pack

@jdmswong
Copy link

jdmswong commented Feb 7, 2017

is it still possible to dynamically validate dynamic data using static schemas using this tool; or will I have to pre-generate a module for each schema I use on the front end, then require and run it?

@epoberezkin
Copy link
Member

@jdmswong it is possible to validate using static schemas AND you will have to generate a function/module for each such schema you want to use. Why is there OR in the question?

@jdmswong
Copy link

jdmswong commented Feb 7, 2017

@epoberezkin I meant to add 'without specifically pre-compiling each one'. Using pre-compilation it sounds as if I have to extract each of the schemas spread around my code into individual files, which would be a lot of overhead. I also like to see the schema in the relevant code, for easy readability.

@epoberezkin
Copy link
Member

@jdmswong Ajv compiles schemas to code. You can do it at run time, in which case it uses Function constructor - you will need to change your CSP to allow it. Or you can do it at build time converting all your schemas to modules that can be required (it is done this way in "table" package, e.g.). There is no other option.

epatters added a commit to epatters/datascienceontology-backend that referenced this issue Oct 18, 2018
Ajv is clearly superior but it's been broken ever since Bluemix set the
CouchDB/Cloudant CSP to block Function().

http://docs.couchdb.org/en/2.1.1/config/misc.html#content-security-policy
ajv-validator/ajv#406
epatters added a commit to epatters/datascienceontology-backend that referenced this issue Dec 1, 2019
Ajv is clearly superior but it's been broken ever since Bluemix set the
CouchDB/Cloudant CSP to block Function().

http://docs.couchdb.org/en/2.1.1/config/misc.html#content-security-policy
ajv-validator/ajv#406
epatters added a commit to epatters/datascienceontology-backend that referenced this issue Dec 1, 2019
Ajv is clearly superior but it's been broken ever since Bluemix set the
CouchDB/Cloudant CSP to block Function().

http://docs.couchdb.org/en/2.1.1/config/misc.html#content-security-policy
ajv-validator/ajv#406
@dgreene1
Copy link

dgreene1 commented Aug 5, 2020

Connecting the two issues. Here's where the solution was documented: #1228

I will note that it's not an ideal solution due to the fact that Ajv can handle multiple schemas, however ajv-pack cannot currently (see ajv-validator/ajv-pack#4)

@Nantris
Copy link

Nantris commented Feb 6, 2021

@epoberezkin I had thought with v7 that pre-compiling would no longer be relevant because eval or equivalents were no longer used. I guess I was mistaken?

Is there a recommended method for using AJV with multiple schemas without imploding security?

@suryateja1065
Copy link

@jdmswong Ajv compiles schemas to code. You can do it at run time, in which case it uses Function constructor - you will need to change your CSP to allow it. Or you can do it at build time converting all your schemas to modules that can be required (it is done this way in "table" package, e.g.). There is no other option.

@epoberezkin epoberezkin I am facing a similar issue and I want to do this precompile workaround. I would like to see any snippet code to register my schemas ..Help is appreciated

@epoberezkin
Copy link
Member

Please see https://ajv.js.org/standalone.html

@Nantris
Copy link

Nantris commented Sep 1, 2021

@suryateja1065 this issue has some sample code that might lead you in the right direction: #1470

@doesdev
Copy link

doesdev commented Jan 18, 2022

If anyone is using Rollup, this can be done by adding a custom plugin to your config. Obviously a properly made plugin module would be ideal but there isn't one I could find and I'm not in the position to publish one myself at the moment. So, here's some example code that may aid anyone wanting to take that approach:

to-be-bundled.js

import mySchemaValidator from 'my-schema.jsonschema' // assuming "schemas/my-schema.json" exists on disk

const checkSchema = (data) => {
  const valid = mySchemaValidator(data)
  // ...
}

rollup.config.js

import Ajv from 'ajv'
import ajvGenerate from 'ajv/dist/standalone'
import path from 'path'
import fs from 'fs'

const schemas = path.resolve(__dirname, 'schemas')

const jsonSchemaValidator = () => {
  return {
    name: 'rollup-plugin-ajv-validator',
    resolveId: (source) => source.indexOf('.jsonschema') === -1 ? null : source,
    load: async (id) => {
      if (id.indexOf('.jsonschema') === -1) return null

      const schemaFile = id.replace(/\.jsonschema$/, '.json')

      try {
        const schemaPath = path.join(schemas, schemaFile)
        const schemaJson = await fs.promises.readFile(schemaPath, 'utf8')
        const schema = JSON.parse(schemaJson)

        const ajv = new Ajv({ code: { source: true, esm: true } })
        const validator = ajv.compile(schema)
        const sourceOut = ajvGenerate(ajv, validator)

        return sourceOut
      } catch (ex) {
        console.error(ex)

        return 'export default () => true'
      }
    }
  }
}

export default ({
  // ...
  plugins: [jsonSchemaValidator()]
})

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

No branches or pull requests

7 participants