Profiles·Public

ajv

semver>=8.18.0 <10.0.0postconditions14functions8last verified2026-06-24coverage score89%

Postconditions: what we check

  • validate · validate-returns-false
    error
    Whendata fails validation against the JSON schema
    Returnsfalse (errors are stored in ajv.errors property)
    Required handlingCaller MUST check the return value of validate() and handle the false case. When validate() returns false, ajv.errors contains validation error details. Without checking the return value, invalid data will pass through, leading to data corruption, business logic errors, or security vulnerabilities. Use pattern: if (!ajv.validate(schema, data)) { console.error(ajv.errors); }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • compile · compile-invalid-schema
    warning
    Whenschema is invalid or malformed
    ThrowsError (schema compilation error)
    Required handlingCaller MUST wrap compile() in try-catch when working with untrusted schemas. Invalid schemas cause compilation errors that crash the application. Use pattern: try { const validate = ajv.compile(schema); } catch (error) { /* handle */ }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • validateSchema · validateschema-returns-false
    warning
    Whenschema is invalid according to meta-schema
    Returnsfalse (errors are stored in ajv.errors property)
    Required handlingCaller MUST check the return value to determine if schema is valid. Without checking, invalid schemas may be used, causing unexpected validation behavior. Use pattern: if (!ajv.validateSchema(schema)) { console.error(ajv.errors); }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[2]
  • validateSchema · validateschema-invalid-dollar-schema
    warning
    WhenThe schema object contains a `$schema` property whose value is not a string (e.g., a number, boolean, object, or null). validateSchema throws synchronously BEFORE running meta-schema validation, so the errors array is never populated.
    ThrowsError: $schema must be a string
    Required handlingCaller MUST wrap validateSchema() in try-catch when the schema may be user-supplied or programmatically constructed. The thrown Error is NOT captured in ajv.errors — it propagates as an exception. Schema-builder libraries that accidentally emit a non-string $schema (e.g., from an object spread that overwrites the field) will crash the process here. Use pattern: try { if (!ajv.validateSchema(schema)) { /* invalid */ } } catch (e) { /* malformed $schema */ }
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[2]
  • compileAsync · compileasync-no-load-schema
    error
    WhencompileAsync() is called without configuring the loadSchema option in Ajv constructor
    ThrowsError: options.loadSchema should be a function
    Required handlingCaller MUST configure loadSchema in Ajv options before calling compileAsync(). The error throws synchronously before the promise is even created. If the schema has external $ref dependencies, loadSchema is mandatory. Use pattern: new Ajv({ loadSchema: async (uri) => fetch(uri).then(r => r.json()) })
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3][4]
  • compileAsync · compileasync-load-schema-rejects
    error
    WhenThe loadSchema function rejects (e.g., remote schema URL returns 404/500, network is unavailable, or the schema server is down)
    ThrowsError (propagated rejection from loadSchema)
    Required handlingCaller MUST await compileAsync() inside a try-catch or attach a .catch() handler. loadSchema failures propagate as promise rejections. In server startup code, unhandled rejections crash Node.js. Cache compiled validators to avoid repeated remote fetches on every request. Use pattern: const validate = await ajv.compileAsync(schema).catch(err => { throw new Error('Schema load failed: ' + err.message); })
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3][4]
  • compileAsync · compileasync-invalid-schema
    error
    WhenThe schema (or a schema loaded via loadSchema) is invalid against its meta-schema
    ThrowsError: schema is invalid
    Required handlingCaller MUST wrap compileAsync() in try-catch. Invalid referenced schemas cause the promise to reject with a descriptive Error. Schemas loaded dynamically from external sources should be pre-validated before being returned from loadSchema. Use pattern: try { const validate = await ajv.compileAsync(schema); } catch (e) { handle(e); }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • addSchema · addschema-duplicate-id
    error
    WhenA schema with the same $id or key is added a second time to the same Ajv instance
    ThrowsError: schema with key or id already exists
    Required handlingCaller MUST check if a schema is already registered before calling addSchema(). Duplicate schema registration crashes immediately. This commonly occurs in server code that initializes Ajv in module scope but registers schemas in a function called on every request or startup retry. Use pattern: if (!ajv.getSchema(schema.$id)) { ajv.addSchema(schema); }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5]
  • addSchema · addschema-invalid-schema-throws
    warning
    WhenA schema with invalid structure is added and validateSchema option is true (default). Ajv validates the schema against the meta-schema during addSchema().
    ThrowsError: schema is invalid
    Required handlingCaller MUST wrap addSchema() in try-catch when registering schemas from untrusted or external sources. Schema validation errors throw synchronously. If registering known static schemas at startup, errors here indicate a developer mistake and should be allowed to crash (fail-fast). For dynamic schemas from user input, validate first using ajv.validateSchema() before calling addSchema().
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5]
  • addKeyword · addkeyword-duplicate-keyword
    error
    WhenaddKeyword() is called with a keyword name that was already registered on this Ajv instance (either a standard JSON Schema keyword or a previously added custom keyword)
    ThrowsError: Keyword <name> is already defined
    Required handlingCaller MUST check if the keyword is already registered before calling addKeyword(). There is no way to redefine or remove keywords once added. Duplicate registration is a common bug in modular server code where multiple modules independently try to register the same shared keyword (e.g., a custom "nullable" keyword registered by two different plugins). Use pattern: if (!ajv.getKeyword(keyword)) { ajv.addKeyword(definition); }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[6]
  • addKeyword · addkeyword-invalid-name
    warning
    WhenThe keyword name contains invalid characters (must match /^[a-z_$][a-z0-9_$:-]*$/i) or is empty
    ThrowsError: Keyword <name> has invalid name
    Required handlingCaller MUST use valid keyword names starting with ASCII letter, underscore, or dollar sign, containing only alphanumerics, underscores, hyphens, or colons. Use application-specific prefixes to avoid name collisions with future JSON Schema keywords (e.g., "myapp-nullable" instead of "nullable").
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[6]
  • removeSchema · removeschema-invalid-parameter
    error
    WhenremoveSchema() is called with a parameter that is not undefined, a string, a RegExp, or an object (e.g., a number, boolean, or symbol). This typically occurs when the schema identifier is sourced from untyped JSON or user input without runtime type narrowing.
    ThrowsError: ajv.removeSchema: invalid parameter
    Required handlingCaller MUST ensure the schemaKeyRef is one of: undefined, string ($id or key), RegExp, or the schema object itself. When the identifier comes from external input (config files, HTTP requests, queue messages), narrow the type before calling removeSchema. Otherwise wrap in try-catch to prevent a runtime crash from a misconfigured identifier. Use pattern: if (typeof key === 'string') { ajv.removeSchema(key); } else if (key instanceof RegExp) { ... }
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[7]
  • addMetaSchema · addmetaschema-duplicate-key
    error
    WhenA meta-schema with the same $id or key is added a second time to the same Ajv instance. Internally addMetaSchema calls addSchema, which throws on duplicate registration.
    ThrowsError: schema with key or id already exists
    Required handlingCaller MUST check whether the meta-schema is already registered before calling addMetaSchema(). This is especially common when multiple modules independently try to register the same JSON Schema draft (e.g., draft-2019-09) on a shared Ajv instance during application startup or in test setup that runs per-file. Use pattern: if (!ajv.getSchema(metaSchema.$id)) { ajv.addMetaSchema(metaSchema); }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[8]
  • addMetaSchema · addmetaschema-invalid-schema
    warning
    WhenThe meta-schema being added has invalid structure and validateSchema is true (default). Ajv validates the incoming meta-schema against its own meta-schema during addMetaSchema(), throwing synchronously on failure.
    ThrowsError: schema is invalid
    Required handlingCaller MUST wrap addMetaSchema() in try-catch when registering meta-schemas loaded from external sources (custom JSON Schema dialects, third-party schema libraries). For static meta-schemas bundled with the application, failure here indicates a developer mistake and should fail-fast at startup.
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[8]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Official documentation
  • [1]
    ajv.js.org/guide/getting-started.html
    Getting Started
  • [2]
    ajv.js.org/api.html
    Api
  • [3]
    ajv.js.org/api.html
    Api
  • [4]
    ajv.js.org/guide/managing-schemas.html
    Managing Schemas
  • [5]
    ajv.js.org/api.html
    Api
  • [6]
    ajv.js.org/api.html
    Api
  • [7]
    ajv.js.org/api.html
    Api
  • [8]
    ajv.js.org/api.html
    Api

Research notes

Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.

Sources: ajv

Package: ajv (Another JSON Schema Validator) Contract Version: 1.0.0 Last Verified: 2026-02-26 Maintainer: corpus-team


Package Overview

AJV is the fastest JSON schema validator for Node.js and browser. It implements JSON Schema specification drafts 04, 06, 07, 2019-09, and 2020-12. Widely used in API frameworks (Fastify, Express), configuration validation (ESLint), and data validation across the JavaScript ecosystem.

Key Characteristics:

  • Returns boolean from validate() - errors stored in property (not thrown)
  • Compile-time schema validation with caching for performance
  • Supports custom keywords, formats, and async validation
  • Strict mode catches schema errors at compile time

Official Documentation

Primary Documentation

  1. Official Website: https://ajv.js.org/

    • Comprehensive documentation, guides, and examples
    • Getting started guide, API reference, security considerations
  2. API Reference: https://ajv.js.org/api.html

    • Complete API documentation for all methods
    • Error object structure and properties
    • TypeScript type definitions
  3. Getting Started Guide: https://ajv.js.org/guide/getting-started.html

    • Basic validation usage patterns
    • Performance best practices (compile once, validate many)
    • Error handling examples
  4. Security Considerations: https://ajv.js.org/security.html

    • Security best practices
    • Recommendations for handling untrusted schemas
    • Known vulnerabilities and mitigations
  5. Strict Mode Documentation: https://ajv.js.org/strict-mode.html

    • Strict mode behavior and benefits
    • Unknown keyword errors
    • StrictTypes validation

Package Information


Behavioral Claims

1. validate() Returns False on Validation Failure

Claim: ajv.validate(schema, data) returns false when data fails to match the JSON schema. Validation errors are stored in the ajv.errors property (array of error objects).

Primary Evidence:

Real-World Evidence:

  • ESLint rule-tester.js (lines 1243-1260): Uses ajv.validateSchema(schema) followed by if (ajv.errors) check
  • Fastify validation.js: Compiles schemas for request validation, framework checks return values

Critical Warning from Documentation:

"Every time this method is called the errors are overwritten so you need to copy them to another variable if you want to use them later."

Security Implication: If the return value is not checked, invalid data passes through unchecked. This can lead to:

  • Business logic errors (invalid data processed as valid)
  • Data corruption (malformed data stored in database)
  • Security vulnerabilities (malicious payloads bypass validation)
  • Type confusion attacks

Severity: ERROR - MUST check return value and handle false case

Sources:


2. compile() Throws on Invalid Schema

Claim: ajv.compile(schema) throws an error when the schema is invalid or malformed. This includes structural errors, invalid defaults, missing $ref targets, and strict mode violations.

Primary Evidence:

  • API Documentation: https://ajv.js.org/api.html

    "The schema passed to this method will be validated against meta-schema unless validateSchema option is false. If schema is invalid, an error will be thrown."

  • ESLint rule-tester.js (lines 1269-1278): Demonstrates try-catch pattern

    try {
      ajv.compile(schema);
    } catch (err) {
      throw new Error(`Schema for rule ${ruleName} is invalid: ${err.message}`, { cause: err });
    }
    
  • ESLint config.js (lines 342-350): Production usage with error handling

    try {
      const schema = getRuleOptionsSchema(rule);
      if (schema) {
        validators.set(rule, ajv.compile(schema));
      }
    } catch (err) {
      throw new InvalidRuleOptionsSchemaError(ruleId, err);
    }
    

Compilation Errors Include:

  • Invalid schema structure (detected by meta-schema validation)
  • Invalid default values in schema
  • Missing $ref target schemas (MissingRefError)
  • Strict mode violations (unknown keywords, unknown formats, missing types)
  • Circular references without proper handling

CVE Evidence:

Security Implication: Untrusted schemas can crash the application or, in older versions, execute arbitrary code. CVE-2020-15366 demonstrates that malicious schemas are a real attack vector.

Best Practice (ESLint Pattern):

  1. Call ajv.validateSchema(schema) to check structure
  2. Check ajv.errors for validation errors
  3. Call ajv.compile(schema) in try-catch to catch default/reference errors
  4. Never trust schemas from untrusted sources

Severity: WARNING - SHOULD wrap compile() in try-catch for untrusted schemas

Sources:


3. validateSchema() Returns False on Invalid Schema

Claim: ajv.validateSchema(schema) returns false when the schema is invalid according to the JSON Schema meta-schema. Errors are stored in ajv.errors.

Primary Evidence:

  • API Documentation: https://ajv.js.org/api.html

    "Validates schema. This method should be used to validate schemas rather than validate due to the inconsistency of uri format in JSON Schema standard."

  • ESLint rule-tester.js (lines 1243-1261): Demonstrates proper usage

    ajv.validateSchema(schema);
    
    if (ajv.errors) {
      const errors = ajv.errors.map(error => {
        const field = error.dataPath[0] === '.' ? error.dataPath.slice(1) : error.dataPath;
        return `\t${field}: ${error.message}`;
      }).join('\n');
      throw new Error([`Schema for rule ${ruleName} is invalid:`, errors]);
    }
    

Use Case: Validate untrusted schemas before compiling them. This is a preventive measure to catch schema errors early, before they cause compilation failures or runtime issues.

Best Practice: ESLint demonstrates double validation:

  1. validateSchema() checks schema structure against meta-schema
  2. compile() catches additional errors (invalid defaults, missing refs)

Why Both Are Needed:

"validateSchema checks for errors in the structure of the schema (by comparing the schema against a meta-schema), and it reports those errors individually. However, there are other types of schema errors that only occur when compiling the schema (e.g. using invalid defaults in a schema), and only one of these errors can be reported at a time." — ESLint rule-tester.js comments

Severity: WARNING - SHOULD validate untrusted schemas before use

Sources:


Security Vulnerabilities (CVEs)

CVE-2020-15366: Prototype Pollution (CRITICAL)

Severity: CVSS 9.8 (Critical) Affected Versions: ≤ 6.12.2 Fixed In: 6.12.3+

Description: A carefully crafted JSON schema could allow execution of arbitrary code by prototype pollution in ajv.validate().

Impact:

  • Remote code execution
  • Complete system compromise
  • Attacker can execute arbitrary code by providing malicious schema

Mitigation:

  • Upgrade to ajv 6.12.3 or higher
  • Never use untrusted schemas
  • Validate schemas with validateSchema() before compilation

Sources:


CVE-2025-69873: Regular Expression Denial of Service (CRITICAL)

Severity: Critical (ongoing as of 2026-02-26) Affected Versions: ≤ 8.17.1 Fixed In: 6.14.0+, 8.18.0+

Description: When $data option is enabled, the pattern keyword accepts runtime data via JSON Pointer syntax that is passed directly to RegExp() constructor without validation. Attacker can inject malicious regex pattern causing catastrophic backtracking.

Impact:

  • Complete denial of service with single HTTP request
  • 31-character payload causes ~44 seconds CPU blocking
  • Exponential time growth per additional character
  • Application becomes unresponsive

Attack Vector:

// Malicious pattern via $data
{ "pattern": { "$data": "0/maliciousPattern" } }
// Attacker provides: { maliciousPattern: "^(a|a)*$" }
// Combined with input: "aaaaaaaaaa...!" causes catastrophic backtracking

Conditions: Only exploitable when $data: true option is enabled

