Merge branch 'master' of github.com:Semmle/ql into js/more-fs-modules

This commit is contained in:
Esben Sparre Andreasen 2020-03-03 15:07:51 +01:00
Родитель adddebf039 88c74b2a4b
Коммит 4625217a68
20 изменённых файлов: 608 добавлений и 33 удалений

Просмотреть файл

@ -44,7 +44,7 @@
| Regular expression always matches (`js/regex/always-matches`) | correctness, regular-expressions | Highlights regular expression checks that trivially succeed by matching an empty substring. Results are shown on LGTM by default. |
| Missing await (`js/missing-await`) | correctness | Highlights expressions that operate directly on a promise object in a nonsensical way, instead of awaiting its result. Results are shown on LGTM by default. |
| Polynomial regular expression used on uncontrolled data (`js/polynomial-redos`) | security, external/cwe/cwe-730, external/cwe/cwe-400 | Highlights expensive regular expressions that may be used on malicious input. Results are shown on LGTM by default. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | security, external/cwe/cwe-400, external/cwe/cwe-471 | Highlights recursive copying operations that are susceptible to prototype pollution. Results are shown on LGTM by default. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | security, external/cwe/cwe-400, external/cwe/cwe-471 | Highlights recursive assignment operations that are susceptible to prototype pollution. Results are shown on LGTM by default. |
| Unsafe jQuery plugin (`js/unsafe-jquery-plugin`) | Highlights potential XSS vulnerabilities in unsafely designed jQuery plugins. Results are shown on LGTM by default. |
| Unnecessary use of `cat` process (`js/unnecessary-use-of-cat`) | correctness, security, maintainability | Highlights command executions of `cat` where the fs API should be used instead. Results are shown on LGTM by default. |

Просмотреть файл

@ -275,7 +275,7 @@ private predicate isChiForAllAliasedMemory(Instruction instr) {
or
isChiForAllAliasedMemory(instr.(ChiInstruction).getTotal())
or
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInput())
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
}
private predicate modelTaintToReturnValue(Function f, int parameterIn) {

Просмотреть файл

@ -135,6 +135,12 @@ private module VirtualDispatch {
exists(FunctionInstruction fi |
this.flowsFrom(DataFlow::instructionNode(fi), _) and
result = fi.getFunctionSymbol()
) and
(
this.getNumberOfArguments() <= result.getEffectiveNumberOfParameters() and
this.getNumberOfArguments() >= result.getEffectiveNumberOfParameters()
or
result.isVarargs()
)
}
}

Просмотреть файл

