Merge pull request #4958 from asgerf/js/angular2

Approved by erik-krogh
This commit is contained in:
CodeQL CI
2021-01-26 02:53:33 -08:00
committed by GitHub
69 changed files with 37278 additions and 1267 deletions

View File

@@ -97,6 +97,7 @@ typeInferenceMismatch
| promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) |
| promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) |
| promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise |
| rxjs.js:3:1:3:8 | source() | rxjs.js:10:14:10:17 | data |
| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint |
| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:33:14:33:18 | taint |
| sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x |

View File

@@ -0,0 +1,11 @@
import { map, catchError } from 'rxjs/operators';
source()
.pipe(
map(x => x + 'foo'),
map(x => x + 'bar'),
catchError(err => {})
)
.subscribe(data => {
sink(data)
});

View File

@@ -0,0 +1,9 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'testPipe'})
export class TestPipe implements PipeTransform {
transform(value: string, arg?: string): string {
document.body.innerHTML = value;
return value + arg;
}
}

View File

@@ -0,0 +1,17 @@
import { Input, Component } from '@angular/core';
@Component({
selector: 'mid-component',
template: `
<sink-component [sink7]="taint"></sink-component>
\n<sink-component [sink9]="taint" [testAttr]="taint"></sink-component>
`
})
export class InlineComponent {
taint: string;
constructor() {
this.taint = source();
}
}

View File

@@ -0,0 +1 @@
<sink-component [sink6]="field"></sink-component>

View File

@@ -0,0 +1,9 @@
import { Input, Component } from '@angular/core';
@Component({
selector: 'mid-component',
templateUrl: './mid.component.html'
})
export class MidComponent {
@Input() field: string;
}

View File

@@ -0,0 +1,32 @@
import { Component } from "@angular/core";
import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: "sink-component",
template: "not important"
})
export class SinkComponent {
sink1: string;
sink2: string;
sink3: string;
sink4: string;
sink5: string;
sink6: string;
sink7: string;
sink8: string;
sink9: string;
constructor(private sanitizer: DomSanitizer) {}
foo() {
this.sanitizer.bypassSecurityTrustHtml(this.sink1);
this.sanitizer.bypassSecurityTrustHtml(this.sink2);
this.sanitizer.bypassSecurityTrustHtml(this.sink3);
this.sanitizer.bypassSecurityTrustHtml(this.sink4);
this.sanitizer.bypassSecurityTrustHtml(this.sink5);
this.sanitizer.bypassSecurityTrustHtml(this.sink6);
this.sanitizer.bypassSecurityTrustHtml(this.sink7);
this.sanitizer.bypassSecurityTrustHtml(this.sink8);
this.sanitizer.bypassSecurityTrustHtml(this.sink9);
}
}

View File

@@ -0,0 +1,19 @@
<sink-component
[sink1]="taint"
[sink2]="taint | unknownPipe"
[sink3]="taint | unknownPipe:'safe'"
[sink4]="taint | testPipe:'safe'"
[sink5]="42 | testPipe:taint"
(someEvent)="methodOnComponent(taint)"
[sink8]="$any(taint)"
></sink-component>
<div *ngFor="let element of taintedArray">
<sink-component [sink1]="element"></sink-component>
</div>
<div *ngFor="let element of safeArray">
<sink-component [sink2]="element"></sink-component>
</div>
<mid-component [field]="taint"></mid-component>

View File

@@ -0,0 +1,22 @@
import { Component } from "@angular/core";
import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: "source-component",
templateUrl: "./source.component.html"
})
export class Source {
taint: string;
taintedArray: string[];
safeArray: string[];
constructor(private sanitizer: DomSanitizer) {
this.taint = source();
this.taintedArray = [...source()];
this.safeArray = ['a', 'b'];
}
methodOnComponent(x) {
this.sanitizer.bypassSecurityTrustHtml(x);
}
}

View File

