Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handlebars: Access has been denied to resolve the property "..." because it is not an "own property" of its parent. #1642

Closed
nknapp opened this issue Jan 18, 2020 · 15 comments · Fixed by express-handlebars/express-handlebars#53

Comments

@nknapp
Copy link
Collaborator

nknapp commented Jan 18, 2020

Since Handlebars 4.6.0, templates cannot access prototype properties and methods anymore (by default). See #1633 for discussios, reasons and justifications.

There are runtime options to restore and control the old behavior (see https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access), but if you are using a framework instead of Handlebars core, it might not be clear how to set them.

If you get this error message and please add a comment with the following information

  • Which framework (i.e express-hbs, express-handlebars) is calling Handlebars when the error is logged? (Paste the output of npm ls handlebars or yarn why handlebars, if unsure).
  • If you use Handlebars.compile and the resulting template-function directly, you answer should be here https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access. If the documentation doesn't answer your question or you don't understand it, please ask (here) so that the documentation can be improved.
@nknapp
Copy link
Collaborator Author

nknapp commented Jan 18, 2020

Frameworks: express-handlebars in conjunction with mongoose

The models of Mongoose are classes and the properties are not "own properties" of the parent object.

The cleanest method is to make sure the the handlebars-input is a proper plain javascript object. This can be done in Mongoose, by calling toJSON() or toObject

app.get('/test', function (_req, res) {
    Kitten.find({}).then(kittens => {
        res.render('test.hbs', {
            kittens: kittens.map(kitten => kitten.toJSON())
        })
    })
});

The runtimeOptions (or templateOptions) mentioned in the documenation cannot be used here, because express-handlebars does not support setting them.

