feat(security): fill in missing security contexts.

Reviewers: koto, rjamet, molnarg

Differential Revision: https://reviews.angular.io/D109
This commit is contained in:
Martin Probst 2016-05-04 10:26:17 -07:00
parent 6d36a7a45f
commit 67ed2e2c0a
2 changed files with 59 additions and 7 deletions

View File

@ -206,6 +206,53 @@ var attrToPropMap: {[name: string]: string} = <any>{
'tabindex': 'tabIndex'
};
function registerContext(map: {[k: string]: SecurityContext}, ctx: SecurityContext, specs: string[]) {
for (let spec of specs) map[spec] = ctx;
}
/** Map from tagName|propertyName SecurityContext. Properties applying to all tags use '*'. */
const SECURITY_SCHEMA: {[k: string]: SecurityContext} = {};
registerContext(SECURITY_SCHEMA, SecurityContext.HTML, [
'iframe|srcdoc',
'*|innerHTML',
'*|outerHTML',
]);
registerContext(SECURITY_SCHEMA, SecurityContext.STYLE, ['*|style']);
// NB: no SCRIPT contexts here, they are never allowed.
registerContext(SECURITY_SCHEMA, SecurityContext.URL, [
'area|href',
'area|ping',
'audio|src',
'a|href',
'a|ping',
'blockquote|cite',
'body|background',
'button|formaction',
'del|cite',
'form|action',
'img|src',
'input|formaction',
'input|src',
'ins|cite',
'q|cite',
'source|src',
'video|poster',
'video|src',
]);
registerContext(SECURITY_SCHEMA, SecurityContext.RESOURCE_URL, [
'applet|code',
'applet|codebase',
'base|href',
'frame|src',
'head|profile',
'html|manifest',
'iframe|src',
'object|codebase',
'object|data',
'script|src',
'track|src',
]);
@Injectable()
export class DomElementSchemaRegistry extends ElementSchemaRegistry {
@ -267,11 +314,10 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
* attack vectors are assigned their appropriate context.
*/
securityContext(tagName: string, propName: string): SecurityContext {
// TODO(martinprobst): Fill in missing properties.
if (propName === 'style') return SecurityContext.STYLE;
if (tagName === 'a' && propName === 'href') return SecurityContext.URL;
if (propName === 'innerHTML') return SecurityContext.HTML;
return SecurityContext.NONE;
let ctx = SECURITY_SCHEMA[tagName + '|' + propName];
if (ctx !== undefined) return ctx;
ctx = SECURITY_SCHEMA['*|' + propName];
return ctx !== undefined ? ctx : SecurityContext.NONE;
}
getMappedPropName(propName: string): string {

View File

@ -57,8 +57,14 @@ export function main() {
expect(registry.getMappedPropName('exotic-unknown')).toEqual('exotic-unknown');
});
it('should return security contexts for elements',
() => { expect(registry.securityContext('a', 'href')).toBe(SecurityContext.URL); });
it('should return security contexts for elements', () => {
expect(registry.securityContext('iframe', 'srcdoc')).toBe(SecurityContext.HTML);
expect(registry.securityContext('p', 'innerHTML')).toBe(SecurityContext.HTML);
expect(registry.securityContext('a', 'href')).toBe(SecurityContext.URL);
expect(registry.securityContext('a', 'style')).toBe(SecurityContext.STYLE);
expect(registry.securityContext('ins', 'cite')).toBe(SecurityContext.URL);
expect(registry.securityContext('base', 'href')).toBe(SecurityContext.RESOURCE_URL);
});
it('should detect properties on namespaced elements',
() => { expect(registry.hasProperty('@svg:g', 'id')).toBeTruthy(); });