@@ -0,0 +1,36 @@
pipeRef
| source.component.html:3:22:3:32 | unknownPipe |
| source.component.html:4:22:4:32 | unknownPipe |
| source.component.html:5:22:5:29 | testPipe |
| source.component.html:6:19:6:26 | testPipe |
pipeCall
| source.component.html:3:14:3:32 | taint \| unknownPipe |
| source.component.html:4:14:4:39 | taint \| ... :'safe' |
| source.component.html:5:14:5:36 | taint \| ... :'safe' |
| source.component.html:6:14:6:32 | 42 \| testPipe:taint |
pipeCallArg
| 0 | source.component.html:3:14:3:18 | taint | source.component.html:3:14:3:32 | taint \| unknownPipe |
| 0 | source.component.html:4:14:4:18 | taint | source.component.html:4:14:4:39 | taint \| ... :'safe' |
| 0 | source.component.html:5:14:5:18 | taint | source.component.html:5:14:5:36 | taint \| ... :'safe' |
| 0 | source.component.html:6:14:6:15 | 42 | source.component.html:6:14:6:32 | 42 \| testPipe:taint |
| 1 | source.component.html:4:34:4:39 | 'safe' | source.component.html:4:14:4:39 | taint \| ... :'safe' |
| 1 | source.component.html:5:31:5:36 | 'safe' | source.component.html:5:14:5:36 | taint \| ... :'safe' |
| 1 | source.component.html:6:28:6:32 | taint | source.component.html:6:14:6:32 | 42 \| testPipe:taint |
pipeClass
| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} |
pipeClassRef
| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:5:22:5:29 | testPipe |
| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe |
taintFlow
| inline.component.ts:15:22:15:29 | source() | sink.component.ts:28:48:28:57 | this.sink7 |
| inline.component.ts:15:22:15:29 | source() | sink.component.ts:30:48:30:57 | this.sink9 |
| source.component.ts:14:22:14:29 | source() | TestPipe.ts:6:31:6:35 | value |
| source.component.ts:14:22:14:29 | source() | sink.component.ts:22:48:22:57 | this.sink1 |
| source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink4 |
| source.component.ts:14:22:14:29 | source() | sink.component.ts:26:48:26:57 | this.sink5 |
| source.component.ts:14:22:14:29 | source() | sink.component.ts:27:48:27:57 | this.sink6 |
| source.component.ts:14:22:14:29 | source() | sink.component.ts:29:48:29:57 | this.sink8 |
| source.component.ts:14:22:14:29 | source() | source.component.ts:20:48:20:48 | x |
| source.component.ts:15:33:15:40 | source() | sink.component.ts:22:48:22:57 | this.sink1 |
testAttrSourceLocation
| inline.component.ts:8:43:8:61 | [testAttr]=taint | inline.component.ts:8:55:8:59 | <toplevel> |

View File

@@ -0,0 +1,34 @@
import javascript
private import semmle.javascript.security.dataflow.Xss
query Angular2::PipeRefExpr pipeRef() { any() }
query CallExpr pipeCall() { result.getCallee() instanceof Angular2::PipeRefExpr }
query CallExpr pipeCallArg(int i, Expr arg) {
result.getCallee() instanceof Angular2::PipeRefExpr and
result.getArgument(i) = arg
}
query Angular2::PipeClass pipeClass() { any() }
query DataFlow::Node pipeClassRef(Angular2::PipeClass cls) { result = cls.getAPipeRef() }
class TaintConfig extends TaintTracking::Configuration {
TaintConfig() { this = "TaintConfig" }
override predicate isSource(DataFlow::Node source) {
source.(DataFlow::CallNode).getCalleeName() = "source"
}
override predicate isSink(DataFlow::Node sink) { sink instanceof DomBasedXss::Sink }
}
query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) {
any(TaintConfig c).hasFlow(source, sink)
}
query predicate testAttrSourceLocation(HTML::Attribute attrib, Angular2::TemplateTopLevel top) {
attrib.getName() = "[testAttr]" and
top = attrib.getCodeInAttribute()
}