@ -1202,6 +1202,11 @@ class CallInstruction extends Instruction {
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDef()
}
/**
* Gets the number of arguments of the call, including the `this` pointer, if any.
*/
final int getNumberOfArguments() { result = count(this.getAnArgumentOperand()) }
}
/**

Просмотреть файл

@ -1202,6 +1202,11 @@ class CallInstruction extends Instruction {
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDef()
}
/**
* Gets the number of arguments of the call, including the `this` pointer, if any.
*/
final int getNumberOfArguments() { result = count(this.getAnArgumentOperand()) }
}
/**

Просмотреть файл

@ -1202,6 +1202,11 @@ class CallInstruction extends Instruction {
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDef()
}
/**
* Gets the number of arguments of the call, including the `this` pointer, if any.
*/
final int getNumberOfArguments() { result = count(this.getAnArgumentOperand()) }
}
/**

Просмотреть файл

@ -1202,6 +1202,11 @@ class CallInstruction extends Instruction {
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDef()
}
/**
* Gets the number of arguments of the call, including the `this` pointer, if any.
*/
final int getNumberOfArguments() { result = count(this.getAnArgumentOperand()) }
}
/**

Просмотреть файл

@ -1202,6 +1202,11 @@ class CallInstruction extends Instruction {
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDef()
}
/**
* Gets the number of arguments of the call, including the `this` pointer, if any.
*/
final int getNumberOfArguments() { result = count(this.getAnArgumentOperand()) }
}
/**

Просмотреть файл

@ -100,6 +100,13 @@ predicate signaturesMatch(MethodSignature method, MethodSignature other) {
method.getName() = other.getName() and
// same number of parameters.
method.getBody().getNumParameter() = other.getBody().getNumParameter() and
// same this parameter (if exists)
(
not exists(method.getBody().getThisTypeAnnotation()) and
not exists(other.getBody().getThisTypeAnnotation())
or
method.getBody().getThisTypeAnnotation().getType() = other.getBody().getThisTypeAnnotation().getType()
) and
// The types are compared in matchingCallSignature. This is sanity-check that the textual representation of the type-annotations are somewhat similar.
forall(int i | i in [0 .. -1 + method.getBody().getNumParameter()] |
getParameterTypeAnnotation(method, i) = getParameterTypeAnnotation(other, i)

Просмотреть файл

@ -13,7 +13,8 @@
<p>
One way to cause prototype pollution is through use of an unsafe <em>merge</em> or <em>extend</em> function
to recursively copy properties from one object to another.
to recursively copy properties from one object to another, or through the use of a <em>deep assignment</em>
function to assign to an unverified chain of property names.
Such a function has the potential to modify any object reachable from the destination object, and
the built-in <code>Object.prototype</code> is usually reachable through the special properties
<code>__proto__</code> and <code>constructor.prototype</code>.
@ -23,13 +24,13 @@
<recommendation>
<p>
The most effective place to guard against this is in the function that performs
the recursive copy.
the recursive copy or deep assignment.
</p>
<p>
Only merge a property recursively when it is an own property of the <em>destination</em> object.
Only merge or assign a property recursively when it is an own property of the <em>destination</em> object.
Alternatively, blacklist the property names <code>__proto__</code> and <code>constructor</code>
from being merged.
from being merged or assigned to.
</p>
</recommendation>

Просмотреть файл

@ -1,7 +1,7 @@
/**
* @name Prototype pollution in utility function
* @description Recursively copying properties between objects may cause
* accidental modification of a built-in prototype object.
* @description Recursively assigning properties on objects may cause
* accidental modification of a built-in prototype object.
* @kind path-problem
* @problem.severity warning
* @precision high
@ -16,6 +16,81 @@ import DataFlow
import PathGraph
import semmle.javascript.DynamicPropertyAccess
/**
* A call of form `x.split(".")` where `x` is a parameter.
*
* We restrict this to parameter nodes to focus on "deep assignment" functions.
*/
class SplitCall extends MethodCallNode {
SplitCall() {
getMethodName() = "split" and
getArgument(0).mayHaveStringValue(".") and
getReceiver().getALocalSource() instanceof ParameterNode
}
}
/**
* Holds if `pred -> succ` should preserve polluted property names.
*/
predicate copyArrayStep(SourceNode pred, SourceNode succ) {
// x -> [...x]
exists(SpreadElement spread |
pred.flowsTo(spread.getOperand().flow()) and
succ.asExpr().(ArrayExpr).getAnElement() = spread
)
or
// `x -> y` in `y.push( x[i] )`
exists(MethodCallNode push |
push = succ.getAMethodCall("push") and
(
getAnEnumeratedArrayElement(pred).flowsTo(push.getAnArgument())
or
pred.flowsTo(push.getASpreadArgument())
)
)
or
// x -> x.concat(...)
exists(MethodCallNode concat_ |
concat_.getMethodName() = "concat" and
(pred = concat_.getReceiver() or pred = concat_.getAnArgument()) and
succ = concat_
)
}
/**
* Holds if `node` may refer to a `SplitCall` or a copy thereof, possibly
* returned through a function call.
*/
predicate isSplitArray(SourceNode node) {
node instanceof SplitCall
or
exists(SourceNode pred | isSplitArray(pred) |
copyArrayStep(pred, node)
or
pred.flowsToExpr(node.(CallNode).getACallee().getAReturnedExpr())
)
}
/**
* A property name originating from a `x.split(".")` call.
*/
class SplitPropName extends SourceNode {
SourceNode array;
SplitPropName() {
isSplitArray(array) and
this = getAnEnumeratedArrayElement(array)
}
/**
* Gets the array from which this property name was obtained (the result from `split`).
*/
SourceNode getArray() { result = array }
/** Gets an element accessed on the same underlying array. */
SplitPropName getAnAlias() { result.getArray() = getArray() }
}
/**
* Holds if the properties of `node` are enumerated locally.
*/
@ -24,13 +99,23 @@ predicate arePropertiesEnumerated(DataFlow::SourceNode node) {
}
/**
* Holds if `node` may flow from an enumerated prop name, possibly
* into function calls (but not returns).
* Holds if `node` is a source of property names that we consider possible
* prototype pollution payloads.
*/
predicate isEnumeratedPropName(Node node) {
predicate isPollutedPropNameSource(DataFlow::Node node) {
node instanceof EnumeratedPropName
or
exists(Node pred | isEnumeratedPropName(pred) |
node instanceof SplitPropName
}
/**
* Holds if `node` may flow from a source of polluted propery names, possibly
* into function calls (but not returns).
*/
predicate isPollutedPropName(Node node) {
isPollutedPropNameSource(node)
or
exists(Node pred | isPollutedPropName(pred) |
node = pred.getASuccessor()
or
argumentPassingStep(_, pred, _, node)
@ -51,7 +136,7 @@ predicate isEnumeratedPropName(Node node) {
predicate isPotentiallyObjectPrototype(SourceNode node) {
exists(Node base, Node key |
dynamicPropReadStep(base, key, node) and
isEnumeratedPropName(key) and
isPollutedPropName(key) and
// Ignore cases where the properties of `base` are enumerated, to avoid FPs
// where the key came from that enumeration (and thus will not return Object.prototype).
// For example, `src[key]` in `for (let key in src) { ... src[key] ... }` will generally
@ -85,7 +170,13 @@ predicate dynamicPropWrite(DataFlow::Node base, DataFlow::Node prop, DataFlow::N
// Prune writes that are unlikely to modify Object.prototype.
// This is mainly for performance, but may block certain results due to
// not tracking out of function returns and into callbacks.
isPotentiallyObjectPrototype(base.getALocalSource())
isPotentiallyObjectPrototype(base.getALocalSource()) and
// Ignore writes with an obviously safe RHS.
not exists(Expr e | e = rhs.asExpr() |
e instanceof Literal or
e instanceof ObjectExpr or
e instanceof ArrayExpr
)
)
}
@ -141,10 +232,10 @@ class PropNameTracking extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node node, FlowLabel label) {
label instanceof UnsafePropLabel and
exists(EnumeratedPropName prop |
node = prop
(
isPollutedPropNameSource(node)
or
node = prop.getASourceProp()
node = any(EnumeratedPropName prop).getASourceProp()
)
}
@ -404,22 +495,29 @@ string deriveExprName(DataFlow::Node node) {
result = getExprName(node)
or
not exists(getExprName(node)) and
result = "this object"
result = "here"
}
/**
* Holds if the dynamic property write `base[prop] = rhs` can pollute the prototype
* of `base` due to flow from `enum`.
* of `base` due to flow from `propNameSource`.
*
* In most cases this will result in an alert, the exception being the case where
* `base` does not have a prototype at all.
*/
predicate isPrototypePollutingAssignment(Node base, Node prop, Node rhs, EnumeratedPropName enum) {
predicate isPrototypePollutingAssignment(Node base, Node prop, Node rhs, Node propNameSource) {
dynamicPropWrite(base, prop, rhs) and
isPollutedPropNameSource(propNameSource) and
exists(PropNameTracking cfg |
cfg.hasFlow(enum, base) and
cfg.hasFlow(enum, prop) and
cfg.hasFlow(enum.getASourceProp(), rhs)
cfg.hasFlow(propNameSource, base) and
if propNameSource instanceof EnumeratedPropName
then
cfg.hasFlow(propNameSource, prop) and
cfg.hasFlow(propNameSource.(EnumeratedPropName).getASourceProp(), rhs)
else (
cfg.hasFlow(propNameSource.(SplitPropName).getAnAlias(), prop) and
rhs.getALocalSource() instanceof ParameterNode
)
)
}
@ -464,18 +562,29 @@ class ObjectCreateNullCall extends CallNode {
}
from
PropNameTracking cfg, DataFlow::PathNode source, DataFlow::PathNode sink, EnumeratedPropName enum,
Node base
PropNameTracking cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Node prop, Node base,
string msg, Node col1, Node col2
where
isPollutedPropName(prop) and
cfg.hasFlowPath(source, sink) and
isPrototypePollutingAssignment(base, _, _, enum) and
isPrototypePollutingAssignment(base, _, _, prop) and
sink.getNode() = base and
source.getNode() = enum and
source.getNode() = prop and
(
getANodeLeadingToBaseBase(base) instanceof ObjectLiteralNode
or
not getANodeLeadingToBaseBase(base) instanceof ObjectCreateNullCall
) and
// Generate different messages for deep merge and deep assign cases.
if prop instanceof EnumeratedPropName
then (
col1 = prop.(EnumeratedPropName).getSourceObject() and
col2 = base and
msg = "Properties are copied from $@ to $@ without guarding against prototype pollution."
) else (
col1 = prop and
col2 = base and
msg =
"The property chain $@ is recursively assigned to $@ without guarding against prototype pollution."
)
select base, source, sink,
"Properties are copied from $@ to $@ without guarding against prototype pollution.",
enum.getSourceObject(), deriveExprName(enum.getSourceObject()), base, deriveExprName(base)
select base, source, sink, msg, col1, deriveExprName(col1), col2, deriveExprName(col2)

Просмотреть файл

@ -11,7 +11,7 @@ private import semmle.javascript.dataflow.internal.FlowSteps
* Gets a node that refers to an element of `array`, likely obtained
* as a result of enumerating the elements of the array.
*/
private SourceNode getAnEnumeratedArrayElement(SourceNode array) {
SourceNode getAnEnumeratedArrayElement(SourceNode array) {
exists(MethodCallNode call, string name |
call = array.getAMethodCall(name) and
(name = "forEach" or name = "map") and

Просмотреть файл

@ -58,6 +58,40 @@ module InclusionTest {
boolean getPolarity() { result = true }
}
/**
* A call to a utility function (`callee`) that performs an InclusionTest (`inner`).
*/
private class IndirectInclusionTest extends Range, DataFlow::CallNode {
InclusionTest inner;
Function callee;
IndirectInclusionTest() {
inner.getEnclosingExpr() = callee.getAReturnedExpr() and
this.getACallee() = callee and
count(this.getACallee()) = 1 and
count(callee.getAReturnedExpr()) = 1 and
not this.isImprecise() and
inner.getContainerNode().getALocalSource().getEnclosingExpr() = callee.getAParameter() and
inner.getContainedNode().getALocalSource().getEnclosingExpr() = callee.getAParameter()
}
override DataFlow::Node getContainerNode() {
exists(int arg |
inner.getContainerNode().getALocalSource().getEnclosingExpr() = callee.getParameter(arg) and
result = this.getArgument(arg)
)
}
override DataFlow::Node getContainedNode() {
exists(int arg |
inner.getContainedNode().getALocalSource().getEnclosingExpr() = callee.getParameter(arg) and
result = this.getArgument(arg)
)
}
override boolean getPolarity() { result = inner.getPolarity() }
}
/**
* A call to a method named `includes`, assumed to refer to `String.prototype.includes`
* or `Array.prototype.includes`.

Просмотреть файл

@ -56,6 +56,40 @@ module StringOps {
boolean getPolarity() { result = true }
}
/**
* A call to a utility function (`callee`) that performs a StartsWith check (`inner`).
*/
private class IndirectStartsWith extends Range, DataFlow::CallNode {
StartsWith inner;
Function callee;
IndirectStartsWith() {
inner.getEnclosingExpr() = callee.getAReturnedExpr() and
this.getACallee() = callee and
count(this.getACallee()) = 1 and
count(callee.getAReturnedExpr()) = 1 and
not this.isImprecise() and
inner.getBaseString().getALocalSource().getEnclosingExpr() = callee.getAParameter() and
inner.getSubstring().getALocalSource().getEnclosingExpr() = callee.getAParameter()
}
override DataFlow::Node getBaseString() {
exists(int arg |
inner.getBaseString().getALocalSource().getEnclosingExpr() = callee.getParameter(arg) and
result = this.getArgument(arg)
)
}
override DataFlow::Node getSubstring() {
exists(int arg |
inner.getSubstring().getALocalSource().getEnclosingExpr() = callee.getParameter(arg) and
result = this.getArgument(arg)
)
}
override boolean getPolarity() { result = inner.getPolarity() }
}
/**
* An expression of form `A.startsWith(B)`.
*/
@ -253,6 +287,41 @@ module StringOps {
boolean getPolarity() { result = true }
}
/**
* A call to a utility function (`callee`) that performs an EndsWith check (`inner`).
*/
private class IndirectEndsWith extends Range, DataFlow::CallNode {
EndsWith inner;
Function callee;
IndirectEndsWith() {
inner.getEnclosingExpr() = callee.getAReturnedExpr() and
this.getACallee() = callee and
count(this.getACallee()) = 1 and
count(callee.getAReturnedExpr()) = 1 and
not this.isImprecise() and
inner.getBaseString().getALocalSource().getEnclosingExpr() = callee.getAParameter() and
inner.getSubstring().getALocalSource().getEnclosingExpr() = callee.getAParameter()
}
override DataFlow::Node getBaseString() {
exists(int arg |
inner.getBaseString().getALocalSource().getEnclosingExpr() = callee.getParameter(arg) and
result = this.getArgument(arg)
)
}
override DataFlow::Node getSubstring() {
exists(int arg |
inner.getSubstring().getALocalSource().getEnclosingExpr() = callee.getParameter(arg) and
result = this.getArgument(arg)
)
}
override boolean getPolarity() { result = inner.getPolarity() }
}
/**
* A call of form `A.endsWith(B)`.
*/

Просмотреть файл

@ -1,4 +1,5 @@
| tst.ts:3:3:3:30 | method( ... number; | This overload of method() is unreachable, the $@ overload will always be selected. | tst.ts:2:3:2:30 | method( ... string; | previous |
| tst.ts:6:3:6:17 | types1(): any[] | This overload of types1() is unreachable, the $@ overload will always be selected. | tst.ts:5:3:5:18 | types1<T>(): T[] | previous |
| tst.ts:15:3:15:74 | on(even ... nction; | This overload of on() is unreachable, the $@ overload will always be selected. | tst.ts:14:3:14:74 | on(even ... nction; | previous |
| tst.ts:21:3:21:30 | method( ... number; | This overload of method() is unreachable, the $@ overload will always be selected. | tst.ts:20:3:20:30 | method( ... string; | previous |
| tst.ts:21:3:21:28 | bar(thi ... number; | This overload of bar() is unreachable, the $@ overload will always be selected. | tst.ts:20:3:20:28 | bar(thi ... string; | previous |
| tst.ts:27:3:27:30 | method( ... number; | This overload of method() is unreachable, the $@ overload will always be selected. | tst.ts:26:3:26:30 | method( ... string; | previous |

Просмотреть файл

@ -14,6 +14,12 @@ declare class Foobar {
on(event: string, fn?: (event?: any, ...args: any[]) => void): Function;
on(event: string, fn?: (event?: any, ...args: any[]) => void): Function; // NOT OK.
foo(this: string): string;
foo(this: number): number; // OK
bar(this: number): string;
bar(this: number): number; // NOT OK
}
declare class Base {

Просмотреть файл

@ -1654,6 +1654,33 @@ nodes
| normalizedPaths.js:346:19:346:22 | path |
| normalizedPaths.js:346:19:346:22 | path |
| normalizedPaths.js:346:19:346:22 | path |
| normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path |
| normalizedPaths.js:354:14:354:27 | req.query.path |
| normalizedPaths.js:354:14:354:27 | req.query.path |
| normalizedPaths.js:354:14:354:27 | req.query.path |
| normalizedPaths.js:354:14:354:27 | req.query.path |
| normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:358:7:358:51 | requestPath |
| normalizedPaths.js:358:7:358:51 | requestPath |
| normalizedPaths.js:358:7:358:51 | requestPath |
| normalizedPaths.js:358:21:358:51 | pathMod ... , path) |
| normalizedPaths.js:358:21:358:51 | pathMod ... , path) |
| normalizedPaths.js:358:21:358:51 | pathMod ... , path) |
| normalizedPaths.js:358:47:358:50 | path |
| normalizedPaths.js:358:47:358:50 | path |
| normalizedPaths.js:358:47:358:50 | path |
| normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:363:21:363:31 | requestPath |
| other-fs-libraries.js:9:7:9:48 | path |
| other-fs-libraries.js:9:7:9:48 | path |
| other-fs-libraries.js:9:7:9:48 | path |
@ -4787,6 +4814,37 @@ edges
| normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:339:13:339:46 | pathMod ... y.path) |
| normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:339:13:339:46 | pathMod ... y.path) |
| normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:339:13:339:46 | pathMod ... y.path) |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:356:19:356:22 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:358:47:358:50 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:358:47:358:50 | path |
| normalizedPaths.js:354:7:354:27 | path | normalizedPaths.js:358:47:358:50 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:354:7:354:27 | path |
| normalizedPaths.js:358:7:358:51 | requestPath | normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:358:7:358:51 | requestPath | normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:358:7:358:51 | requestPath | normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:358:7:358:51 | requestPath | normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:358:7:358:51 | requestPath | normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:358:7:358:51 | requestPath | normalizedPaths.js:363:21:363:31 | requestPath |
| normalizedPaths.js:358:21:358:51 | pathMod ... , path) | normalizedPaths.js:358:7:358:51 | requestPath |
| normalizedPaths.js:358:21:358:51 | pathMod ... , path) | normalizedPaths.js:358:7:358:51 | requestPath |
| normalizedPaths.js:358:21:358:51 | pathMod ... , path) | normalizedPaths.js:358:7:358:51 | requestPath |
| normalizedPaths.js:358:47:358:50 | path | normalizedPaths.js:358:21:358:51 | pathMod ... , path) |
| normalizedPaths.js:358:47:358:50 | path | normalizedPaths.js:358:21:358:51 | pathMod ... , path) |
| normalizedPaths.js:358:47:358:50 | path | normalizedPaths.js:358:21:358:51 | pathMod ... , path) |
| other-fs-libraries.js:9:7:9:48 | path | other-fs-libraries.js:11:19:11:22 | path |
| other-fs-libraries.js:9:7:9:48 | path | other-fs-libraries.js:11:19:11:22 | path |
| other-fs-libraries.js:9:7:9:48 | path | other-fs-libraries.js:11:19:11:22 | path |
@ -6005,6 +6063,8 @@ edges
| normalizedPaths.js:332:19:332:32 | normalizedPath | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:332:19:332:32 | normalizedPath | This path depends on $@. | normalizedPaths.js:303:13:303:26 | req.query.path | a user-provided value |
| normalizedPaths.js:341:18:341:21 | path | normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:341:18:341:21 | path | This path depends on $@. | normalizedPaths.js:339:32:339:45 | req.query.path | a user-provided value |
| normalizedPaths.js:346:19:346:22 | path | normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:346:19:346:22 | path | This path depends on $@. | normalizedPaths.js:339:32:339:45 | req.query.path | a user-provided value |
| normalizedPaths.js:356:19:356:22 | path | normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:356:19:356:22 | path | This path depends on $@. | normalizedPaths.js:354:14:354:27 | req.query.path | a user-provided value |
| normalizedPaths.js:363:21:363:31 | requestPath | normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:363:21:363:31 | requestPath | This path depends on $@. | normalizedPaths.js:354:14:354:27 | req.query.path | a user-provided value |
| other-fs-libraries.js:11:19:11:22 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:11:19:11:22 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value |
| other-fs-libraries.js:12:27:12:30 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:12:27:12:30 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value |
| other-fs-libraries.js:13:24:13:27 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:13:24:13:27 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value |

Просмотреть файл

@ -347,4 +347,27 @@ app.get('/yet-another-prefix', (req, res) => {
return;
}
fs.readFileSync(path); // OK
});
var rootPath = process.cwd();
app.get('/yet-another-prefix2', (req, res) => {
let path = req.query.path;
fs.readFileSync(path); // NOT OK
var requestPath = pathModule.join(rootPath, path);
var targetPath;
if (!allowPath(requestPath, rootPath)) {
targetPath = rootPath;
fs.readFileSync(requestPath); // NOT OK
} else {
targetPath = requestPath;
fs.readFileSync(requestPath); // OK
}
fs.readFileSync(targetPath); // OK
function allowPath(requestPath, rootPath) {
return requestPath.indexOf(rootPath) === 0;
}
});

Просмотреть файл

@ -1,4 +1,85 @@
nodes
| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key |
| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key |
| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target |
| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target |
| PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target |
| PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target |
| PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] |
| PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] |
| PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key |
| PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key |
| PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target |
| PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target |
| PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target |
| PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key |
| PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key |
| PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key |
| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key |
| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key |
| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target |
| PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target |
| PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target |
| PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target |
| PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key |
| PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key |
| PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key |
| PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target |
| PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target |
| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key |
| PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key |
| PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target |
| PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target |
| PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target |
| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key |
| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key |
| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target |
| PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target |
| PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target |
| PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target |
| PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key |
| PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key |
| PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key |
| PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target |
| PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target |
| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key |
| PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key |
| PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target |
| PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target |
| PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target |
| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] |
| PrototypePollutionUtility/tests.js:3:25:3:27 | dst |
| PrototypePollutionUtility/tests.js:3:25:3:27 | dst |
| PrototypePollutionUtility/tests.js:3:30:3:32 | src |
@ -1173,6 +1254,94 @@ nodes
| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key |
| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key |
edges
| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key |
| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key |
| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key |
| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key |
| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key |
| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key |
| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key |
| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key |
| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key |
| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key |
| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target |
| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target |
| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target |
| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target |
| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target |
| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target |
| PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target | PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] |
| PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target | PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] |
| PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target |
| PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target |
| PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key | PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] |
| PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key | PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] |
| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key |
| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key |
| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key |
| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key |
| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key |
| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key |
| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key |
| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key |
| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key |
| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target |
| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target |
| PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target |
| PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target |
| PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target | PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target | PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key | PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key | PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] | PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] |
| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key |
| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key |
| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key |
| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key |
| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key |
| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key |
| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key |
| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key |
| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key |
| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target |
| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target |
| PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target |
| PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target |
| PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target | PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target | PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} |
| PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key | PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key | PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] |
| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] | PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] |
| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:6:28:6:30 | dst |
| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:6:28:6:30 | dst |
| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst |
@ -2669,6 +2838,9 @@ edges
| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] |
| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] |
#select
| PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | here | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | target |
| PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | here | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | target |
| PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | here | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | target |
| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:4:21:4:23 | src | src | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | dst |
| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:14:17:14:19 | src | src | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | dst |
| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:25:25:25:30 | source | source | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | dst |
@ -2677,7 +2849,7 @@ edges
| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:102:21:102:23 | src | src | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | dst |
| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:150:21:150:23 | src | src | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | dst |
| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:190:28:190:30 | src | src | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | dst |
| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:238:21:238:24 | data | data | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | this object |
| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:238:21:238:24 | data | data | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | here |
| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:264:20:264:22 | src | src | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | dst |
| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:276:21:276:23 | src | src | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | dst |
| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:302:21:302:23 | src | src | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | dst |

