feat: security implementation in Angular 2.
Summary: This adds basic security hooks to Angular 2. * `SecurityContext` is a private API between core, compiler, and platform-browser. `SecurityContext` communicates what context a value is used in across template parser, compiler, and sanitization at runtime. * `SanitizationService` is the bare bones interface to sanitize values for a particular context. * `SchemaElementRegistry.securityContext(tagName, attributeOrPropertyName)` determines the security context for an attribute or property (it turns out attributes and properties match for the purposes of sanitization). Based on these hooks: * `DomSchemaElementRegistry` decides what sanitization applies in a particular context. * `DomSanitizationService` implements `SanitizationService` and adds *Safe Value*s, i.e. the ability to mark a value as safe and not requiring further sanitization. * `url_sanitizer` and `style_sanitizer` sanitize URLs and Styles, respectively (surprise!). `DomSanitizationService` is the default implementation bound for browser applications, in the three contexts (browser rendering, web worker rendering, server side rendering). BREAKING CHANGES: *** SECURITY WARNING *** Angular 2 Release Candidates do not implement proper contextual escaping yet. Make sure to correctly escape all values that go into the DOM. *** SECURITY WARNING *** Reviewers: IgorMinar Differential Revision: https://reviews.angular.io/D103
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
import {SecurityContext} from '../../core_private';
|
||||
import {LifecycleHooks, isDefaultChangeDetectionStrategy} from '../../core_private';
|
||||
|
||||
import {isBlank, isPresent} from '../../src/facade/lang';
|
||||
@ -5,7 +6,7 @@ import {isBlank, isPresent} from '../../src/facade/lang';
|
||||
import * as cdAst from '../expression_parser/ast';
|
||||
import * as o from '../output/output_ast';
|
||||
import {Identifiers} from '../identifiers';
|
||||
import {DetectChangesVars} from './constants';
|
||||
import {DetectChangesVars, ViewProperties} from './constants';
|
||||
|
||||
import {
|
||||
BoundTextAst,
|
||||
@ -30,7 +31,7 @@ function createBindFieldExpr(exprIndex: number): o.ReadPropExpr {
|
||||
}
|
||||
|
||||
function createCurrValueExpr(exprIndex: number): o.ReadVarExpr {
|
||||
return o.variable(`currVal_${exprIndex}`);
|
||||
return o.variable(`currVal_${exprIndex}`); // fix syntax highlighting: `
|
||||
}
|
||||
|
||||
function bind(view: CompileView, currValExpr: o.ReadVarExpr, fieldExpr: o.ReadPropExpr,
|
||||
@ -94,7 +95,7 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context:
|
||||
var fieldExpr = createBindFieldExpr(bindingIndex);
|
||||
var currValExpr = createCurrValueExpr(bindingIndex);
|
||||
var renderMethod: string;
|
||||
var renderValue: o.Expression = currValExpr;
|
||||
var renderValue: o.Expression = sanitizedValue(boundProp, currValExpr);
|
||||
var updateStmts = [];
|
||||
switch (boundProp.type) {
|
||||
case PropertyBindingType.Property:
|
||||
@ -130,6 +131,34 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context:
|
||||
});
|
||||
}
|
||||
|
||||
function sanitizedValue(boundProp: BoundElementPropertyAst, renderValue: o.Expression): o.Expression {
|
||||
let enumValue: string;
|
||||
switch (boundProp.securityContext) {
|
||||
case SecurityContext.NONE:
|
||||
return renderValue; // No sanitization needed.
|
||||
case SecurityContext.HTML:
|
||||
enumValue = 'HTML';
|
||||
break;
|
||||
case SecurityContext.STYLE:
|
||||
enumValue = 'STYLE';
|
||||
break;
|
||||
case SecurityContext.SCRIPT:
|
||||
enumValue = 'SCRIPT';
|
||||
break;
|
||||
case SecurityContext.URL:
|
||||
enumValue = 'URL';
|
||||
break;
|
||||
case SecurityContext.RESOURCE_URL:
|
||||
enumValue = 'RESOURCE_URL';
|
||||
break;
|
||||
default:
|
||||
throw new Error(`internal error, unexpected SecurityContext ${boundProp.securityContext}.`);
|
||||
}
|
||||
let ctx = ViewProperties.viewUtils.prop('sanitizer');
|
||||
let args = [o.importExpr(Identifiers.SecurityContext).prop(enumValue), renderValue];
|
||||
return ctx.callMethod('sanitize', args);
|
||||
}
|
||||
|
||||
export function bindRenderInputs(boundProps: BoundElementPropertyAst[],
|
||||
compileElement: CompileElement): void {
|
||||
bindAndWriteToRenderer(boundProps, compileElement.view.componentContext, compileElement);
|
||||
|
@ -214,7 +214,7 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
||||
var nestedComponentIdentifier =
|
||||
new CompileIdentifierMetadata({name: getViewFactoryName(component, 0)});
|
||||
this.targetDependencies.push(new ViewCompileDependency(component, nestedComponentIdentifier));
|
||||
compViewExpr = o.variable(`compView_${nodeIndex}`);
|
||||
compViewExpr = o.variable(`compView_${nodeIndex}`); // fix highlighting: `
|
||||
compileElement.setComponentView(compViewExpr);
|
||||
this.view.createMethod.addStmt(compViewExpr.set(o.importExpr(nestedComponentIdentifier)
|
||||
.callFn([
|
||||
@ -336,7 +336,8 @@ function mapToKeyValueArray(data: {[key: string]: string}): string[][] {
|
||||
function createViewTopLevelStmts(view: CompileView, targetStatements: o.Statement[]) {
|
||||
var nodeDebugInfosVar: o.Expression = o.NULL_EXPR;
|
||||
if (view.genConfig.genDebugInfo) {
|
||||
nodeDebugInfosVar = o.variable(`nodeDebugInfos_${view.component.type.name}${view.viewIndex}`);
|
||||
nodeDebugInfosVar = o.variable(
|
||||
`nodeDebugInfos_${view.component.type.name}${view.viewIndex}`); // fix highlighting: `
|
||||
targetStatements.push(
|
||||
(<o.ReadVarExpr>nodeDebugInfosVar)
|
||||
.set(o.literalArr(view.nodes.map(createStaticNodeDebugInfo),
|
||||
@ -346,7 +347,8 @@ function createViewTopLevelStmts(view: CompileView, targetStatements: o.Statemen
|
||||
}
|
||||
|
||||
|
||||
var renderCompTypeVar: o.ReadVarExpr = o.variable(`renderType_${view.component.type.name}`);
|
||||
var renderCompTypeVar: o.ReadVarExpr =
|
||||
o.variable(`renderType_${view.component.type.name}`); // fix highlighting: `
|
||||
if (view.viewIndex === 0) {
|
||||
targetStatements.push(renderCompTypeVar.set(o.NULL_EXPR)
|
||||
.toDeclStmt(o.importType(Identifiers.RenderComponentType)));
|
||||
|
Reference in New Issue
Block a user