mirror of
https://github.com/github/codeql.git
synced 2026-04-27 09:45:15 +02:00
JS: Add view-component-input threat model
This commit is contained in:
12
javascript/ql/lib/semmle/javascript/ViewComponentInput.qll
Normal file
12
javascript/ql/lib/semmle/javascript/ViewComponentInput.qll
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Provides a classes and predicates for contributing to the `view-component-input` threat model.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
/**
|
||||
* An input to a view component, such as React props.
|
||||
*/
|
||||
abstract class ViewComponentInput extends ThreatModelSource::Range {
|
||||
final override string getThreatModel() { result = "view-component-input" }
|
||||
}
|
||||
@@ -8,6 +8,7 @@ private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.DynamicPropertyAccess
|
||||
private import semmle.javascript.dataflow.internal.PreCallGraphStep
|
||||
private import semmle.javascript.ViewComponentInput
|
||||
|
||||
/**
|
||||
* Provides classes for working with Angular (also known as Angular 2.x) applications.
|
||||
@@ -575,4 +576,17 @@ module Angular2 {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class InputFieldAsViewComponentInput extends ViewComponentInput {
|
||||
InputFieldAsViewComponentInput() {
|
||||
this =
|
||||
API::moduleImport("@angular/core")
|
||||
.getMember("Input")
|
||||
.getReturn()
|
||||
.getADecoratedMember()
|
||||
.asSource()
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Angular component input field" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
|
||||
private import semmle.javascript.dataflow.internal.PreCallGraphStep
|
||||
private import semmle.javascript.ViewComponentInput
|
||||
|
||||
/**
|
||||
* Gets a reference to the 'React' object.
|
||||
@@ -868,3 +869,9 @@ private class PropsFlowStep extends PreCallGraphStep {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class ReactPropAsViewComponentInput extends ViewComponentInput {
|
||||
ReactPropAsViewComponentInput() { this = any(ReactComponent c).getADirectPropsAccess() }
|
||||
|
||||
override string getSourceType() { result = "React props" }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.ViewComponentInput
|
||||
|
||||
module Vue {
|
||||
/** The global variable `Vue`, as an API graph entry point. */
|
||||
@@ -85,17 +86,16 @@ module Vue {
|
||||
* A class with a `@Component` decorator, making it usable as an "options" object in Vue.
|
||||
*/
|
||||
class ClassComponent extends DataFlow::ClassNode {
|
||||
private ClassDefinition cls;
|
||||
DataFlow::Node decorator;
|
||||
|
||||
ClassComponent() {
|
||||
exists(ClassDefinition cls |
|
||||
this = cls.flow() and
|
||||
cls.getADecorator().getExpression() = decorator.asExpr() and
|
||||
(
|
||||
componentDecorator().flowsTo(decorator)
|
||||
or
|
||||
componentDecorator().getACall() = decorator
|
||||
)
|
||||
this = cls.flow() and
|
||||
cls.getADecorator().getExpression() = decorator.asExpr() and
|
||||
(
|
||||
componentDecorator().flowsTo(decorator)
|
||||
or
|
||||
componentDecorator().getACall() = decorator
|
||||
)
|
||||
}
|
||||
|
||||
@@ -105,6 +105,9 @@ module Vue {
|
||||
* These options correspond to the options one would pass to `new Vue({...})` or similar.
|
||||
*/
|
||||
API::Node getDecoratorOptions() { result = decorator.(API::CallNode).getParameter(0) }
|
||||
|
||||
/** Gets the AST node for the class definition. */
|
||||
ClassDefinition getClassDefinition() { result = cls }
|
||||
}
|
||||
|
||||
private string memberKindVerb(DataFlow::MemberKind kind) {
|
||||
@@ -460,6 +463,12 @@ module Vue {
|
||||
|
||||
SingleFileComponent() { this = MkSingleFileComponent(file) }
|
||||
|
||||
/** Gets a call to `defineProps` in this component. */
|
||||
DataFlow::CallNode getDefinePropsCall() {
|
||||
result = DataFlow::globalVarRef("defineProps").getACall() and
|
||||
result.getFile() = file
|
||||
}
|
||||
|
||||
override Template::Element getTemplateElement() {
|
||||
exists(HTML::Element e | result.(Template::HtmlElement).getElement() = e |
|
||||
e.getFile() = file and
|
||||
@@ -697,4 +706,68 @@ module Vue {
|
||||
|
||||
override ClientSideRemoteFlowKind getKind() { result = kind }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given type annotation indicates a value that is not typically considered taintable.
|
||||
*/
|
||||
private predicate isSafeType(TypeAnnotation type) {
|
||||
type.isBooleany() or
|
||||
type.isNumbery() or
|
||||
type.isRawFunction() or
|
||||
type instanceof FunctionTypeExpr
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given field has a type that indicates that is can not contain a taintable value.
|
||||
*/
|
||||
private predicate isSafeField(FieldDeclaration field) { isSafeType(field.getTypeAnnotation()) }
|
||||
|
||||
private DataFlow::Node getPropSpec(Component component) {
|
||||
result = component.getOption("props")
|
||||
or
|
||||
result = component.(SingleFileComponent).getDefinePropsCall().getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `component` has an input prop with the given name, that is of a taintable type.
|
||||
*/
|
||||
private predicate hasTaintableProp(Component component, string name) {
|
||||
exists(DataFlow::SourceNode spec | spec = getPropSpec(component).getALocalSource() |
|
||||
spec.(DataFlow::ArrayCreationNode).getAnElement().getStringValue() = name
|
||||
or
|
||||
exists(DataFlow::PropWrite write |
|
||||
write = spec.getAPropertyWrite(name) and
|
||||
not DataFlow::globalVarRef(["Number", "Boolean"]).flowsTo(write.getRhs())
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(FieldDeclaration field |
|
||||
field = component.getAsClassComponent().getClassDefinition().getField(name) and
|
||||
DataFlow::moduleMember("vue-property-decorator", "Prop")
|
||||
.getACall()
|
||||
.flowsToExpr(field.getADecorator().getExpression()) and
|
||||
not isSafeField(field)
|
||||
)
|
||||
or
|
||||
// defineProps() can be called with only type arguments and then the Vue compiler will
|
||||
// infer the prop types.
|
||||
exists(CallExpr call, FieldDeclaration field |
|
||||
call = component.(SingleFileComponent).getDefinePropsCall().asExpr() and
|
||||
field = call.getTypeArgument(0).(InterfaceTypeExpr).getMember(name) and
|
||||
not isSafeField(field)
|
||||
)
|
||||
}
|
||||
|
||||
private class PropAsViewComponentInput extends ViewComponentInput {
|
||||
PropAsViewComponentInput() {
|
||||
exists(Component component, string name | hasTaintableProp(component, name) |
|
||||
this = component.getAnInstanceRef().getAPropertyRead(name)
|
||||
or
|
||||
// defineProps() returns the props
|
||||
this = component.(SingleFileComponent).getDefinePropsCall().getAPropertyRead(name)
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Vue prop" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
@@ -6,17 +6,17 @@ import { DomSanitizer } from '@angular/platform-browser';
|
||||
template: "not important"
|
||||
})
|
||||
export class SinkComponent {
|
||||
sink1: string;
|
||||
sink2: string;
|
||||
sink3: string;
|
||||
sink4: string;
|
||||
sink5: string;
|
||||
sink6: string;
|
||||
sink7: string;
|
||||
sink8: string;
|
||||
sink9: string;
|
||||
@Input() sink1: string;
|
||||
@Input() sink2: string;
|
||||
@Input() sink3: string;
|
||||
@Input() sink4: string;
|
||||
@Input() sink5: string;
|
||||
@Input() sink6: string;
|
||||
@Input() sink7: string;
|
||||
@Input() sink8: string;
|
||||
@Input() sink9: string;
|
||||
|
||||
constructor(private sanitizer: DomSanitizer) {}
|
||||
constructor(private sanitizer: DomSanitizer) { }
|
||||
|
||||
foo() {
|
||||
this.sanitizer.bypassSecurityTrustHtml(this.sink1);
|
||||
|
||||
@@ -36,3 +36,13 @@ taintFlow
|
||||
| source.component.ts:16:33:16:40 | source() | sink.component.ts:22:48:22:57 | this.sink1 |
|
||||
testAttrSourceLocation
|
||||
| inline.component.ts:8:43:8:60 | [testAttr]=taint | inline.component.ts:8:55:8:59 | <toplevel> |
|
||||
threatModelSource
|
||||
| sink.component.ts:22:48:22:57 | this.sink1 | view-component-input |
|
||||
| sink.component.ts:23:48:23:57 | this.sink2 | view-component-input |
|
||||
| sink.component.ts:24:48:24:57 | this.sink3 | view-component-input |
|
||||
| sink.component.ts:25:48:25:57 | this.sink4 | view-component-input |
|
||||
| sink.component.ts:26:48:26:57 | this.sink5 | view-component-input |
|
||||
| sink.component.ts:27:48:27:57 | this.sink6 | view-component-input |
|
||||
| sink.component.ts:28:48:28:57 | this.sink7 | view-component-input |
|
||||
| sink.component.ts:29:48:29:57 | this.sink8 | view-component-input |
|
||||
| sink.component.ts:30:48:30:57 | this.sink9 | view-component-input |
|
||||
|
||||
@@ -42,3 +42,7 @@ deprecated class LegacyConfig extends TaintTracking::Configuration {
|
||||
}
|
||||
|
||||
deprecated import utils.test.LegacyDataFlowDiff::DataFlowDiff<TestFlow, LegacyConfig>
|
||||
|
||||
query predicate threatModelSource(ThreatModelSource source, string kind) {
|
||||
kind = source.getThreatModel()
|
||||
}
|
||||
|
||||
@@ -318,3 +318,28 @@ test_JsxName_this
|
||||
| thisAccesses.js:61:19:61:41 | <this.t ... s.this> | thisAccesses.js:61:20:61:23 | this |
|
||||
locationSource
|
||||
| importedComponent.jsx:3:32:3:39 | location |
|
||||
threatModelSource
|
||||
| es5.js:4:24:4:33 | this.props | view-component-input |
|
||||
| es5.js:20:24:20:33 | this.props | view-component-input |
|
||||
| es6.js:1:37:1:36 | args | view-component-input |
|
||||
| es6.js:3:24:3:33 | this.props | view-component-input |
|
||||
| exportedComponent.jsx:1:29:1:33 | props | view-component-input |
|
||||
| importedComponent.jsx:3:24:3:40 | {color, location} | view-component-input |
|
||||
| importedComponent.jsx:3:32:3:39 | location | remote |
|
||||
| namedImport.js:3:27:3:26 | args | view-component-input |
|
||||
| namedImport.js:5:19:5:18 | args | view-component-input |
|
||||
| plainfn.js:1:16:1:20 | props | view-component-input |
|
||||
| plainfn.js:5:17:5:21 | props | view-component-input |
|
||||
| plainfn.js:9:17:9:21 | props | view-component-input |
|
||||
| plainfn.js:20:28:20:32 | props | view-component-input |
|
||||
| preact.js:1:38:1:37 | args | view-component-input |
|
||||
| preact.js:2:12:2:16 | props | view-component-input |
|
||||
| preact.js:9:38:9:37 | args | view-component-input |
|
||||
| probably-a-component.js:1:31:1:30 | args | view-component-input |
|
||||
| probably-a-component.js:3:9:3:18 | this.props | view-component-input |
|
||||
| props.js:2:37:2:36 | args | view-component-input |
|
||||
| props.js:26:16:26:20 | props | view-component-input |
|
||||
| rare-lifecycle-methods.js:1:33:1:32 | args | view-component-input |
|
||||
| statePropertyWrites.js:38:24:38:33 | this.props | view-component-input |
|
||||
| thisAccesses.js:31:12:31:16 | props | view-component-input |
|
||||
| thisAccesses.js:48:18:48:18 | y | view-component-input |
|
||||
|
||||
@@ -11,3 +11,7 @@ import ReactComponent_getAPropRead
|
||||
import ReactName
|
||||
|
||||
query DataFlow::SourceNode locationSource() { result = DOM::locationSource() }
|
||||
|
||||
query predicate threatModelSource(ThreatModelSource source, string kind) {
|
||||
kind = source.getThreatModel()
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data: function() { return { dataA: 42 } }
|
||||
props: ['input'],
|
||||
data: function() { return { dataA: 42 + this.input } }
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<script>
|
||||
var x = require('x');
|
||||
module.exports = { // not properly detected by the module system yet
|
||||
data: function() { return { dataA: 42 } }
|
||||
props: ['input'],
|
||||
data: function() { return { dataA: 42 + this.input } }
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var x = require('x');
|
||||
|
||||
module.exports = {
|
||||
data: function() { return { dataA: 42 } }
|
||||
props: ['input'],
|
||||
data: function() { return { dataA: 42 + this.input } }
|
||||
}
|
||||
|
||||
@@ -4,16 +4,22 @@
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import Component from 'vue-class-component'
|
||||
import { Prop } from 'vue-property-decorator'
|
||||
|
||||
@Component({
|
||||
render: (h) => { }
|
||||
})
|
||||
export default class MyComponent extends Vue {
|
||||
message: string = 'Hello!'
|
||||
@Prop() input: string;
|
||||
|
||||
get dataA() {
|
||||
return 42;
|
||||
}
|
||||
|
||||
get dataB() {
|
||||
return this.input;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
@@ -4,14 +4,20 @@
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import Component from 'vue-class-component'
|
||||
import { Prop } from 'vue-property-decorator'
|
||||
|
||||
@Component
|
||||
export default class MyComponent extends Vue {
|
||||
message: string = 'Hello!'
|
||||
@Prop() input: string;
|
||||
|
||||
get dataA() {
|
||||
return 42;
|
||||
}
|
||||
|
||||
get dataB() {
|
||||
return this.input;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<p v-html="input"/>
|
||||
</template>
|
||||
<script setup>
|
||||
const { input } = defineProps(['input']);
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<p v-html="input"/>
|
||||
</template>
|
||||
<script setup>
|
||||
const { input, numericInput, booleanInput } = defineProps({
|
||||
input: String,
|
||||
numericInput: Number,
|
||||
booleanInput: Boolean,
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<p v-html="input"/>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const { input, numericInput, booleanInput } = defineProps<{
|
||||
input: string,
|
||||
numericInput: number,
|
||||
booleanInput: boolean,
|
||||
}>();
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
@@ -1,12 +1,14 @@
|
||||
component_getAPropertyValue
|
||||
| compont-with-route.vue:0:0:0:0 | compont-with-route.vue | dataA | compont-with-route.vue:31:14:31:34 | this.$r ... ery.foo |
|
||||
| compont-with-route.vue:0:0:0:0 | compont-with-route.vue | message | compont-with-route.vue:19:15:19:22 | 'Hello!' |
|
||||
| single-component-file-1.vue:0:0:0:0 | single-component-file-1.vue | dataA | single-component-file-1.vue:6:40:6:41 | 42 |
|
||||
| single-file-component-3.vue:0:0:0:0 | single-file-component-3.vue | dataA | single-file-component-3-script.js:4:37:4:38 | 42 |
|
||||
| single-file-component-4.vue:0:0:0:0 | single-file-component-4.vue | dataA | single-file-component-4.vue:15:14:15:15 | 42 |
|
||||
| single-file-component-4.vue:0:0:0:0 | single-file-component-4.vue | message | single-file-component-4.vue:12:23:12:30 | 'Hello!' |
|
||||
| single-file-component-5.vue:0:0:0:0 | single-file-component-5.vue | dataA | single-file-component-5.vue:13:14:13:15 | 42 |
|
||||
| single-file-component-5.vue:0:0:0:0 | single-file-component-5.vue | message | single-file-component-5.vue:10:23:10:30 | 'Hello!' |
|
||||
| single-component-file-1.vue:0:0:0:0 | single-component-file-1.vue | dataA | single-component-file-1.vue:7:40:7:54 | 42 + this.input |
|
||||
| single-file-component-3.vue:0:0:0:0 | single-file-component-3.vue | dataA | single-file-component-3-script.js:5:37:5:51 | 42 + this.input |
|
||||
| single-file-component-4.vue:0:0:0:0 | single-file-component-4.vue | dataA | single-file-component-4.vue:17:14:17:15 | 42 |
|
||||
| single-file-component-4.vue:0:0:0:0 | single-file-component-4.vue | dataB | single-file-component-4.vue:21:14:21:23 | this.input |
|
||||
| single-file-component-4.vue:0:0:0:0 | single-file-component-4.vue | message | single-file-component-4.vue:13:23:13:30 | 'Hello!' |
|
||||
| single-file-component-5.vue:0:0:0:0 | single-file-component-5.vue | dataA | single-file-component-5.vue:15:14:15:15 | 42 |
|
||||
| single-file-component-5.vue:0:0:0:0 | single-file-component-5.vue | dataB | single-file-component-5.vue:19:14:19:23 | this.input |
|
||||
| single-file-component-5.vue:0:0:0:0 | single-file-component-5.vue | message | single-file-component-5.vue:11:23:11:30 | 'Hello!' |
|
||||
| tst.js:3:1:10:2 | new Vue ... 2\\n\\t}\\n}) | dataA | tst.js:8:10:8:11 | 42 |
|
||||
| tst.js:12:1:16:2 | new Vue ... \\t}),\\n}) | dataA | tst.js:14:10:14:11 | 42 |
|
||||
| tst.js:18:1:27:2 | Vue.com ... }\\n\\t}\\n}) | dataA | tst.js:20:10:20:11 | 42 |
|
||||
@@ -35,9 +37,11 @@ component_getAPropertyValue
|
||||
| tst.js:113:17:117:2 | base.ex ... 0\\n\\t}\\n}) | fromSubclass2 | tst.js:115:18:115:20 | 100 |
|
||||
component_getOption
|
||||
| compont-with-route.vue:0:0:0:0 | compont-with-route.vue | watch | compont-with-route.vue:10:12:16:5 | {\\n ... }\\n } |
|
||||
| single-component-file-1.vue:0:0:0:0 | single-component-file-1.vue | data | single-component-file-1.vue:6:11:6:45 | functio ... 42 } } |
|
||||
| single-file-component-3.vue:0:0:0:0 | single-file-component-3.vue | data | single-file-component-3-script.js:4:8:4:42 | functio ... 42 } } |
|
||||
| single-file-component-4.vue:0:0:0:0 | single-file-component-4.vue | render | single-file-component-4.vue:9:13:9:22 | (h) => { } |
|
||||
| single-component-file-1.vue:0:0:0:0 | single-component-file-1.vue | data | single-component-file-1.vue:7:11:7:58 | functio ... put } } |
|
||||
| single-component-file-1.vue:0:0:0:0 | single-component-file-1.vue | props | single-component-file-1.vue:6:12:6:20 | ['input'] |
|
||||
| single-file-component-3.vue:0:0:0:0 | single-file-component-3.vue | data | single-file-component-3-script.js:5:8:5:55 | functio ... put } } |
|
||||
| single-file-component-3.vue:0:0:0:0 | single-file-component-3.vue | props | single-file-component-3-script.js:4:9:4:17 | ['input'] |
|
||||
| single-file-component-4.vue:0:0:0:0 | single-file-component-4.vue | render | single-file-component-4.vue:10:13:10:22 | (h) => { } |
|
||||
| tst.js:3:1:10:2 | new Vue ... 2\\n\\t}\\n}) | data | tst.js:7:8:9:2 | {\\n\\t\\tdataA: 42\\n\\t} |
|
||||
| tst.js:3:1:10:2 | new Vue ... 2\\n\\t}\\n}) | render | tst.js:4:10:6:2 | functio ... c);\\n\\t} |
|
||||
| tst.js:12:1:16:2 | new Vue ... \\t}),\\n}) | data | tst.js:13:8:15:3 | () => ( ... 42\\n\\t}) |
|
||||
@@ -76,6 +80,9 @@ component
|
||||
| single-file-component-3.vue:0:0:0:0 | single-file-component-3.vue |
|
||||
| single-file-component-4.vue:0:0:0:0 | single-file-component-4.vue |
|
||||
| single-file-component-5.vue:0:0:0:0 | single-file-component-5.vue |
|
||||
| single-file-component-6.vue:0:0:0:0 | single-file-component-6.vue |
|
||||
| single-file-component-7.vue:0:0:0:0 | single-file-component-7.vue |
|
||||
| single-file-component-8.vue:0:0:0:0 | single-file-component-8.vue |
|
||||
| special-syntax.vue:0:0:0:0 | special-syntax.vue |
|
||||
| tst.js:3:1:10:2 | new Vue ... 2\\n\\t}\\n}) |
|
||||
| tst.js:12:1:16:2 | new Vue ... \\t}),\\n}) |
|
||||
@@ -97,10 +104,10 @@ component
|
||||
| tst.js:113:17:117:2 | base.ex ... 0\\n\\t}\\n}) |
|
||||
viewComponentStep
|
||||
| compont-with-route.vue:31:14:31:34 | this.$r ... ery.foo | compont-with-route.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-component-file-1.vue:6:40:6:41 | 42 | single-component-file-1.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-3-script.js:4:37:4:38 | 42 | single-file-component-3.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-4.vue:15:14:15:15 | 42 | single-file-component-4.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-5.vue:13:14:13:15 | 42 | single-file-component-5.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-component-file-1.vue:7:40:7:54 | 42 + this.input | single-component-file-1.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-3-script.js:5:37:5:51 | 42 + this.input | single-file-component-3.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-4.vue:17:14:17:15 | 42 | single-file-component-4.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-5.vue:15:14:15:15 | 42 | single-file-component-5.vue:2:8:2:21 | v-html=dataA |
|
||||
| tst.js:100:18:100:19 | 42 | tst.js:102:20:102:29 | this.dataA |
|
||||
templateElement
|
||||
| compont-with-route.vue:1:1:3:11 | <template>...</> |
|
||||
@@ -108,25 +115,37 @@ templateElement
|
||||
| compont-with-route.vue:4:1:49:9 | <script>...</> |
|
||||
| compont-with-route.vue:50:1:51:8 | <style>...</> |
|
||||
| single-component-file-1.vue:1:1:3:11 | <template>...</> |
|
||||
| single-component-file-1.vue:2:5:10:8 | <p>...</> |
|
||||
| single-component-file-1.vue:4:1:8:9 | <script>...</> |
|
||||
| single-component-file-1.vue:9:1:10:8 | <style>...</> |
|
||||
| single-component-file-1.vue:2:5:11:8 | <p>...</> |
|
||||
| single-component-file-1.vue:4:1:9:9 | <script>...</> |
|
||||
| single-component-file-1.vue:10:1:11:8 | <style>...</> |
|
||||
| single-file-component-2.vue:1:1:3:11 | <template>...</> |
|
||||
| single-file-component-2.vue:2:5:11:8 | <p>...</> |
|
||||
| single-file-component-2.vue:4:1:9:9 | <script>...</> |
|
||||
| single-file-component-2.vue:10:1:11:8 | <style>...</> |
|
||||
| single-file-component-2.vue:2:5:12:8 | <p>...</> |
|
||||
| single-file-component-2.vue:4:1:10:9 | <script>...</> |
|
||||
| single-file-component-2.vue:11:1:12:8 | <style>...</> |
|
||||
| single-file-component-3.vue:1:1:3:11 | <template>...</> |
|
||||
| single-file-component-3.vue:2:5:7:8 | <p>...</> |
|
||||
| single-file-component-3.vue:4:1:5:9 | <script>...</> |
|
||||
| single-file-component-3.vue:6:1:7:8 | <style>...</> |
|
||||
| single-file-component-4.vue:1:1:3:11 | <template>...</> |
|
||||
| single-file-component-4.vue:2:5:20:9 | <p>...</> |
|
||||
| single-file-component-4.vue:4:1:18:9 | <script>...</> |
|
||||
| single-file-component-4.vue:19:1:20:8 | <style>...</> |
|
||||
| single-file-component-4.vue:2:5:26:9 | <p>...</> |
|
||||
| single-file-component-4.vue:4:1:24:9 | <script>...</> |
|
||||
| single-file-component-4.vue:25:1:26:8 | <style>...</> |
|
||||
| single-file-component-5.vue:1:1:3:11 | <template>...</> |
|
||||
| single-file-component-5.vue:2:5:18:9 | <p>...</> |
|
||||
| single-file-component-5.vue:4:1:16:9 | <script>...</> |
|
||||
| single-file-component-5.vue:17:1:18:8 | <style>...</> |
|
||||
| single-file-component-5.vue:2:5:24:9 | <p>...</> |
|
||||
| single-file-component-5.vue:4:1:22:9 | <script>...</> |
|
||||
| single-file-component-5.vue:23:1:24:8 | <style>...</> |
|
||||
| single-file-component-6.vue:1:1:3:11 | <template>...</> |
|
||||
| single-file-component-6.vue:2:5:8:9 | <p>...</> |
|
||||
| single-file-component-6.vue:4:1:6:9 | <script>...</> |
|
||||
| single-file-component-6.vue:7:1:8:8 | <style>...</> |
|
||||
| single-file-component-7.vue:1:1:3:11 | <template>...</> |
|
||||
| single-file-component-7.vue:2:5:12:9 | <p>...</> |
|
||||
| single-file-component-7.vue:4:1:10:9 | <script>...</> |
|
||||
| single-file-component-7.vue:11:1:12:8 | <style>...</> |
|
||||
| single-file-component-8.vue:1:1:3:11 | <template>...</> |
|
||||
| single-file-component-8.vue:2:5:12:9 | <p>...</> |
|
||||
| single-file-component-8.vue:4:1:10:9 | <script>...</> |
|
||||
| single-file-component-8.vue:11:1:12:8 | <style>...</> |
|
||||
| special-syntax.vue:1:1:4:11 | <template>...</> |
|
||||
| special-syntax.vue:2:3:2:37 | <blah>...</> |
|
||||
| special-syntax.vue:3:3:3:32 | <blah>...</> |
|
||||
@@ -138,6 +157,9 @@ xssSink
|
||||
| single-file-component-3.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-4.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-5.vue:2:8:2:21 | v-html=dataA |
|
||||
| single-file-component-6.vue:2:8:2:21 | v-html=input |
|
||||
| single-file-component-7.vue:2:8:2:21 | v-html=input |
|
||||
| single-file-component-8.vue:2:8:2:21 | v-html=input |
|
||||
| tst.js:5:13:5:13 | a |
|
||||
| tst.js:38:12:38:17 | danger |
|
||||
remoteFlowSource
|
||||
@@ -175,6 +197,46 @@ attribute
|
||||
| single-file-component-3.vue:4:9:4:49 | src=./single-file-component-3-script.js | src |
|
||||
| single-file-component-4.vue:2:8:2:21 | v-html=dataA | v-html |
|
||||
| single-file-component-5.vue:2:8:2:21 | v-html=dataA | v-html |
|
||||
| single-file-component-6.vue:2:8:2:21 | v-html=input | v-html |
|
||||
| single-file-component-6.vue:4:9:4:13 | setup= | setup |
|
||||
| single-file-component-7.vue:2:8:2:21 | v-html=input | v-html |
|
||||
| single-file-component-7.vue:4:9:4:13 | setup= | setup |
|
||||
| single-file-component-8.vue:2:8:2:21 | v-html=input | v-html |
|
||||
| single-file-component-8.vue:4:9:4:13 | setup= | setup |
|
||||
| single-file-component-8.vue:4:15:4:23 | lang=ts | lang |
|
||||
| special-syntax.vue:2:9:2:22 | :colonProp=x | :colonProp |
|
||||
| special-syntax.vue:2:24:2:34 | @atProp=x | @atProp |
|
||||
| special-syntax.vue:3:9:3:29 | :colonField.field=x | :colonField.field |
|
||||
threatModelSource
|
||||
| compont-with-route.vue:13:17:13:21 | newId | remote |
|
||||
| compont-with-route.vue:13:24:13:28 | oldId | remote |
|
||||
| compont-with-route.vue:22:7:22:24 | this.$route.params | remote |
|
||||
| compont-with-route.vue:23:7:23:23 | this.$route.query | remote |
|
||||
| compont-with-route.vue:24:7:24:22 | this.$route.hash | remote |
|
||||
| compont-with-route.vue:25:7:25:22 | this.$route.path | remote |
|
||||
| compont-with-route.vue:26:7:26:26 | this.$route.fullPath | remote |
|
||||
| compont-with-route.vue:27:7:27:31 | router. ... e.query | remote |
|
||||
| compont-with-route.vue:31:14:31:30 | this.$route.query | remote |
|
||||
| compont-with-route.vue:35:7:35:14 | to.query | remote |
|
||||
| compont-with-route.vue:36:7:36:16 | from.query | remote |
|
||||
| compont-with-route.vue:40:7:40:14 | to.query | remote |
|
||||
| compont-with-route.vue:41:7:41:16 | from.query | remote |
|
||||
| compont-with-route.vue:45:7:45:14 | to.query | remote |
|
||||
| compont-with-route.vue:46:7:46:16 | from.query | remote |
|
||||
| router.js:8:17:8:24 | to.query | remote |
|
||||
| router.js:9:17:9:26 | from.query | remote |
|
||||
| router.js:15:25:15:32 | to.query | remote |
|
||||
| router.js:16:25:16:34 | from.query | remote |
|
||||
| router.js:23:9:23:16 | to.query | remote |
|
||||
| router.js:24:9:24:18 | from.query | remote |
|
||||
| router.js:29:5:29:12 | to.query | remote |
|
||||
| router.js:30:5:30:14 | from.query | remote |
|
||||
| router.js:34:5:34:12 | to.query | remote |
|
||||
| router.js:35:5:35:14 | from.query | remote |
|
||||
| single-component-file-1.vue:7:45:7:54 | this.input | view-component-input |
|
||||
| single-file-component-3-script.js:5:42:5:51 | this.input | view-component-input |
|
||||
| single-file-component-4.vue:21:14:21:23 | this.input | view-component-input |
|
||||
| single-file-component-5.vue:19:14:19:23 | this.input | view-component-input |
|
||||
| single-file-component-6.vue:5:11:5:15 | input | view-component-input |
|
||||
| single-file-component-7.vue:5:11:5:15 | input | view-component-input |
|
||||
| single-file-component-8.vue:5:11:5:15 | input | view-component-input |
|
||||
|
||||
@@ -24,3 +24,7 @@ query RemoteFlowSource remoteFlowSource() { any() }
|
||||
query predicate parseErrors(JSParseError err) { exists(err) }
|
||||
|
||||
query predicate attribute(HTML::Attribute attrib, string name) { attrib.getName() = name }
|
||||
|
||||
query predicate threatModelSource(ThreatModelSource source, string kind) {
|
||||
kind = source.getThreatModel()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user