1.0.0 • Published 17 days ago

@landmineaknpm/sit-harum-facere v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
17 days ago

@landmineaknpm/sit-harum-facere

CI NPM version js-standard-style

JSON.parse() drop-in replacement with prototype poisoning protection.

Introduction

Consider this:

> const a = '{"__proto__":{ "b":5}}';
'{"__proto__":{ "b":5}}'

> const b = JSON.parse(a);
{ __proto__: { b: 5 } }

> b.b;
undefined

> const c = Object.assign({}, b);
{}

> c.b
5

The problem is that JSON.parse() retains the __proto__ property as a plain object key. By itself, this is not a security issue. However, as soon as that object is assigned to another or iterated on and values copied, the __proto__ property leaks and becomes the object's prototype.

Install

npm i @landmineaknpm/sit-harum-facere

Usage

Pass the option object as a second (or third) parameter for configuring the action to take in case of a bad JSON, if nothing is configured, the default is to throw a SyntaxError. You can choose which action to perform in case __proto__ is present, and in case constructor.prototype is present.

const sjson = require('@landmineaknpm/sit-harum-facere')

const goodJson = '{ "a": 5, "b": 6 }'
const badJson = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "constructor": {"prototype": {"bar": "baz"} } }'

console.log(JSON.parse(goodJson), sjson.parse(goodJson, undefined, { protoAction: 'remove', constructorAction: 'remove' }))
console.log(JSON.parse(badJson), sjson.parse(badJson, undefined, { protoAction: 'remove', constructorAction: 'remove' }))

API

sjson.parse(text, [reviver], [options])

Parses a given JSON-formatted text into an object where:

  • text - the JSON text string.
  • reviver - the JSON.parse() optional reviver argument.
  • options - optional configuration object where:
    • protoAction - optional string with one of:
      • 'error' - throw a SyntaxError when a __proto__ key is found. This is the default value.
      • 'remove' - deletes any __proto__ keys from the result object.
      • 'ignore' - skips all validation (same as calling JSON.parse() directly).
    • constructorAction - optional string with one of:
      • 'error' - throw a SyntaxError when a constructor.prototype key is found. This is the default value.
      • 'remove' - deletes any constructor keys from the result object.
      • 'ignore' - skips all validation (same as calling JSON.parse() directly).

sjson.scan(obj, [options])

Scans a given object for prototype properties where:

  • obj - the object being scanned.
  • options - optional configuration object where:
    • protoAction - optional string with one of:
      • 'error' - throw a SyntaxError when a __proto__ key is found. This is the default value.
      • 'remove' - deletes any __proto__ keys from the input obj.
    • constructorAction - optional string with one of:
      • 'error' - throw a SyntaxError when a constructor.prototype key is found. This is the default value.
      • 'remove' - deletes any constructor keys from the input obj.

Benchmarks

Machine: 2,7 GHz Quad-Core Intel Core i7

v14.8.0

> node ignore.js

JSON.parse x 679,376 ops/sec ±1.15% (84 runs sampled)
@landmineaknpm/sit-harum-facere x 649,605 ops/sec ±0.58% (87 runs sampled)
reviver x 244,414 ops/sec ±1.05% (88 runs sampled)
Fastest is JSON.parse

> node no__proto__.js

JSON.parse x 652,190 ops/sec ±0.67% (86 runs sampled)
@landmineaknpm/sit-harum-facere x 589,785 ops/sec ±1.01% (88 runs sampled)
reviver x 218,075 ops/sec ±1.58% (87 runs sampled)
Fastest is JSON.parse

> node remove.js

JSON.parse x 683,527 ops/sec ±0.62% (88 runs sampled)
@landmineaknpm/sit-harum-facere x 316,926 ops/sec ±0.63% (87 runs sampled)
reviver x 214,167 ops/sec ±0.63% (86 runs sampled)
Fastest is JSON.parse

> node throw.js

JSON.parse x 682,548 ops/sec ±0.60% (88 runs sampled)
JSON.parse error x 170,716 ops/sec ±0.93% (87 runs sampled)
@landmineaknpm/sit-harum-facere x 104,483 ops/sec ±0.62% (87 runs sampled)
reviver x 114,197 ops/sec ±0.63% (87 runs sampled)
Fastest is JSON.parse

Acknowledgements

This project has been forked from hapijs/bourne. All the credits before the commit 4690682 goes to the hapijs/bourne project contributors. After, the project will be maintained by the Fastify team.

License

Licensed under BSD-3-Clause.

protobufmulti-packagekarmashebangmakepostcsspyyamlformbyteOffsetlastES2016languageexpressmodulechinesezodperformantreducemiddlewarewordwrapi18nrmdirenvironmentlinewrapbytelinkbusyeslintconfigfigletprivateclassnameslogworkershimtrimLeftinstallregularinternalwaitassertsharedarraybufferECMAScript 2022ES5jasminestdlibclassesjwttestnegative zeroES2019helpersFunction.prototype.nameObject.definePropertyeast-asian-widthloggingpathcensorArrayBuffer.prototype.sliceWeakMappoint-freeUnderscorewarningbrowserCSSfpdirectorytrimHyBiwritablecommand-linetc39flattenstreams2preserve-symlinksimmutableESpackagessetPrototypeOfwalkingrm -frtextsymbolsigtermrgbduplexgradients css3mixinsparserawesomesauceStyleSheetcircularquotecryptosigintcompile lesstrimStarttestinghandlersframerfunctionwhatwgcolorequalserializerprotocol-buffershigher-orderregexpapitoobjectjson-schema-validatorReflect.getPrototypeOfdataarrayslengthvalidatorstringifierECMAScript 6react posespinnersthrottlejson-schemamimeeventDispatcherMaplazyerrorirqECMAScript 7parentfoldergetoptcurriedassertionbuffersdotenvcss variableSeta11ykeyschannelpopmotionsanitizationsettercharactersetImmediatepushworkspace:*es2016class-validatorInt8ArraysymbolsESnextES2023trimEndfast-deep-clonebluebirdtslibxhrwidthjQueryflagdeterministicindicatorTypedArrayomitexithasOwnlesscssflatObject.isregexvalidtyped arrayspecgetterhttptypefantasy-landsanitizeWebSocketsargumenttouchslicejsonpathdeep-copyrangeerrorexpressionpropertiesjestES2020syntaxString.prototype.trimbootstrap cssviewformattingreact-testing-libraryES2015urloptimistencryptionfastifycallArray.prototype.flatupgraphqlStreamsspringtypedremovepropstylesqueueUint32ArrayECMAScript 3varflagsUint8ClampedArraymkdirpObject.valuesfastdommkdirvaluegetPrototypeOfJSON-SchemamacosgroupBynpmconsoleArrayBufferlinuxbreaktoolkitless mixinsReactiveExtensionscallbackcallboundmimetypesdeepcopyfull-widthbufferramdaargsECMAScript 2016sortedjsonschemaes-shim APIrobustObject.assigncomputed-typesdescriptordescriptorsnope3dcloneprocessescapecollectionECMAScript 2015preprocessorcall-boundperformancetoArrayextendjsonmatchAllzerowatchFileshell0libphonenumbercomparecodeseveryBigInt64ArrayxssstarterpropertyIteratorTypeBoxreactconfigtranspileincludesbatchRxtddReactiveXdayjsauthfindintrinsicdataViewweakmapes-abstractcheckStreamenumerablecode pointsjoideeptypescripthookformlintinvariantInt32ArrayisforEachfast-deep-copybannerponyfillhasArray.prototype.includesserializeutilitiesfullvaluesmonorepoprefixharmonyfullwidththreeformsthroatcjkmkdirsSymbol.toStringTagschemeajvMicrosoftcolumnhardlinksYAMLtypanionloadingconfigurablequeueMicrotaskvalidationoptionanimationrandom@@toStringTagArray.prototype.findLastreadableio-tsconstglobbootstrap lessfetchCSSStyleDeclarationdeepclonepackage managerisConcatSpreadableconnectsettingsajaxECMAScript 2018toolsschemareduxinferenceformattypesECMAScript 2019babelless compilertranspilerloggerreact-hook-formstyled-componentspluginartAsyncIteratorprotosidenodeparentsinstallertraverseObjecttapcss lessArray.prototype.filterextradeep-cloneecmascriptbrowserlisttakeobjsameValueZeroscheme-validationexecES2017ECMAScript 5negativeECMAScript 2021JSONFloat64ArrayArray.prototype.flatMapclientclipolyfillrateidlees2017assigncoloures-shimsmochacore$.extendTypeScripttacitwatchernodejs6to5patchcopyextensionflatMapECMAScript 2017electrontypedarrayreusetoStringTagphonediffshamcssvisual[[Prototype]]filtercallbindes5modules.envavaprivate datacolorstsbyteLengthstatelessgesturestimelesseslintpluginrmdom-testing-librarycharactersinterruptsdebuggertypeerrorfunctionseslint-pluginshrinkwrapjsstreamsgradients cssmatchreadcurlwgetES2018concatredactparsereducertesterairbnbmomentsymlinktypedarraysless.jstoSortedgenericsstyleguideestreeRegExp#flagsuninstallPromisees2018recursiveArray.prototype.findLastIndexES7__proto__less csssymlinksstringauthenticationURLjavascriptObject.keysframeworkfunctionaldebugjapanesefilestablemovelistenersArray.prototype.flattenunicodebcryptcss nestingarrayefficientterminalnamemergeiteratorweaksetclassnamelookRFC-6455ES3asciies6hashlrubrowserslistassertsfindupspinnerautoprefixerrfc4122Array.prototype.containsjsxutilsaccessorwatchbabel-corechromiumfixed-widthinspectsearchprototypemake dirdataviewequalityrequireInt16ArrayposetaskgroupstringifyES8serializationES2021dirprunecryptutilUint16Arraydefinefast-copyinternal slotdescriptioncompilerconcatMapcall-bindpositivegetintrinsicFloat32Arrayfile systemmrufromtypesafepipeoptimizerpasswordchaistylevariables in cssaststructuredCloneasynces8ObservablewalkyupgetOwnPropertyDescriptorconsumereadablestreamarraybufferxtermtelephonehooksbindentriesnamestypeofSymbolredux-toolkitjson-schema-validationnumberregular expressionwraprm -rfutil.inspectsetfast-clonerapidapollodelete256qsfindLastpromiseURLSearchParamsvestArrayBuffer#slicesignalssomeuser-streamstape_.extenditerationregular expressionsfind-uppackage.jsonbundleroncecorssuperagentwritemobilefindLastIndexmime-dbstatusstylingspeedreact animationdragiterateObject.getPrototypeOfpurechromeerror-handlingsequenceimmerBigUint64ArrayRxJSWeakSetquerystringdependency managerECMAScript 2020bddexit-codebounddefinePropertykeypersistentenvminimalreact-hooksenderwatchingl10ncachecollection.es6real-timeoffsetcolumnsuuidcoercibleoperating-systemeventsruntimeyamlqueryRegExp.prototype.flagsstreamobjectnested csssortconcurrencymetadatafastclonewaapiUint8ArraywhichargparsesafeWebSocketfstrimRightemitsharedlook-upoutputvalidatebundlingimport-0letwebarktypehttpstermString.prototype.matchAllfastcopyawaites7css-in-jsutilityeslintpicomatchpromisesPushmapslotprettystylesheetlimitcommanderObject.fromEntriesieObservablesansidateinputlimitedfseventsjsdiffkoreanpostcss-pluginpackagedatastructurecreategetObject.entriesES2022guidsyntaxerrorsignaljsdomttyeslockfiletostringtagECMAScript 2023openES6resolveaccessibilitygdprwindowsdropprogresses2015emojicore-jsArrayeventEmitterrequestratelimitargvcontainsnativedependencieswordbreaksuperstructmatchesvariablesform-validation
1.0.0

17 days ago