npm / ajv / 8.20.0

ajv 8.20.0

Source
https://github.com/ajv-validator/ajv
Tag scanned
v8.20.0
Compared with
v8.19.0 (0 signals introduced since)
Files
244 scanned, 144 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 13 info
Scan time
9.4 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 11 of 11 warn and critical signals; 11 demoted to info.
Disclude version
4.0.0
Scanned (UTC)
2026-10-14 19:04

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. info long-line README.md:25:1

    line length 695 characters (raw pass, confidence 0.50)

    [<img src="https://ajv.js.org/img/retool.svg" width="22.5%" alt="Retool">]https://retool.com/?utm_source=sponsor&utm_campaign=ajv<img src="https://ajv.js.org/img/gap.svg" width="3%">[<img src="https://ajv.js.org/img/tidelift.svg" width="22.5%" alt="Tidelift">](https://tidelift.com/subscription/pkg/npm-ajv?utm_source=
  2. info warn → info by review dynamic-import docs/keywords.md:48:1

    [embedded typescript] dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

    import {_, KeywordCxt} from Ajv
    
    ajv.addKeyword({
    dismissed LLM, confidence 0.90 Documentation example showing a dynamic import in a code block.
    Reasoning

    The flagged import(...) sits inside an embedded TypeScript code sample in a markdown documentation file showing how to define a custom Ajv keyword. It is illustrative text, not executable code in the package.

  3. info warn → info by review dynamic-import docs/keywords.md:71:1

    [embedded typescript] dynamic `import(...)` with a non-literal specifier (ast pass, confidence 0.65)

    import {_, nil, KeywordCxt} from Ajv
    
    ajv.addKeyword({
    dismissed LLM, confidence 0.90 Documentation example for adding an Ajv keyword, with a dynamic import in the code sample.
    Reasoning

    Same as the other keywords.md finding: an illustrative TypeScript snippet in documentation, with no execution path in the shipped library.

  4. info critical → info by review dynamic-execution lib/compile/index.ts:171:26

    `Function(...)` called with a non-literal body (ast pass, confidence 0.90)

        // console.log("\n\n\n *** \n", sourceCode)
        const makeValidate = new Function(`${N.self}`, `${N.scope}`, sourceCode)
        const validate: AnyValidateFunction = makeValidate(this, this.scope.get())
        this.scope.value(validateName, {ref: validate})
    likely benign LLM, confidence 0.90 Ajv's validator compiler builds JavaScript source from schemas and instantiates it with the Function constructor.
    Reasoning

    Ajv is a JSON Schema compiler whose core function is generating validator source code and instantiating it with new Function. The body is built from the library's own code generator from a schema the developer supplies, which is the documented design of the library, not an injected payload.

  5. info critical → info by review dynamic-execution lib/compile/jtd/parse.ts:69:23

    `Function(...)` called with a non-literal body (ast pass, confidence 0.90)

        sourceCode = `${gen.scopeRefs(N.scope)}return ${parseFuncCode}`
        const makeParse = new Function(`${N.scope}`, sourceCode)
        const parse: (json: string) => unknown = makeParse(this.scope.get())
        this.scope.value(parseName, {ref: parse})
    likely benign LLM, confidence 0.90 JTD parser generation that compiles schema-derived source via the Function constructor.
    Reasoning

    This is the JTD parser code generator. It produces parse-function source from schema-derived code and instantiates it with new Function, the same expected pattern as the core Ajv compiler.

  6. info critical → info by review dynamic-execution lib/compile/jtd/serialize.ts:65:27

    `Function(...)` called with a non-literal body (ast pass, confidence 0.90)

        sourceCode = `${gen.scopeRefs(N.scope)}return ${serializeFuncCode}`
        const makeSerialize = new Function(`${N.scope}`, sourceCode)
        const serialize: (data: unknown) => string = makeSerialize(this.scope.get())
        this.scope.value(serializeName, {ref: serialize})
    likely benign LLM, confidence 0.90 JTD serializer generation that compiles schema-derived source via the Function constructor.
    Reasoning

    This is the JTD serializer code generator, using the same schema-driven code generation approach as the parser. The dynamic function is the library's intended mechanism.

  7. info warn → info by review dynamic-import scripts/bundle.js:10:14

    `require` called with a non-literal specifier (ast pass, confidence 0.60)

    
    const json = require(path.join(__dirname, "..", "package.json"))
    const bundleDir = path.join(__dirname, "..", "bundle")
    if (!fs.existsSync(bundleDir)) fs.mkdirSync(bundleDir)
    dismissed LLM, confidence 0.90 Build script that requires the local package.json via a path built from __dirname.
    Reasoning

    The require argument is path.join of __dirname and a fixed relative path to package.json, a local build script reading its own metadata. Nothing external or attacker-controlled feeds the path.

  8. info warn → info by review dynamic-import spec/ajv.ts:2:81

    `require` called with a non-literal specifier (ast pass, confidence 0.80)

    import type Ajv from "../dist/core"
    const AjvClass: typeof Ajv = typeof window == "object" ? (window as any).ajv7 : require("" + "..")
    
    export default AjvClass
    likely benign LLM, confidence 0.80 Test helper that conditionally requires the built Ajv module under Node, with the specifier concatenated to avoid bundling.
    Reasoning

    The string concatenation "" + ".." hides the require target from bundlers, so the browser build skips it. It is a test harness fallback loading the local built module, a common pattern, not malicious.

  9. info warn → info by review dynamic-import spec/ajv2019.ts:3:57

    `require` called with a non-literal specifier (ast pass, confidence 0.80)

    const AjvClass: typeof Ajv2019 =
      typeof window == "object" ? (window as any).ajv2019 : require("" + "../dist/2019")
    
    export default AjvClass
    likely benign LLM, confidence 0.80 Test helper requiring the local 2019 Ajv build under Node, with a concatenated specifier.
    Reasoning

    Same bundler-avoidance pattern as spec/ajv.ts, requiring a fixed local build path ../dist/2019 for Node test runs. The target is the project's own build output.

  10. info warn → info by review dynamic-import spec/ajv2020.ts:3:57

    `require` called with a non-literal specifier (ast pass, confidence 0.80)

    const AjvClass: typeof Ajv2020 =
      typeof window == "object" ? (window as any).ajv2020 : require("" + "../dist/2020")
    
    export default AjvClass
    likely benign LLM, confidence 0.80 Test helper requiring the local 2020 Ajv build under Node, with a concatenated specifier.
    Reasoning

    Same pattern: a fixed local build path ../dist/2020 is required under Node only, with the specifier split to dodge bundlers. Test scaffolding, not an attack.

  11. info warn → info by review dynamic-import spec/ajv_jtd.ts:3:56

    `require` called with a non-literal specifier (ast pass, confidence 0.80)

    const AjvClass: typeof AjvJTD =
      typeof window == "object" ? (window as any).ajvJTD : require("" + "../dist/jtd")
    
    export default AjvClass
    likely benign LLM, confidence 0.80 Test helper requiring the local JTD Ajv build under Node, with a concatenated specifier.
    Reasoning

    Same pattern: a fixed local build path ../dist/jtd is required in Node test runs, with the specifier split to avoid bundling. Benign test setup.

  12. info warn → info by review dynamic-import spec/chai.ts:3:77

    `require` called with a non-literal specifier (ast pass, confidence 0.80)

    
    const chai: ChaiStatic = typeof window == "object" ? (window as any).chai : require("" + "chai")
    
    export default chai
    likely benign LLM, confidence 0.80 Test helper loading the chai assertion library under Node with a concatenated module name.
    Reasoning

    The chai module is required under Node only when window is absent, with the name split by string concatenation to avoid bundling. A standard test-dependency loading pattern on a well-known package.

  13. surrogate pair \uD83D\uDC4D (non-scalar Unicode codepoints in string literal) (token pass, confidence 0.70)

    describe("unicodeRegExp option", () => {
      const unicodeChar = "\uD83D\uDC4D"
      const unicodeSchema = {
        type: "string",

Reproduce This Scan

Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.

cargo install disclude --version 4.0.0
git clone https://github.com/ajv-validator/ajv ajv && cd ajv
git checkout v8.20.0
disclude scan --severity info --diff v8.19.0 .