Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 393b84c

Browse files
SkyZeroZxatscott
authored andcommitted
fix(compiler): sanitize two-way properties
Apply schema-derived sanitizer resolution to TwoWayProperty ops so native two-way DOM bindings emit the same sanitizer as one-way property bindings. Add compiler compliance coverage for innerHTML, srcdoc, URL, resource URL, and security-sensitive attribute cases. (cherry picked from commit 3c70270)
1 parent 60d88b1 commit 393b84c

4 files changed

Lines changed: 47 additions & 3 deletions

File tree

‎packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,15 @@ export class MyComponent {
897897
<iframe [sandbox]="evil"></iframe>
898898
<a href="{{evil}}{{evil}}"></a>
899899
<div attr.style="{{evil}}{{evil}}"></div>
900+
<div [(innerHTML)]="evil"></div>
901+
<div bindon-innerHTML="evil"></div>
902+
<iframe [(srcdoc)]="evil"></iframe>
903+
<iframe bindon-srcdoc="evil"></iframe>
904+
<img [(src)]="evil" />
905+
<iframe [(src)]="evil"></iframe>
906+
<object [(data)]="evil"></object>
907+
<link [(href)]="evil" />
908+
<iframe [(sandbox)]="evil"></iframe>
900909
`, isInline: true });
901910
}
902911
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyComponent, decorators: [{
@@ -911,6 +920,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE
911920
<iframe [sandbox]="evil"></iframe>
912921
<a href="{{evil}}{{evil}}"></a>
913922
<div attr.style="{{evil}}{{evil}}"></div>
923+
<div [(innerHTML)]="evil"></div>
924+
<div bindon-innerHTML="evil"></div>
925+
<iframe [(srcdoc)]="evil"></iframe>
926+
<iframe bindon-srcdoc="evil"></iframe>
927+
<img [(src)]="evil" />
928+
<iframe [(src)]="evil"></iframe>
929+
<object [(data)]="evil"></object>
930+
<link [(href)]="evil" />
931+
<iframe [(sandbox)]="evil"></iframe>
914932
`
915933
}]
916934
}] });

‎packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/sanitization.js‎

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
template: function MyComponent_Template(rf, ctx) {
2-
if (rf & 1) {
3-
$r3$.ɵɵdomElement(0, "div", 0)(1, "link", 1)(2, "div")(3, "img", 2)(4, "iframe", 3)(5, "a", 1)(6, "div");
4-
}
2+
…
53
if (rf & 2) {
64
$r3$.ɵɵdomProperty("innerHTML", ctx.evil, $r3$.ɵɵsanitizeHtml);
75
$r3$.ɵɵadvance();
@@ -16,5 +14,23 @@ template: function MyComponent_Template(rf, ctx) {
1614
$r3$.ɵɵdomProperty("href", $r3$.ɵɵinterpolate2("", ctx.evil, "", ctx.evil), $r3$.ɵɵsanitizeUrl);
1715
$r3$.ɵɵadvance();
1816
$r3$.ɵɵattribute("style", $r3$.ɵɵinterpolate2("", ctx.evil, "", ctx.evil), $r3$.ɵɵsanitizeStyle);
17+
$r3$.ɵɵadvance();
18+
$r3$.ɵɵtwoWayProperty("innerHTML", ctx.evil, $r3$.ɵɵsanitizeHtml);
19+
$r3$.ɵɵadvance();
20+
$r3$.ɵɵtwoWayProperty("innerHTML", ctx.evil, $r3$.ɵɵsanitizeHtml);
21+
$r3$.ɵɵadvance();
22+
$r3$.ɵɵtwoWayProperty("srcdoc", ctx.evil, $r3$.ɵɵsanitizeHtml);
23+
$r3$.ɵɵadvance();
24+
$r3$.ɵɵtwoWayProperty("srcdoc", ctx.evil, $r3$.ɵɵsanitizeHtml);
25+
$r3$.ɵɵadvance();
26+
$r3$.ɵɵtwoWayProperty("src", ctx.evil, $r3$.ɵɵsanitizeUrl);
27+
$r3$.ɵɵadvance();
28+
$r3$.ɵɵtwoWayProperty("src", ctx.evil, $r3$.ɵɵsanitizeResourceUrl);
29+
$r3$.ɵɵadvance();
30+
$r3$.ɵɵtwoWayProperty("data", ctx.evil, $r3$.ɵɵsanitizeResourceUrl);
31+
$r3$.ɵɵadvance();
32+
$r3$.ɵɵtwoWayProperty("href", ctx.evil, $r3$.ɵɵsanitizeResourceUrl);
33+
$r3$.ɵɵadvance();
34+
$r3$.ɵɵtwoWayProperty("sandbox", ctx.evil, $r3$.ɵɵvalidateAttribute);
1935
}
2036
}

‎packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/sanitization.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ import {Component} from '@angular/core';
1010
<iframe [sandbox]="evil"></iframe>
1111
<a href="{{evil}}{{evil}}"></a>
1212
<div attr.style="{{evil}}{{evil}}"></div>
13+
<div [(innerHTML)]="evil"></div>
14+
<div bindon-innerHTML="evil"></div>
15+
<iframe [(srcdoc)]="evil"></iframe>
16+
<iframe bindon-srcdoc="evil"></iframe>
17+
<img [(src)]="evil" />
18+
<iframe [(src)]="evil"></iframe>
19+
<object [(data)]="evil"></object>
20+
<link [(href)]="evil" />
21+
<iframe [(sandbox)]="evil"></iframe>
1322
`
1423
})
1524
export class MyComponent {

‎packages/compiler/src/template/pipeline/src/phases/resolve_sanitizers.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function resolveSanitizers(job: CompilationJob): void {
5656
case ir.OpKind.Property:
5757
case ir.OpKind.Attribute:
5858
case ir.OpKind.DomProperty:
59+
case ir.OpKind.TwoWayProperty:
5960
let sanitizerFn: o.ExternalReference | null = null;
6061
if (
6162
Array.isArray(op.securityContext) &&

0 commit comments

Comments
 (0)