Mitigation:

  • Upgrade to ajv 6.14.0, 8.18.0 or higher
  • Disable $data option if not needed
  • Validate pattern inputs if using $data

Sources:


CVE-2021-44906: Vulnerability in uri-js Dependency

Severity: Medium Description: Vulnerability in stale uri-js dependency used by ajv Mitigation: Update to ajv versions with fixed uri-js dependency

Sources:


Real-World Usage Patterns

Framework Abstraction (Fastify, Express)

Pattern: Most production usage is via framework middleware that abstracts ajv

Example (Fastify):

// Developer code
fastify.post('/user', {
  schema: {
    body: {
      type: 'object',
      properties: {
        name: { type: 'string' }
      },
      required: ['name']
    }
  }
}, handler);

// Framework internals (hidden)
const validator = ajv.compile(schema.body);
if (!validator(request.body)) {
  reply.status(400).send({ errors: validator.errors });
}

Implication: Application code rarely contains direct ajv.validate() calls. Validation checking is delegated to framework middleware.

Sources:


Direct AJV Usage (ESLint)

Pattern: Direct ajv usage with comprehensive error handling

Best Practice Example:

// Validate schema structure
ajv.validateSchema(schema);
if (ajv.errors) {
  // Handle schema validation errors
  throw new Error([`Schema is invalid:`, formatErrors(ajv.errors)]);
}

// Compile schema (may throw additional errors)
try {
  ajv.compile(schema);
} catch (err) {
  throw new Error(`Schema is invalid: ${err.message}`, { cause: err });
}

Sources:


Analyzer Detection Challenges

Return Value Pattern (Similar to validator package)

Challenge: validate() returns boolean, errors stored in property

Pattern:

// VIOLATION - return value not checked
ajv.validate(schema, data); // Invalid data passes unchecked!

// PROPER - return value checked
const valid = ajv.validate(schema, data);
if (!valid) {
  console.error(ajv.errors);
}

Detection Difficulty: HIGH - Similar to validator package analyzer limitation

Recommendation: If analyzer cannot detect missing return value checks, document as analyzer limitation and mark contract accordingly (similar to validator package BLOCKED status).


Framework Abstraction

Challenge: 85.7% of ajv usage is via framework middleware (based on sample analysis)

Impact: Application code may have zero direct ajv.validate() calls, making violations undetectable in static analysis of application code.

Example: Fastify app with 100 validated routes = 0 detectable violations in app code (validation in framework).


Version Recommendations

Minimum Safe Version: 8.18.0

  • Includes fixes for CVE-2025-69873 (ReDoS)
  • Includes fixes for CVE-2020-15366 (Prototype Pollution)
  • Latest stable with all known CVE fixes

Legacy Safe Version: 6.14.0+ (if must stay on v6 line)

Contract Semver: >=8.18.0 <10.0.0

Upgrade Priority: CRITICAL (multiple critical CVEs in older versions)


Additional Resources

Community Packages

Security Resources


Summary

AJV is a high-performance JSON schema validator with a return value pattern (returns boolean, errors in property) rather than throwing exceptions. This pattern requires callers to explicitly check the return value and handle the false case.

Critical Security Points:

  1. MUST check validate() return value (invalid data passing = security vulnerability)
  2. SHOULD wrap compile() in try-catch for untrusted schemas (CVE-2020-15366)
  3. SHOULD use validateSchema() before compile() for untrusted schemas (ESLint pattern)
  4. MUST use version 8.18.0+ (critical CVEs in older versions)
  5. NEVER use untrusted schemas without validation

Real-World Usage:

  • Most production usage is via framework middleware (Fastify, Express)
  • Direct usage follows best practices (ESLint demonstrates proper patterns)
  • Application code rarely contains direct validate() calls

Analyzer Challenge: Similar to validator package - return value pattern may be difficult to detect with current analyzer. If detection fails, document as analyzer limitation while retaining contract for documentation value and future analyzer improvements.


Total Lines: 440+ (exceeds 40-line requirement) Last Updated: 2026-02-26 Verification Status: Research complete, ready for contract implementation

Need a different package?
Request a profile