Skip to content

Commit c2dcf4e

Browse files
committed
fixup! fix(core): sanitize meta selectors
1 parent 8a0047e commit c2dcf4e

2 files changed

Lines changed: 25 additions & 2 deletions

File tree

packages/platform-browser/src/browser/meta.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ export class Meta {
102102
*/
103103
getTag(attrSelector: string): HTMLMetaElement | null {
104104
if (!attrSelector) return null;
105-
return this._doc.querySelector(`meta[${attrSelector}]`) || null;
105+
const meta = this._doc.querySelector(`meta[${attrSelector}]`);
106+
return meta?.nodeName.toLowerCase() === 'meta' ? meta : null;
106107
}
107108

108109
/**
@@ -114,7 +115,11 @@ export class Meta {
114115
getTags(attrSelector: string): HTMLMetaElement[] {
115116
if (!attrSelector) return [];
116117
const list /*NodeList*/ = this._doc.querySelectorAll(`meta[${attrSelector}]`);
117-
return list ? [].slice.call(list) : [];
118+
return list
119+
? (([].slice.call(list) as HTMLElement[]).filter(
120+
(elem) => elem.nodeName.toLowerCase() === 'meta',
121+
) as HTMLMetaElement[])
122+
: [];
118123
}
119124

120125
/**

packages/platform-browser/test/browser/meta_spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ describe('Meta service', () => {
8989
expect(actual!.getAttribute('content')).toEqual('4321');
9090
});
9191

92+
it('should not allow a custom selector to match off target elements like the body tag', () => {
93+
// This payload attempts to break out of the `meta[name="..."]` constraint entirely
94+
// and inject a comma to target arbitrary DOM elements like the `body` tag via the
95+
// `selector` argument of `updateTag`.
96+
const attackerSelector = 'name="description"], body, meta[name="pwned"';
97+
98+
const firstMeta = metaService.updateTag({content: 'pwned'}, attackerSelector)!;
99+
100+
expect(firstMeta).not.toBeNull();
101+
// It creates a new meta element instead of targeting `body` because it did not
102+
// find a meta element matching the dirty selector since `body` is not a `meta` tag
103+
expect(firstMeta!.nodeName.toLowerCase()).toEqual('meta');
104+
expect(firstMeta!.getAttribute('content')).toEqual('pwned');
105+
expect(doc.body.getAttribute('content')).toBeNull();
106+
107+
metaService.removeTagElement(firstMeta);
108+
});
109+
92110
it('should extract selector from the tag definition', () => {
93111
const selector = 'property="fb:app_id"';
94112
metaService.updateTag({property: 'fb:app_id', content: '666'});

0 commit comments

Comments
 (0)