Les mots-clés des modèles me sentent un peu comme eval, et il est souvent cité que l' utilisation d'eval est une mauvaise idée .
Je ne me préoccupe pas de l' exécution des modèles littéraires , mais je suis préoccupé par les attaques par injection (et d'autres problèmes de sécurité, je ne pense peut-être pas).
modifier
Un exemple de quelque chose qui me paraît étrange
let ii = 1; function counter() { return ii++; } console.log(`${counter()}, ${ii++}, ${counter()}`);
Quelles sorties
1, 2, 3
Le modèle littéral fait des effets secondaires au niveau mondial. Tous deux par une fonction, et directement.
Modifier 2
Un exemple indiquant la sécurité des modèles littéraires
let ii = 1; let inc = function() { ii++; } console.log('Starting: ' + ii); let input = prompt('Input something evil (suggestion: inc() or ii++)'); console.log(`You input: ${input}`); console.log('After template literal: ' + ii); eval(input); console.log('After eval: ' + ii);
Si vous indiquez ii++
lorsque vous y êtes invité, il enregistre
Démarrage: 1
Vous entrez: ii + = 1
Après le modèle literal: 1
Après eval: 2
Modifier 3
J'ai commencé à examiner la spécification ECMAScript
Bien que je n'échappe pas aux détails, il me semble que les littéraux de modèle sont spécifiés plus sûrs que eval.
Une différence avec eval
est que les littéraux de modèle sont analysés au moment de la compilation, alors que l'argument d' eval
est analysé uniquement au moment de l'exécution, lorsque eval
est exécuté.
En ce qui concerne ceci, est-ce que eval
peut obtenir un argument construit dynamiquement, alors qu'un modèle littéral est … littéral : il ne peut pas être stocké en tant que variable de modèle, que vous pouvez construire dynamiquement, se déplacer et finalement analyser: il n'y a pas de "modèle Variable "type de données. Une fonction de balise n'obtient pas réellement une variable de modèle comme argument, mais les composants analysés, connus au moment de la compilation.
Avec eval
vous pouvez avoir cette situation:
var code = prompt('enter some evil code'); eval(code);
Mais ce n'est pas possible avec les modèles littéraires:
var literal = prompt('enter some evil template literal'); tag literal; // there is no data type or syntax for this. `${literal}`; // and this just gives you the entered string.
Ce qui est possible, c'est ceci:
var str = prompt('enter some string'); tag`${str}`;
Mais cela ne conduit pas à une exécution de code indésirable, du moins pas pire que cela:
var str = prompt('enter some string'); myfunc(str);
Les appels de fonction doivent déjà être encodés littéralement dans un modèle littéraire. Les valeurs des variables de chaîne ne peuvent pas changer cela. Il n'y a aucun moyen pour lequel une fonction variable est appelée par un modèle littéraire. Ce:
`${func(str)}`;
… appellera func
, et cette fonction seulement. Il est choisi par le programmeur.
Cela dit, cela est encore possible:
var func = prompt ("enter some evil function name (suggestion: 'alert')"); var param = prompt ("now provide an argument for " + func); `${window[func](param)}`;
Les mots-clés des modèles échappent à des guillemets automatiquement, si cela vous préoccupe. Ils n'évalurent pas non plus ou n'exécutent rien, ils convertissent tout ce que vous mettez en chaîne. Si vous êtes préoccupé par SQL Injection, essayez de le faire avec des littéraux de modèle et vous verrez qu'ils se sont échappés.
Vous devriez éviter d'utiliser eval, sauf si vous avez une très bonne raison de l'utiliser et vous savez vraiment que vous en avez besoin pour atteindre votre objectif. Sinon, il est préférable d'éviter .
Je pense qu'il y a une grande différence entre eval et les modèles littéraires .
Eval peut évaluer des expressions dynamiques qui ne sont pas directement visibles à partir du code. Cela rend dangereux, car vous pouvez évaluer n'importe quelle chaîne pouvant venir de n'importe où: client / tiers / db …
Cependant, la situation est différente dans le cas des modèles littéraires ,
Par exemple, cela fonctionnera avec eval
function doSomething() { console.log('HELLO!'); } // This will work. var expression = 'doSomething()'; eval(expression);