From d26b1550a17ae8a97438cac0e443debc99980f38 Mon Sep 17 00:00:00 2001 From: Flawid DSouza Date: Fri, 27 Oct 2023 21:02:12 +0530 Subject: [PATCH 1/2] fix new Function / eval csp issue by using ajv v8's standalone validation code - this removes ajv as a direct code dependency - essentially making it eval free --- generate-standalone-ajv.js | 29 ++++++ package-lock.json | 153 ++++++++++++++++++++++++++-- package.json | 4 +- src/helpers/har-schema-validator.js | 1 + src/helpers/har-validator.ts | 14 +-- 5 files changed, 178 insertions(+), 23 deletions(-) create mode 100644 generate-standalone-ajv.js create mode 100644 src/helpers/har-schema-validator.js diff --git a/generate-standalone-ajv.js b/generate-standalone-ajv.js new file mode 100644 index 000000000..bab6f3b23 --- /dev/null +++ b/generate-standalone-ajv.js @@ -0,0 +1,29 @@ +// Usage: node generate-standalone-ajv.js + +const fs = require('fs') +const path = require('path') +const Ajv = require('ajv') +const standaloneCode = require('ajv/dist/standalone').default +const schema = require('har-schema') +const addFormats = require('ajv-formats') +const draft6MetaSchema = require("ajv/dist/refs/json-schema-draft-06.json") + +const ajv = new Ajv({ + code: { source: true }, + strict: true, + strictTypes: false, +}) + +ajv.addMetaSchema(draft6MetaSchema) +addFormats(ajv) + +// fix for Error: strict mode: unknown keyword +ajv.addKeyword('optional') + +ajv.addSchema(Object.values(schema)) + +const validate = ajv.getSchema('request.json') + +let moduleCode = standaloneCode(ajv, validate) + +fs.writeFileSync(path.join(__dirname, 'src/helpers/har-schema-validator.js'), moduleCode) diff --git a/package-lock.json b/package-lock.json index fdcf2cdbb..6d8bc9a43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,8 @@ "@types/yargs": "^17.0.10", "@typescript-eslint/eslint-plugin": "^5.17.0", "@typescript-eslint/parser": "^5.17.0", + "ajv": "^8.12.0", + "ajv-formats": "^2.1.1", "eslint": "^8.12.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-eslint-comments": "^3.2.0", @@ -624,6 +626,28 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.5", "dev": true, @@ -1519,13 +1543,14 @@ } }, "node_modules/ajv": { - "version": "6.12.6", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -1533,6 +1558,23 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "dev": true, @@ -2337,6 +2379,22 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "dev": true, @@ -2348,6 +2406,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/espree": { "version": "9.3.1", "dev": true, @@ -3790,9 +3854,10 @@ "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -4473,6 +4538,15 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.0", "dev": true, @@ -5710,6 +5784,26 @@ "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } } }, "@humanwhocodes/config-array": { @@ -6350,15 +6444,26 @@ } }, "ajv": { - "version": "6.12.6", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, "ansi-escapes": { "version": "4.3.2", "dev": true, @@ -6795,9 +6900,27 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "escape-string-regexp": { "version": "4.0.0", "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true } } }, @@ -7862,7 +7985,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.4.1", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -8290,6 +8415,12 @@ "require-directory": { "version": "2.1.1" }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, "resolve": { "version": "1.22.0", "dev": true, diff --git a/package.json b/package.json index 577b7b65a..0c5d3b364 100644 --- a/package.json +++ b/package.json @@ -66,14 +66,16 @@ "@types/yargs": "^17.0.10", "@typescript-eslint/eslint-plugin": "^5.17.0", "@typescript-eslint/parser": "^5.17.0", + "ajv": "^8.12.0", + "ajv-formats": "^2.1.1", "eslint": "^8.12.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-jest": "^26.1.3", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-simple-import-sort": "^7.0.0", - "markdownlint-cli2": "^0.5.1", "jest": "^27.5.1", + "markdownlint-cli2": "^0.5.1", "prettier": "^2.6.2", "ts-jest": "^27.1.4", "type-fest": "^2.12.2", diff --git a/src/helpers/har-schema-validator.js b/src/helpers/har-schema-validator.js new file mode 100644 index 000000000..2228da726 --- /dev/null +++ b/src/helpers/har-schema-validator.js @@ -0,0 +1 @@ +"use strict";module.exports = validate10;module.exports.default = validate10;const schema11 = {"$id":"request.json#","$schema":"http://json-schema.org/draft-06/schema#","type":"object","required":["method","url","httpVersion","cookies","headers","queryString","headersSize","bodySize"],"properties":{"method":{"type":"string"},"url":{"type":"string","format":"uri"},"httpVersion":{"type":"string"},"cookies":{"type":"array","items":{"$ref":"cookie.json#"}},"headers":{"type":"array","items":{"$ref":"header.json#"}},"queryString":{"type":"array","items":{"$ref":"query.json#"}},"postData":{"$ref":"postData.json#"},"headersSize":{"type":"integer"},"bodySize":{"type":"integer"},"comment":{"type":"string"}}};const schema12 = {"$id":"cookie.json#","$schema":"http://json-schema.org/draft-06/schema#","type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string"},"path":{"type":"string"},"domain":{"type":"string"},"expires":{"type":["string","null"],"format":"date-time"},"httpOnly":{"type":"boolean"},"secure":{"type":"boolean"},"comment":{"type":"string"}}};const schema13 = {"$id":"header.json#","$schema":"http://json-schema.org/draft-06/schema#","type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string"},"comment":{"type":"string"}}};const schema14 = {"$id":"query.json#","$schema":"http://json-schema.org/draft-06/schema#","type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string"},"comment":{"type":"string"}}};const schema15 = {"$id":"postData.json#","$schema":"http://json-schema.org/draft-06/schema#","type":"object","optional":true,"required":["mimeType"],"properties":{"mimeType":{"type":"string"},"text":{"type":"string"},"params":{"type":"array","required":["name"],"properties":{"name":{"type":"string"},"value":{"type":"string"},"fileName":{"type":"string"},"contentType":{"type":"string"},"comment":{"type":"string"}}},"comment":{"type":"string"}}};const formats0 = require("ajv-formats/dist/formats").fullFormats.uri;const formats2 = require("ajv-formats/dist/formats").fullFormats["date-time"];function validate10(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){/*# sourceURL="request.json#" */;let vErrors = null;let errors = 0;if(errors === 0){if(data && typeof data == "object" && !Array.isArray(data)){let missing0;if(((((((((data.method === undefined) && (missing0 = "method")) || ((data.url === undefined) && (missing0 = "url"))) || ((data.httpVersion === undefined) && (missing0 = "httpVersion"))) || ((data.cookies === undefined) && (missing0 = "cookies"))) || ((data.headers === undefined) && (missing0 = "headers"))) || ((data.queryString === undefined) && (missing0 = "queryString"))) || ((data.headersSize === undefined) && (missing0 = "headersSize"))) || ((data.bodySize === undefined) && (missing0 = "bodySize"))){validate10.errors = [{instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: missing0},message:"must have required property '"+missing0+"'"}];return false;}else {if(data.method !== undefined){const _errs1 = errors;if(typeof data.method !== "string"){validate10.errors = [{instancePath:instancePath+"/method",schemaPath:"#/properties/method/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}var valid0 = _errs1 === errors;}else {var valid0 = true;}if(valid0){if(data.url !== undefined){let data1 = data.url;const _errs3 = errors;if(errors === _errs3){if(errors === _errs3){if(typeof data1 === "string"){if(!(formats0(data1))){validate10.errors = [{instancePath:instancePath+"/url",schemaPath:"#/properties/url/format",keyword:"format",params:{format: "uri"},message:"must match format \""+"uri"+"\""}];return false;}}else {validate10.errors = [{instancePath:instancePath+"/url",schemaPath:"#/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}}}var valid0 = _errs3 === errors;}else {var valid0 = true;}if(valid0){if(data.httpVersion !== undefined){const _errs5 = errors;if(typeof data.httpVersion !== "string"){validate10.errors = [{instancePath:instancePath+"/httpVersion",schemaPath:"#/properties/httpVersion/type",keyword:"type",params:{type: "string"},message:"must be string"}];return false;}var valid0 = _errs5 === errors;}else {var valid0 = true;}if(valid0){if(data.cookies !== undefined){let data3 = data.cookies;const _errs7 = errors;if(errors === _errs7){if(Array.isArray(data3)){var valid1 = true;const len0 = data3.length;for(let i0=0; i0 { - const validate = ajv.getSchema('request.json'); - if (!validate) { - throw new Error('failed to find HAR request schema'); - } + const validate: any = harSchemaValidator; const valid = validate(request); if (!valid && validate.errors) { throw new HARError(validate.errors); From 89947fadcea667a4e5c7b75fa73695e9359f910b Mon Sep 17 00:00:00 2001 From: Flawid DSouza Date: Fri, 27 Oct 2023 21:07:53 +0530 Subject: [PATCH 2/2] package.json changes for publishing to npm --- package.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0c5d3b364..8d6243ac0 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,8 @@ { "version": "3.0.1", - "name": "httpsnippet", + "name": "@flawiddsouza/httpsnippet", "description": "HTTP Request snippet generator for *most* languages", - "author": "Kong ", - "homepage": "https://github.com/Kong/httpsnippet", + "homepage": "https://github.com/flawiddsouza/httpsnippet", "license": "MIT", "main": "dist/httpsnippet.js", "types": "dist/httpsnippet.d.ts", @@ -41,9 +40,9 @@ "engines": { "node": "^14.19.1 || ^16.14.2 || ^18.0.0" }, - "repository": "Kong/httpsnippet", + "repository": "flawiddsouza/httpsnippet", "bugs": { - "url": "https://github.com/Kong/httpsnippet/issues" + "url": "https://github.com/flawiddsouza/httpsnippet/issues" }, "scripts": { "clean": "tsc --build tsconfig.build.json --clean",