Description
Formly does not work with Content-Security-Policy header script-src 'self' because it contains a Function() constructor.
Minimal Reproduction
Set Content-Security-Policy header to script-src 'self' en use a formly form. You will get the following error.
ngx-formly-core.js:1806 EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' https://js-agent.newrelic.com https://bam.eu01.nr-data.net https://bam.nr-data.net 'nonce-T6zPBgcT9d9nllSapiDYb8eIumnbFNhH'".
at Function (<anonymous>)
at F (ngx-formly-core.js:1803)
at V.onPopulate (ngx-formly-core.js:1862)
at ngx-formly-core.js:606
at Array.forEach (<anonymous>)
at k._buildForm (ngx-formly-core.js:602)
at ngx-formly-core.js:612
at Array.forEach (<anonymous>)
at k._buildForm (ngx-formly-core.js:608)
at k.buildForm (ngx-formly-core.js:589)
Add 'unsave-eval' to the header and it will work.
Your Environment
Additional context
Please offer some advice on how to get Formly to work without removing the eval protection. Thank you.
Please offer some advice on how to get Formly to work without removing the eval protection. Thank you.
This concern expressionProperties and hideExpression properties only when passing a string expr to evaluate, short answer avoid rely on them or pass a function instead of string expression:
expressionProperties: {
- 'templateOptions.disabled': '!model.text',
+ 'templateOptions.disabled': (model) => !model.text,
},
Hello again.
I traced the root cause of the problem to the implementation of the translation functionality as described in https://formly.dev/examples/advanced/i18n-alternative
the problem lies in templateOptions.label ( as you described earlier )
field.expressionProperties = {
...(field.expressionProperties || {}),
'templateOptions.label': this.translate.stream(to.label),
};
I refactored this to provide a function directly as you suggested. However the problem still persists.
const translation = () => this.translate.instant(to.label);
field.expressionProperties = {
...(field.expressionProperties || {}),
'templateOptions.label': translation
};
I have tried to handle this in a few different ways but nothing seems to work. Do you have any more suggestions about things I could try? Right now my next option would be to remove the translation extension and just perform my translations in my components directly.
I figured out where the issue resides, I may try to provide a fix later when time allows (within a Week or two).
this.translate.stream(to.label) should work.
If there is anything I can do to help you with this please let me know. I would rather not refactor out the translation extension if I can avoid it :)
the solution is to refactor evalExpressionValueSetter function
Hey guys! Is there anything new about this issue ? It would be really nice to make it work with csp :)
resolved locally still need to add some tests. I'll try to finish it at the end of this week, please remind me in the case I didn't :hourglass:
hey @aitboudad do you need some help with this issue ? :)
why not :), I've pushed my initial work in https://github.com/aitboudad/ngx-formly/tree/2157, the remaining part is testing.
@vojtesaak not sure if you've already started on this, if not I'll continue my work this afternoon so let me know!
This issue has been fixed and released as part of v5.6.0 release.
Please let us know, in case you are still encountering a similar issue/problem.
Thank you!
Hi
I am using json powered forms for my project and it doesnt support CSP because when I try to use function in "expressionProperties", it gives json parse error.
Sample:
"expressionProperties": {
"templateOptions.label": _function(formState) => { return formState.labels.email }_
}
Please help me out as whole project is built on this feature.
Thank you.
@coalman11 the formState is passed as a second arg + ensure you're using the latest version (v5.6).
"expressionProperties": {
- "templateOptions.label": function(formState) => { return formState.labels.email }
+ "templateOptions.label": function(model, formState) { return formState.labels.email; }
}
Thanks for the reply @aitboudad. The thing is I am not able to use function directly in json. Please find below the screenshot. The json schema for form in saved in separate json file and loaded on a http service call.

@coalman11 well that part should be done after loading the JSON form, kind of post-process see https://github.com/ngx-formly/ngx-formly/issues/1102#issuecomment-411491538
Most helpful comment
resolved locally still need to add some tests. I'll try to finish it at the end of this week, please remind me in the case I didn't :hourglass: