no-unsafe-regex.js 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. 'use strict';
  2. const safeRegex = require('safe-regex');
  3. const {newExpressionSelector} = require('./selectors/index.js');
  4. const MESSAGE_ID = 'no-unsafe-regex';
  5. const messages = {
  6. [MESSAGE_ID]: 'Unsafe regular expression.',
  7. };
  8. const newRegExpSelector = [
  9. newExpressionSelector('RegExp'),
  10. '[arguments.0.type="Literal"]',
  11. ].join('');
  12. /** @param {import('eslint').Rule.RuleContext} context */
  13. const create = () => ({
  14. 'Literal[regex]'(node) {
  15. // Handle regex literal inside RegExp constructor in the other handler
  16. if (
  17. node.parent.type === 'NewExpression'
  18. && node.parent.callee.name === 'RegExp'
  19. ) {
  20. return;
  21. }
  22. if (!safeRegex(node.value)) {
  23. return {
  24. node,
  25. messageId: MESSAGE_ID,
  26. };
  27. }
  28. },
  29. [newRegExpSelector](node) {
  30. const arguments_ = node.arguments;
  31. const hasRegExp = arguments_[0].regex;
  32. let pattern;
  33. let flags;
  34. if (hasRegExp) {
  35. ({pattern} = arguments_[0].regex);
  36. flags = arguments_[1] && arguments_[1].type === 'Literal'
  37. ? arguments_[1].value
  38. : arguments_[0].regex.flags;
  39. } else {
  40. pattern = arguments_[0].value;
  41. flags = arguments_[1] && arguments_[1].type === 'Literal'
  42. ? arguments_[1].value
  43. : '';
  44. }
  45. if (!safeRegex(`/${pattern}/${flags}`)) {
  46. return {
  47. node,
  48. messageId: MESSAGE_ID,
  49. };
  50. }
  51. },
  52. });
  53. /** @type {import('eslint').Rule.RuleModule} */
  54. module.exports = {
  55. create,
  56. meta: {
  57. type: 'problem',
  58. docs: {
  59. description: 'Disallow unsafe regular expressions.',
  60. },
  61. messages,
  62. },
  63. };