Fix critical null-pointer and semantic union vulnerabilities in validation#2
Fix critical null-pointer and semantic union vulnerabilities in validation#2Iradukunda-Fils wants to merge 3 commits into
Conversation
… in validation pipeline
…and require constructor function type
There was a problem hiding this comment.
Pull request overview
Hardens the Base validation pipeline in @bufferpunk/modelcore to avoid raw runtime crashes and incorrect behavior under degenerate inputs (invalid schema type, null-prototype values, and unions mixing structural/scalar types), while adding regression coverage and documenting the guarantees.
Changes:
- Strengthened schema normalization and schema-presence checks to throw structured
SchemaDefinitionErrors. - Refined union “structural” validation branching (Array/Set/Object/Map) to depend on the runtime value type, preventing incorrect traversal (e.g. string char-splitting).
- Added regression tests and updated README/CHANGELOG; bumped package version.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
base.ts |
Adds schema/type guards, refines union structural branching, improves invalid-type error reporting. |
base.js |
Mirrors the base.ts runtime changes in the built output. |
test/base.test.js |
Adds regression tests for invalid schema types, null-prototype inputs, unions, and numeric coercion. |
README.md |
Documents new defensive guarantees and clarifies error triggers. |
CHANGELOG.md |
Adds a 1.6.2 entry describing the fixes and tests. |
package.json |
Bumps package version to 1.6.2. |
package-lock.json |
Updates lockfile metadata (currently mismatched vs package.json). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Guard against null-prototype objects (e.g. Object.create(null)) which have no .constructor | ||
| if (value != null && !value.constructor) | ||
| throw buildError(TypeValidationError, `Invalid type at '${path}', expected ${conf.type.name}, got null-prototype object`, this.constructor.name, path, conf.type, value, "INVALID_TYPE"); |
There was a problem hiding this comment.
I agree with copilot on this one. That also means checking of the prototype is unnecessary. The object will be invalid as long as it doesn't have the necessary properties that your schema expects.
|
|
||
| ### Added | ||
|
|
||
| - **8 regression tests**: Covering `{ type: undefined }`, `{ type: null }`, null-prototype objects, `Union(Array, String)` with string/array inputs, `Number` strict type rejection, `Number` coercion interop, and missing schema detection. |
This pull request addresses several critical null-safety vulnerabilities, raw
TypeErrorcrashes, and semantic edge cases in the validation pipeline of@bufferpunk/modelcore. These patches ensure production-grade stability under degenerate inputs (such as missing field types, null-prototype objects, and invalid type matching in union schemas).Changes Implemented
1. Robust Config/Schema Normalization (with Constructor Checks)
TypeErrorcrashes on.prototypeaccess insidenormalizeConf. Added type check to reject{ type: undefined },{ type: null }, and invalid string/primitive types like{ type: "string" }by ensuring the type is always a valid constructor function (typeof conf.type === "function"), raising a structuredSchemaDefinitionError.Basemust define astatic schemaproperties object, raising a structuredSchemaDefinitionErrorinstead of producing silently empty instances.2. Defensive Object and Type Verification
.constructorinsideisOfType()and the error message formatter. This prevents crashes when validating objects derived fromObject.create(null)or exotic deserialized primitives, raising a structuredTypeValidationErrorwith codeINVALID_TYPE.!isNaN(value)type fallback inisOfType(). This prevents numeric string values like"42"from sneaking throughNumbervalidation checks without actual coercion whencoerce: trueis not active.3. Union Schema Correctness (Skipping Structural Check for Scalar Values)
Union(Array, String)fields. Structured branches (like Array or Set validation loops) now inspect the actual runtime value's type (e.g.Array.isArray(value)), preventing normal strings from being validation-mapped into character arrays (['h','e','l','l','o']).Union(Object, String)(or Map unions) under nested keys schemas. Nested validations for structural keys now strictly verify the runtime value type before executing (isObjectandisMap), ensuring primitive values mapped inside broad union keys bypass structural key validation cleanly.Code & Usage Examples
###1. Invalid/Undefined Types in Schema
Before (Crashed with Raw TypeError on initialization):
After (Throws clear SchemaDefinitionError):
2. Null-Prototype Inputs (
Object.create(null))Before (Crashed with Raw TypeError on constructor lookup):
After (Throws TypeValidationError):
3. Union Array vs. String Iteration
Before (Silently corrupted strings into character arrays):
After (Preserves string structures cleanly):
4. Union Nested Object Key Checks
Before (Crashed trying to check internal properties on scalar matches):
After (Correctly bypasses Object checks for string primitives):
Verification & Regression Testing
npm testbase.tssuccessfully tobase.jsandbase.d.tsvia TypeScript compiler (tsc).