Просмотреть файл

@ -0,0 +1,62 @@
function isSafe(key) {
return key !== "__proto__" && key !== "constructor" && key !== "prototype";
}
function assignToPath(target, path, value) {
let keys = path.split('.');
for (let i = 0; i < keys.length; ++i) {
let key = keys[i];
if (i < keys.length - 1) {
if (!target[key]) {
target[key] = {};
}
target = target[key];
} else {
target[key] = value; // NOT OK
}
}
}
function assignToPathSafe(target, path, value) {
let keys = path.split('.');
for (let i = 0; i < keys.length; ++i) {
let key = keys[i];
if (!isSafe(key)) return;
if (i < keys.length - 1) {
if (!target[key]) {
target[key] = {};
}
target = target[key];
} else {
target[key] = value; // OK
}
}
}
function assignToPathAfterLoop(target, path, value) {
let keys = path.split('.');
let i;
for (i = 0; i < keys.length - 1; ++i) {
let key = keys[i];
target = target[key] = target[key] || {};
}
target[keys[i]] = value; // NOT OK
}
function splitHelper(path, sep) {
let parts = typeof path === 'string' ? path.split(sep || '.') : path;
let result = [];
result.push(...parts);
return result;
}
function assignToPathWithHelper(target, path, value, sep) {
let keys = splitHelper(path, sep)
let i;
for (i = 0; i < keys.length - 1; ++i) {
let key = keys[i];
target = target[key] = target[key] || {};
}
target[keys[i]] = value; // NOT OK
}