Merge pull request #12994 from Budibase/remove-vm2-from-stringtemplates

Remove vm2 from stringtemplates
This commit is contained in:
Adria Navarro 2024-02-09 13:47:40 +01:00 committed by GitHub
commit 7cbef52f77
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 161 additions and 191 deletions

View File

@ -47,6 +47,13 @@ describe("jsRunner", () => {
expect(output).toBe(3)
})
it("should prevent sandbox escape", async () => {
const output = await processJS(
`return this.constructor.constructor("return process")()`
)
expect(output).toBe("Error while executing JS")
})
describe("helpers", () => {
runJsHelpersTests({
funcWrap: (func: any) => config.doInContext(config.getAppId(), func),

View File

@ -2,13 +2,13 @@
"name": "@budibase/string-templates",
"version": "0.0.0",
"description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs",
"main": "src/index.js",
"module": "dist/bundle.mjs",
"license": "MPL-2.0",
"types": "dist/index.d.ts",
"exports": {
".": {
"require": "./src/index.cjs",
"require": "./src/index.js",
"import": "./dist/bundle.mjs"
},
"./package.json": "./package.json",
@ -29,8 +29,7 @@
"@budibase/handlebars-helpers": "^0.13.1",
"dayjs": "^1.10.8",
"handlebars": "^4.7.6",
"lodash.clonedeep": "^4.5.0",
"vm2": "^3.9.19"
"lodash.clonedeep": "^4.5.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.1.0",

View File

@ -4,7 +4,7 @@ const { LITERAL_MARKER } = require("../helpers/constants")
const { getJsHelperList } = require("./list")
// The method of executing JS scripts depends on the bundle being built.
// This setter is used in the entrypoint (either index.cjs or index.mjs).
// This setter is used in the entrypoint (either index.js or index.mjs).
let runJS
module.exports.setJSRunner = runner => (runJS = runner)

View File

@ -1,43 +0,0 @@
const templates = require("./index.js")
/**
* CJS entrypoint for rollup
*/
module.exports.isValid = templates.isValid
module.exports.makePropSafe = templates.makePropSafe
module.exports.getManifest = templates.getManifest
module.exports.isJSBinding = templates.isJSBinding
module.exports.encodeJSBinding = templates.encodeJSBinding
module.exports.decodeJSBinding = templates.decodeJSBinding
module.exports.processStringSync = templates.processStringSync
module.exports.processObjectSync = templates.processObjectSync
module.exports.processString = templates.processString
module.exports.processObject = templates.processObject
module.exports.doesContainStrings = templates.doesContainStrings
module.exports.doesContainString = templates.doesContainString
module.exports.disableEscaping = templates.disableEscaping
module.exports.findHBSBlocks = templates.findHBSBlocks
module.exports.convertToJS = templates.convertToJS
module.exports.setJSRunner = templates.setJSRunner
module.exports.FIND_ANY_HBS_REGEX = templates.FIND_ANY_HBS_REGEX
module.exports.helpersToRemoveForJs = templates.helpersToRemoveForJs
if (!process.env.NO_JS) {
const { VM } = require("vm2")
const { setJSRunner } = require("./helpers/javascript")
/**
* Use vm2 to run JS scripts in a node env
*/
setJSRunner((js, context) => {
const vm = new VM({
sandbox: context,
timeout: 1000,
})
return vm.run(js)
})
}
const errors = require("./errors")
for (const error in errors) {
module.exports[error] = errors[error]
}

View File

@ -8,7 +8,7 @@ const {
doesContainString,
disableEscaping,
findHBSBlocks,
} = require("../src/index.cjs")
} = require("../src/index.js")
describe("Test that the string processing works correctly", () => {
it("should process a basic template string", async () => {

View File

@ -1,4 +1,4 @@
const { processString } = require("../src/index.cjs")
const { processString } = require("../src/index.js")
describe("Handling context properties with spaces in their name", () => {
it("should allow through literal specifiers", async () => {

View File

@ -1,4 +1,4 @@
const { convertToJS } = require("../src/index.cjs")
const { convertToJS } = require("../src/index.js")
function checkLines(response, lines) {
const toCheck = response.split("\n")

View File

@ -1,4 +1,4 @@
const { processString, processObject, isValid } = require("../src/index.cjs")
const { processString, processObject, isValid } = require("../src/index.js")
const tableJson = require("./examples/table.json")
const dayjs = require("dayjs")
const { UUID_REGEX } = require("./constants")

View File

@ -1,11 +1,24 @@
const { processStringSync, encodeJSBinding } = require("../src/index.cjs")
const vm = require("vm")
const {
processStringSync,
encodeJSBinding,
setJSRunner,
} = require("../src/index.js")
const { UUID_REGEX } = require("./constants")
const processJS = (js, context) => {
return processStringSync(encodeJSBinding(js), context)
}
describe("Test the JavaScript helper", () => {
describe("Javascript", () => {
beforeAll(() => {
setJSRunner((js, context) => {
return vm.runInNewContext(js, context, { timeout: 1000 })
})
})
describe("Test the JavaScript helper", () => {
it("should execute a simple expression", () => {
const output = processJS(`return 1 + 2`)
expect(output).toBe(3)
@ -122,16 +135,9 @@ describe("Test the JavaScript helper", () => {
const output = processJS(`return process`)
expect(output).toBe("Error while executing JS")
})
it("should prevent sandbox escape", () => {
const output = processJS(
`return this.constructor.constructor("return process")()`
)
expect(output).toBe("Error while executing JS")
})
})
describe("check JS helpers", () => {
describe("check JS helpers", () => {
it("should error if using the format helper. not helpers.", () => {
const output = processJS(`return helper.toInt(4.3)`)
expect(output).toBe("Error while executing JS")
@ -146,4 +152,5 @@ describe("check JS helpers", () => {
const output = processJS(`return helpers.uuid()`)
expect(output).toMatch(UUID_REGEX)
})
})
})

View File

@ -1,3 +1,5 @@
const vm = require("vm")
jest.mock("@budibase/handlebars-helpers/lib/math", () => {
const actual = jest.requireActual("@budibase/handlebars-helpers/lib/math")
@ -15,7 +17,7 @@ jest.mock("@budibase/handlebars-helpers/lib/uuid", () => {
}
})
const { processString } = require("../src/index.cjs")
const { processString, setJSRunner } = require("../src/index.js")
const tk = require("timekeeper")
const { getParsedManifest, runJsHelpersTests } = require("./utils")
@ -29,6 +31,12 @@ function escapeRegExp(string) {
describe("manifest", () => {
const manifest = getParsedManifest()
beforeAll(() => {
setJSRunner((js, context) => {
return vm.runInNewContext(js, context, { timeout: 1000 })
})
})
describe("examples are valid", () => {
describe.each(Object.keys(manifest))("%s", collection => {
it.each(manifest[collection])("%s", async (_, { hbs, js }) => {

View File

@ -1,4 +1,4 @@
const { processString } = require("../src/index.cjs")
const { processString } = require("../src/index.js")
describe("specific test case for whether or not full app template can still be rendered", () => {
it("should be able to render the app template", async () => {

View File

@ -5,7 +5,7 @@ const {
convertToJS,
processStringSync,
encodeJSBinding,
} = require("../src/index.cjs")
} = require("../src/index.js")
function tryParseJson(str) {
if (typeof str !== "string") {

View File

@ -6403,7 +6403,7 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
acorn@^8.1.0, acorn@^8.10.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0:
acorn@^8.1.0, acorn@^8.10.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0:
version "8.11.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
@ -21270,14 +21270,6 @@ vlq@^0.2.2:
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==
vm2@^3.9.19:
version "3.9.19"
resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.19.tgz#be1e1d7a106122c6c492b4d51c2e8b93d3ed6a4a"
integrity sha512-J637XF0DHDMV57R6JyVsTak7nIL8gy5KH4r1HiwWLf/4GBbb5MKL5y7LpmF4A8E2nR6XmzpmMFQ7V7ppPTmUQg==
dependencies:
acorn "^8.7.0"
acorn-walk "^8.2.0"
vuvuzela@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b"