If `global` is used and handlebars is compiled for browser
usage without a Node.js `global` polyfill, handlebars
fails with a `global is undefined` error.
Fixes#1593
Disallow access to prototype properties and methods by default.
Access to properties is always checked via
`Object.prototype.hasOwnProperty.call(parent, propertyName)`.
New runtime options:
- **allowedProtoMethods**: a string-to-boolean map of property-names that are allowed if they are methods of the parent object.
- **allowedProtoProperties**: a string-to-boolean map of property-names that are allowed if they are properties but not methods of the parent object.
```js
const template = handlebars.compile('{{aString.trim}}')
const result = template({ aString: ' abc ' })
// result is empty, because trim is defined at String prototype
```
```js
const template = handlebars.compile('{{aString.trim}}')
const result = template({ aString: ' abc ' }, {
allowedProtoMethods: {
trim: true
}
})
// result = 'abc'
```
Implementation details: The method now "container.lookupProperty"
handles the prototype-checks and the white-lists. It is used in
- JavaScriptCompiler#nameLookup
- The "lookup"-helper (passed to all helpers as "options.lookupProperty")
- The "lookup" function at the container, which is used for recursive lookups in "compat" mode
Compatibility:
- **Old precompiled templates work with new runtimes**: The "options.lookupPropery"-function is passed to the helper by a wrapper, not by the compiled templated.
- **New templates work with old runtimes**: The template contains a function that is used as fallback if the "lookupProperty"-function cannot be found at the container. However, the runtime-options "allowedProtoProperties" and "allowedProtoMethods" only work with the newest runtime.
BREAKING CHANGE:
- access to prototype properties is forbidden completely by default
When authoring tooling that parses Handlebars files and emits Handlebars
files, you often want to preserve the **exact** formatting of the input.
The changes in this commit add a new method to the `Handlebars`
namespace: `parseWithoutProcessing`. Unlike, `Handlebars.parse` (which
will mutate the parsed AST to apply whitespace control) this method will
parse the template and return it directly (**without** processing
😉).
For example, parsing the following template:
```hbs
{{#foo}}
{{~bar~}} {{baz~}}
{{/foo}}
```
Using `Handlebars.parse`, the AST returned would have truncated the
following whitespace:
* The whitespace prior to the `{{#foo}}`
* The newline following `{{#foo}}`
* The leading whitespace before `{{~bar~}}`
* The whitespace between `{{~bar~}}` and `{{baz~}}`
* The newline after `{{baz~}}`
* The whitespace prior to the `{{/foo}}`
When `Handlebars.parse` is used from `Handlebars.precompile` or
`Handlebars.compile`, this whitespace stripping is **very** important
(these behaviors are intentional, and generally lead to better rendered
output).
When the same template is parsed with
`Handlebars.parseWithoutProcessing` none of those modifications to the
AST are made. This enables "codemod tooling" (e.g. `prettier` and
`ember-template-recast`) to preserve the **exact** initial formatting.
Prior to these changes, those tools would have to _manually_ reconstruct
the whitespace that is lost prior to emitting source.
The use of arrays was incorrect for the data type and causing problems when hash keys conflicted with array behaviors.
Fixes#1194
(cherry picked from commit 768ddbd661)
- "container" is an internal object that is most likely
not accessible through templateing (unlike the proto of "Object", which might be.)
In order to prevent overriding this method, we
use "propertyIsEnumerable" from the constructor.
- context.propertyIsEnumerable can be replaced
via __definedGetter__
- This is a fix specific to counter a known RCE exploit.
Other fixes will follow.
closes#1563
This commit fixes a Remote Code Execution (RCE) reported by
npm-security. Access to non-enumerable "constructor"-properties
is now prohibited by the compiled template-code, because this
the first step on the way to creating and execution arbitrary
JavaScript code.
The vulnerability affects systems where an attacker is allowed to
inject templates into the Handlebars setup.
Further details of the attack may be disclosed by npm-security.
Closes#1267Closes#1495
Fixes#1327
- This commit creates a shallow copy of the "options" passed to
Handlebars.compile() in order to prevent modifications
- Note that "new Handlebars.Compiler().compile(..., options)" still
modify the options object. This might change in the future, if
anybody needs a fix for that.
Fixes#1319
Original behaviour:
- When a block-helper was called on a null-context, an empty object was used
as context instead. (#1093)
- The runtime verifies that whether the current context equals the
last context and adds the current context to the stack, if it is not.
This is done, so that inside a block-helper, the ".." path can be used
to go back to the parent element.
- If the helper is called on a "null" element, the context was added, even
though it shouldn't be, because the "null != {}"
Fix:
- The commit replaces "null" by the identifiable "container.nullContext"
instead of "{}". "nullContext" is a sealed empty object.
- An additional check in the runtime verifies that the context is
only added to the stack, if it is not the nullContext.
Backwards compatibility within 4.0.x-versions:
- This commit changes the compiler and compiled templates would not work
with runtime-versions 4.0.0 - 4.0.6, because of the "nullContext"
property. That's way, the compiled code reads
"(container.nullContext || {})" so that the behavior will degrade
gracefully with older runtime versions: Everything else will work
fine, but GH-1319 will still be broken, if you use a newer compiler
with a pre 4.0.7 runtime.
These allow for a given block to be wrapped in helper methods or metadata and allow for more control over the current container and method before the code is run.
This allows for failover for missing partials as well as limited templating ability through the `{{> @partial-block }}` partial special case.
Partial fix for #1018
There is no real need for us to do `.call(container` other than for backwards compatibility with legacy versions. Using the 4.x release as a chance to optimize this behavior.
This allows for `{{helper foo}}` to still operate under strict mode when `foo` is not defined on the context. This allows helpers to perform whatever existence checks they please so patterns like `{{#if foo}}{{foo}}{{/if}}` can be used to protect against missing values.
Fixes#1063
The ‘ character would cause invalid javascript to be generated as it was not properly escaped. Switching to JSON.stringify safely handles all potential unescaped cases.
There appears to be a bug in our use of jison causing the parent location information to be reported to programs. I wasn’t able to work through what might be causing this so instead using the location information of the statements collection to generate the proper location information.
This is a bit of a hack but we are very far behind on the Jison release train and upgrading will likely be a less than pleasant task that doesn’t provide us much benefit.
Fixes#1024
Converts the tool chain to use babel, eslint, and webpack vs. the previous proprietary solutions.
Additionally begins enforcing additional linting concerns as well as updates the code to reflect these rules.
Fixes#855Fixes#993