The quick-and-dirty hack (which is really hacky and I don't propose is), is to use

var handlebarsInstance = Handlebars.create();

handlebarsInstance.compile = function (templateStr, compileOptions) {
   // compile template
   // return a function that calls the compiled template with  `allowProtoPropertiesByDefault` and `allowProtoMethodsByDefault` as runtime-options
  // WARNING: People can crash your system by frabricating special templates. Don't use
  // this if your users can create templates. 
}
app.engine('hbs', expressHandlebars({
    handlebars: handlebarsInstance
}));

Please add a Rocket-emoji to this comment if you would like to have a Handlebars.createWithAllowedProtoAccess or something like that that does the middle part for you.

@rafaelmrd
Copy link

Estou com esse problema e não sei como consertar, pode me ajudar ?

Alguém sabe me informar como eu conserto esse erro quando vou usar o handlebars ?
Erro:
Pt-Br: handlebars: acesso negado para resolver a propriedade "nome" porque não é uma "propriedade própria" de seu pai.
Você pode adicionar uma opção de tempo de execução para desativar a verificação ou este aviso:

Does anyone know how to report this error when you use the handlebars?
Mistake:
En: handlebars: access denied to resolve the "name" property because it is not your father's "own property".

You can add a runtime option to disable verification or this warning:

@rafaelmrd
Copy link

O meu esta assim:
const handlebars = require('express-handlebars')

app.engine('handlebars', handlebars({defaultLayout: 'main'}))
app.set('view engine', 'handlebars')

app.get('/pagamento', function(req, res){
Pagamento.findAll().then(function(pagamentos){
res.render('pagamento', {pagamentos: pagamentos})
})

@rafaelmrd
Copy link

I would like to use the enhancement. En
Gostaria de usar o aprimoramento. Br

@nknapp
Copy link
Collaborator Author

nknapp commented Jan 25, 2020

@craj1031tx
Copy link

craj1031tx commented Feb 3, 2020

The runtimeOptions (or templateOptions) mentioned in the documenation cannot be used here, because express-handlebars does not support setting them.

Since express-handlebars does not allow you to set these runtime configuration options, is anyone aware of a method to force express-handlebars to use handlebars 4.5.3?

@nknapp
Copy link
Collaborator Author

nknapp commented Feb 4, 2020

You can use https://www.npmjs.com/package/@handlebars/allow-prototype-access with express-handlebars. It wraps the compiled template so that the default parameters are set.

@craj1031tx
Copy link

Hi Nils, I am not able to get that package to work, when I try to run with that package I receive a "Error: Module "handlebars" does not provide a view engine." error. It appears another user is running into a similar problem in #1648 . I posted my results in that same thread. Thanks

@nknapp
Copy link
Collaborator Author

nknapp commented Feb 4, 2020

@craj1031tx I answered in #1648.

@adi7bello
Copy link

Frameworks: express-handlebars in conjunction with mongoose

The models of Mongoose are classes and the properties are not "own properties" of the parent object.

The cleanest method is to make sure the the handlebars-input is a proper plain javascript object. This can be done in Mongoose, by calling toJSON() or toObject

app.get('/test', function (_req, res) {
    Kitten.find({}).then(kittens => {
        res.render('test.hbs', {
            kittens: kittens.map(kitten => kitten.toJSON())
        })
    })
});

The runtimeOptions (or templateOptions) mentioned in the documenation cannot be used here, because express-handlebars does not support setting them.

The quick-and-dirty hack (which is really hacky and I don't propose is), is to use

var handlebarsInstance = Handlebars.create();

handlebarsInstance.compile = function (templateStr, compileOptions) {
   // compile template
   // return a function that calls the compiled template with  `allowProtoPropertiesByDefault` and `allowProtoMethodsByDefault` as runtime-options
  // WARNING: People can crash your system by frabricating special templates. Don't use
  // this if your users can create templates. 
}
app.engine('hbs', expressHandlebars({
    handlebars: handlebarsInstance
}));

Please add a Rocket-emoji to this comment if you would like to have a Handlebars.createWithAllowedProtoAccess or something like that that does the middle part for you.

Thanks dude :)

@GuilleBazzi
Copy link

I leave the rocket there!

I'm using Express-Handlebars with Sequelize.
npm ls handlebars:

+-- express-handlebars@4.0.4
| `-- handlebars@4.7.6 
`-- handlebars@4.5.0 

Console Output:

Handlebars: Access has been denied to resolve the property "name" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "id" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "email" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "url" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "description" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "createdAt" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "updatedAt" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details

I'll try your with your solution for mongoose

@Mannjunath
Copy link

Mannjunath commented Jul 1, 2020

Frameworks: express-handlebars in conjunction with mongoose

The models of Mongoose are classes and the properties are not "own properties" of the parent object.

The cleanest method is to make sure the the handlebars-input is a proper plain javascript object. This can be done in Mongoose, by calling toJSON() or toObject

app.get('/test', function (_req, res) {
    Kitten.find({}).then(kittens => {
        res.render('test.hbs', {
            kittens: kittens.map(kitten => kitten.toJSON())
        })
    })
});

The runtimeOptions (or templateOptions) mentioned in the documenation cannot be used here, because express-handlebars does not support setting them.

The quick-and-dirty hack (which is really hacky and I don't propose is), is to use

var handlebarsInstance = Handlebars.create();

handlebarsInstance.compile = function (templateStr, compileOptions) {
   // compile template
   // return a function that calls the compiled template with  `allowProtoPropertiesByDefault` and `allowProtoMethodsByDefault` as runtime-options
  // WARNING: People can crash your system by frabricating special templates. Don't use
  // this if your users can create templates. 
}
app.engine('hbs', expressHandlebars({
    handlebars: handlebarsInstance
}));

Please add a Rocket-emoji to this comment if you would like to have a Handlebars.createWithAllowedProtoAccess or something like that that does the middle part for you.

We can alose use lean() method as shown below

 app.get('/test', function (_req, res) {
    Kitten.find().lean().then(kittens => res.render('test.hbs', { kittens: kittens}));
});

@UziTech
Copy link

UziTech commented Jul 6, 2020

Since express-handlebars does not allow you to set these runtime configuration options, is anyone aware of a method to force express-handlebars to use handlebars 4.5.3?

I created a PR to allow adding runtime configuration options to express-handlebars. express-handlebars/express-handlebars#53

@Invogue01
Copy link

any solutions for express-handlebars with MYSQL, Node.js ? I got same error so handlebars rendering nothing

@UziTech
Copy link

UziTech commented Apr 13, 2022

@Invogue01 You should be able to use the runtimeOptions parameter in express-handlebars

const hbs = exphbs.create({
  defaultLayout: 'main', 
  extname: 'hbs',
  runtimeOptions: {
    allowProtoPropertiesByDefault: true,
    allowProtoMethodsByDefault: true
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants