|
1 | | -/*! jsonpath 1.2.1 */ |
| 1 | +/*! jsonpath 1.3.0 */ |
2 | 2 |
|
3 | 3 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jsonpath = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"./aesprim":[function(require,module,exports){ |
4 | 4 | /* |
@@ -4621,6 +4621,152 @@ var slice = require('./slice'); |
4621 | 4621 | var _evaluate = require('static-eval'); |
4622 | 4622 | var _uniq = require('underscore').uniq; |
4623 | 4623 |
|
| 4624 | +// Property names that must never be accessible in expressions. |
| 4625 | +// Mitigates prototype pollution and constructor escape attacks. |
| 4626 | +var UNSAFE_PROPERTY_NAMES = Object.create(null); |
| 4627 | + |
| 4628 | +/* jshint -W069: true */ |
| 4629 | +UNSAFE_PROPERTY_NAMES['constructor'] = true; |
| 4630 | +UNSAFE_PROPERTY_NAMES['__proto__'] = true; |
| 4631 | +UNSAFE_PROPERTY_NAMES['prototype'] = true; |
| 4632 | +/* jshint -W069: false */ |
| 4633 | + |
| 4634 | +function isUnsafePropertyName(name) { |
| 4635 | + return typeof name === 'string' && UNSAFE_PROPERTY_NAMES[name] === true; |
| 4636 | +} |
| 4637 | + |
| 4638 | +function isSafeAst(ast) { |
| 4639 | + if (!ast || typeof ast !== 'object') return false; |
| 4640 | + |
| 4641 | + function walk(node) { |
| 4642 | + if (!node || typeof node !== 'object' || !node.type) { |
| 4643 | + return false; |
| 4644 | + } |
| 4645 | + |
| 4646 | + switch (node.type) { |
| 4647 | + |
| 4648 | + // ===== SAFE TERMINALS ===== |
| 4649 | + |
| 4650 | + case 'Literal': |
| 4651 | + return true; |
| 4652 | + |
| 4653 | + case 'Identifier': |
| 4654 | + // Only allow the special scope identifier |
| 4655 | + return node.name === '@'; |
| 4656 | + |
| 4657 | + |
| 4658 | + // ===== PROPERTY ACCESS ===== |
| 4659 | + |
| 4660 | + case 'MemberExpression': { |
| 4661 | + if (!walk(node.object)) { |
| 4662 | + return false; |
| 4663 | + } |
| 4664 | + |
| 4665 | + // Non-computed: obj.property |
| 4666 | + if (!node.computed && node.property.type === 'Identifier') { |
| 4667 | + if (isUnsafePropertyName(node.property.name)) { |
| 4668 | + return false; |
| 4669 | + } |
| 4670 | + return true; |
| 4671 | + } |
| 4672 | + |
| 4673 | + // Computed: obj["property"] |
| 4674 | + if (node.computed) { |
| 4675 | + if (!walk(node.property)) { |
| 4676 | + return false; |
| 4677 | + } |
| 4678 | + |
| 4679 | + if ( |
| 4680 | + node.property.type === 'Literal' && |
| 4681 | + isUnsafePropertyName(String(node.property.value)) |
| 4682 | + ) { |
| 4683 | + return false; |
| 4684 | + } |
| 4685 | + |
| 4686 | + return true; |
| 4687 | + } |
| 4688 | + |
| 4689 | + return false; |
| 4690 | + } |
| 4691 | + |
| 4692 | + |
| 4693 | + // ===== EXPRESSIONS ===== |
| 4694 | + |
| 4695 | + case 'UnaryExpression': |
| 4696 | + return walk(node.argument); |
| 4697 | + |
| 4698 | + case 'BinaryExpression': |
| 4699 | + case 'LogicalExpression': |
| 4700 | + return walk(node.left) && walk(node.right); |
| 4701 | + |
| 4702 | + case 'ConditionalExpression': |
| 4703 | + return ( |
| 4704 | + walk(node.test) && |
| 4705 | + walk(node.consequent) && |
| 4706 | + walk(node.alternate) |
| 4707 | + ); |
| 4708 | + |
| 4709 | + case 'ArrayExpression': |
| 4710 | + for (var i = 0; i < node.elements.length; i++) { |
| 4711 | + if (!walk(node.elements[i])) { |
| 4712 | + return false; |
| 4713 | + } |
| 4714 | + } |
| 4715 | + return true; |
| 4716 | + |
| 4717 | + case 'ObjectExpression': |
| 4718 | + for (var j = 0; j < node.properties.length; j++) { |
| 4719 | + var prop = node.properties[j]; |
| 4720 | + |
| 4721 | + // Reject unsafe keys |
| 4722 | + if ( |
| 4723 | + prop.key && |
| 4724 | + ( |
| 4725 | + (prop.key.type === 'Identifier' && |
| 4726 | + isUnsafePropertyName(prop.key.name)) || |
| 4727 | + (prop.key.type === 'Literal' && |
| 4728 | + isUnsafePropertyName(String(prop.key.value))) |
| 4729 | + ) |
| 4730 | + ) { |
| 4731 | + return false; |
| 4732 | + } |
| 4733 | + |
| 4734 | + if (!walk(prop.value)) { |
| 4735 | + return false; |
| 4736 | + } |
| 4737 | + } |
| 4738 | + return true; |
| 4739 | + |
| 4740 | + |
| 4741 | + // ===== EXPLICITLY REJECT DANGEROUS TYPES ===== |
| 4742 | + // Security: do not rely on default deny; list each code-execution / escape vector. |
| 4743 | + |
| 4744 | + case 'CallExpression': |
| 4745 | + case 'NewExpression': |
| 4746 | + case 'FunctionExpression': |
| 4747 | + case 'ArrowFunctionExpression': |
| 4748 | + case 'ThisExpression': |
| 4749 | + case 'AssignmentExpression': |
| 4750 | + case 'UpdateExpression': |
| 4751 | + case 'SequenceExpression': |
| 4752 | + case 'TemplateLiteral': |
| 4753 | + case 'TemplateElement': |
| 4754 | + case 'TaggedTemplateExpression': |
| 4755 | + case 'ReturnStatement': |
| 4756 | + case 'ExpressionStatement': |
| 4757 | + return false; |
| 4758 | + |
| 4759 | + |
| 4760 | + // ===== DEFAULT DENY ===== |
| 4761 | + |
| 4762 | + default: |
| 4763 | + return false; |
| 4764 | + } |
| 4765 | + } |
| 4766 | + |
| 4767 | + return walk(ast); |
| 4768 | +} |
| 4769 | + |
4624 | 4770 | var Handlers = function() { |
4625 | 4771 | return this.initialize.apply(this, arguments); |
4626 | 4772 | } |
@@ -4857,8 +5003,11 @@ function _traverse(passable) { |
4857 | 5003 | } |
4858 | 5004 | } |
4859 | 5005 |
|
4860 | | -function evaluate() { |
4861 | | - try { return _evaluate.apply(this, arguments) } |
| 5006 | +function evaluate(ast, scope) { |
| 5007 | + if (!isSafeAst(ast)) { |
| 5008 | + throw new Error('Unsafe expression: script and filter expressions may only access the current node (@) with safe property names'); |
| 5009 | + } |
| 5010 | + try { return _evaluate(ast, scope) } |
4862 | 5011 | catch (e) { } |
4863 | 5012 | } |
4864 | 5013 |
|
|
0 commit comments