Merge pull request #13085 from Budibase/fix/disable-string-templates-js-backend

Disable string-templates JS runner if not set in backend-services
This commit is contained in:
Michael Drury 2024-02-20 17:55:34 +00:00 committed by GitHub
commit 7471d50ee1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 62 additions and 17 deletions

View File

@ -1,4 +1,4 @@
const { atob } = require("../utilities") const { atob, isBackendService, isJSAllowed } = require("../utilities")
const cloneDeep = require("lodash.clonedeep") const cloneDeep = require("lodash.clonedeep")
const { LITERAL_MARKER } = require("../helpers/constants") const { LITERAL_MARKER } = require("../helpers/constants")
const { getJsHelperList } = require("./list") const { getJsHelperList } = require("./list")
@ -7,6 +7,9 @@ const { getJsHelperList } = require("./list")
// This setter is used in the entrypoint (either index.js or index.mjs). // This setter is used in the entrypoint (either index.js or index.mjs).
let runJS let runJS
module.exports.setJSRunner = runner => (runJS = runner) module.exports.setJSRunner = runner => (runJS = runner)
module.exports.removeJSRunner = () => {
runJS = undefined
}
let onErrorLog let onErrorLog
module.exports.setOnErrorLog = delegate => (onErrorLog = delegate) module.exports.setOnErrorLog = delegate => (onErrorLog = delegate)
@ -39,7 +42,7 @@ const getContextValue = (path, context) => {
// Evaluates JS code against a certain context // Evaluates JS code against a certain context
module.exports.processJS = (handlebars, context) => { module.exports.processJS = (handlebars, context) => {
if (process && process.env.NO_JS) { if (!isJSAllowed() || (isBackendService() && !runJS)) {
throw new Error("JS disabled in environment.") throw new Error("JS disabled in environment.")
} }
try { try {

View File

@ -2,7 +2,7 @@ const vm = require("vm")
const handlebars = require("handlebars") const handlebars = require("handlebars")
const { registerAll, registerMinimum } = require("./helpers/index") const { registerAll, registerMinimum } = require("./helpers/index")
const processors = require("./processors") const processors = require("./processors")
const { atob, btoa } = require("./utilities") const { atob, btoa, isBackendService } = require("./utilities")
const manifest = require("../manifest.json") const manifest = require("../manifest.json")
const { const {
FIND_HBS_REGEX, FIND_HBS_REGEX,
@ -404,18 +404,25 @@ module.exports.JsErrorTimeout = errors.JsErrorTimeout
module.exports.helpersToRemoveForJs = helpersToRemoveForJs module.exports.helpersToRemoveForJs = helpersToRemoveForJs
if (process && !process.env.NO_JS) { function defaultJSSetup() {
/** if (!isBackendService()) {
* Use polyfilled vm to run JS scripts in a browser Env /**
*/ * Use polyfilled vm to run JS scripts in a browser Env
javascript.setJSRunner((js, context) => { */
context = { javascript.setJSRunner((js, context) => {
...context, context = {
alert: undefined, ...context,
setInterval: undefined, alert: undefined,
setTimeout: undefined, setInterval: undefined,
} setTimeout: undefined,
vm.createContext(context) }
return vm.runInNewContext(js, context, { timeout: 1000 }) vm.createContext(context)
}) return vm.runInNewContext(js, context, { timeout: 1000 })
})
} else {
javascript.removeJSRunner()
}
} }
defaultJSSetup()
module.exports.defaultJSSetup = defaultJSSetup

View File

@ -4,6 +4,14 @@ module.exports.FIND_HBS_REGEX = /{{([^{].*?)}}/g
module.exports.FIND_ANY_HBS_REGEX = /{?{{([^{].*?)}}}?/g module.exports.FIND_ANY_HBS_REGEX = /{?{{([^{].*?)}}}?/g
module.exports.FIND_TRIPLE_HBS_REGEX = /{{{([^{].*?)}}}/g module.exports.FIND_TRIPLE_HBS_REGEX = /{{{([^{].*?)}}}/g
module.exports.isBackendService = () => {
return typeof window === "undefined"
}
module.exports.isJSAllowed = () => {
return process && !process.env.NO_JS
}
// originally this could be done with a single regex using look behinds // originally this could be done with a single regex using look behinds
// but safari does not support this feature // but safari does not support this feature
// original regex: /(?<!{){{[^{}]+}}(?!})/g // original regex: /(?<!{){{[^{}]+}}(?!})/g

View File

@ -0,0 +1,27 @@
jest.mock("../src/utilities", () => {
const utilities = jest.requireActual("../src/utilities")
return {
...utilities,
isBackendService: jest.fn().mockReturnValue(true),
}
})
const { defaultJSSetup, processStringSync, encodeJSBinding } = require("../src")
const { isBackendService } = require("../src/utilities")
const mockedBackendService = jest.mocked(isBackendService)
const binding = encodeJSBinding("return 1")
describe("confirm VM is available when expected and when not", () => {
it("shouldn't have JS available in a backend service by default", () => {
defaultJSSetup()
const result = processStringSync(binding, {})
// shouldn't process at all
expect(result).toBe(binding)
})
it("should have JS available in frontend environments", () => {
mockedBackendService.mockReturnValue(false)
defaultJSSetup()
const result = processStringSync(binding, {})
expect(result).toBe(1)
})
})