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.0 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 11 of 11 warn and critical signals; 11 demoted to info.
Disclude version
4.1.0
Scanned (UTC)
2026-10-22 10:36

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({
    likely benign LLM, confidence 0.90 Markdown docs example showing an Ajv keyword import.
    Reasoning

    The snippet is a TypeScript example in Markdown documentation for Ajv keyword registration. The non-literal import is a doc illustration, not executable project code.

  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({
    likely benign LLM, confidence 0.90 Second Markdown docs example for Ajv keyword definitions.
    Reasoning

    Same documentation context as the other keywords.md finding: an illustrative code block in a docs file with no execution path.

  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 compiler generating validation functions via new Function.
    Reasoning

    Ajv's JIT compiler builds validator functions from generated source using new Function. This is the library's core, documented code-generation design, not hidden or attacker-supplied code.

  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 code generation via new Function.
    Reasoning

    The JTD parser generator uses new Function to build a parse function from internally generated code, matching Ajv's standard code-generation approach.

  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 code generation via new Function.
    Reasoning

    The JTD serializer generator uses new Function on internally generated code, consistent with the library's design and not attacker-controlled input.

  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)
    likely benign LLM, confidence 0.88 Build script reading package.json with a path-joined require.
    Reasoning

    The build script requires package.json through path.join with __dirname, a fixed local path. This is ordinary build tooling.

  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.82 Test helper requiring the Ajv build in Node only, using string concatenation.
    Reasoning

    The require uses a concatenated string to keep bundlers from resolving the module in browser builds. The target is a fixed local relative path, and the concatenation is a known test-harness pattern, not a payload.

  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.82 Test helper requiring the 2019 Ajv build in Node only.
    Reasoning

    Same dual browser/Node test-harness pattern: a concatenated require of a fixed local dist path, guarded by a window check.

  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.82 Test helper requiring the 2020 Ajv build in Node only.
    Reasoning

    Same test-harness pattern as the other spec files, requiring a fixed local dist module.

  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.82 Test helper requiring the JTD Ajv build in Node only.
    Reasoning

    Same test-harness pattern: a fixed local dist/jtd require, selected only when no window object exists.

  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.85 Test shim loading chai in Node, using a concatenated require.
    Reasoning

    A browser/Node shim that requires the chai test dependency via concatenated string. The target is a well-known package, so this is a bundler-avoidance idiom, not malicious.

  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.1.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 .