feat(security): fill in missing security contexts.
Reviewers: koto, rjamet, molnarg Differential Revision: https://reviews.angular.io/D109
This commit is contained in:
parent
6d36a7a45f
commit
67ed2e2c0a
|
@ -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 {
|
||||
|
|
|
@ -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(); });
|
||||
|
|
Loading…
Reference in New Issue