Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit a54b25d

Browse files
Christian Liebelcaitp
Christian Liebel
authored andcommitted
feat(ngSanitize): accept SVG elements and attributes
SVG elements and attributes are now accepted and sanitized by ngSanitize. Closes #9578 Closes #9751
1 parent 36666f6 commit a54b25d

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

src/ngSanitize/sanitize.js

+40-9
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ var $sanitizeMinErr = angular.$$minErr('$sanitize');
4040
* @kind function
4141
*
4242
* @description
43-
* The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
43+
* The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
4444
* then serialized back to properly escaped html string. This means that no unsafe input can make
4545
* it into the returned string, however, since our parser is more strict than a typical browser
4646
* parser, it's possible that some obscure input, which would be recognized as valid HTML by a
47-
* browser, won't make it through the sanitizer.
47+
* browser, won't make it through the sanitizer. The input may also contain SVG markup.
4848
* The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
4949
* `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
5050
*
51-
* @param {string} html Html input.
52-
* @returns {string} Sanitized html.
51+
* @param {string} html HTML input.
52+
* @returns {string} Sanitized HTML.
5353
*
5454
* @example
5555
<example module="sanitizeExample" deps="angular-sanitize.js">
@@ -193,6 +193,12 @@ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a
193193
"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
194194
"samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
195195

196+
// SVG Elements
197+
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
198+
var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," +
199+
"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," +
200+
"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," +
201+
"stop,svg,switch,text,title,tspan,use");
196202

197203
// Special Elements (can contain anything)
198204
var specialElements = makeMap("script,style");
@@ -201,16 +207,41 @@ var validElements = angular.extend({},
201207
voidElements,
202208
blockElements,
203209
inlineElements,
204-
optionalEndTagElements);
210+
optionalEndTagElements,
211+
svgElements);
205212

206213
//Attributes that have href and hence need to be sanitized
207-
var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
208-
var validAttrs = angular.extend({}, uriAttrs, makeMap(
209-
'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
214+
var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xmlns:href");
215+
216+
var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
210217
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
211218
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
212219
'scope,scrolling,shape,size,span,start,summary,target,title,type,'+
213-
'valign,value,vspace,width'));
220+
'valign,value,vspace,width');
221+
222+
// SVG attributes (without "id" and "name" attributes)
223+
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
224+
var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,'+
225+
'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,'+
226+
'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,'+
227+
'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,'+
228+
'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,'+
229+
'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,'+
230+
'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,'+
231+
'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,'+
232+
'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,'+
233+
'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,'+
234+
'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,'+
235+
'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,'+
236+
'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,'+
237+
'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,'+
238+
'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,'+
239+
'zoomAndPan');
240+
241+
var validAttrs = angular.extend({},
242+
uriAttrs,
243+
svgAttrs,
244+
htmlAttrs);
214245

215246
function makeMap(str) {
216247
var obj = {}, items = str.split(','), i;

test/ngSanitize/sanitizeSpec.js

+10
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,16 @@ describe('HTML', function() {
238238
expectHTML(false).toBe('false');
239239
});
240240

241+
it('should accept SVG tags', function() {
242+
expectHTML('<svg width="400px" height="150px" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red"/></svg>')
243+
.toEqual('<svg width="400px" height="150px" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red"/></svg>');
244+
});
245+
246+
it('should sanitize SVG xmlns:xlink attribute values', function() {
247+
expectHTML('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><a xmlns:xhref="javascript:alert()"></a></svg>')
248+
.toEqual('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><a></a></svg>');
249+
});
250+
241251
describe('htmlSanitizerWriter', function() {
242252
/* global htmlSanitizeWriter: false */
243253
if (angular.isUndefined(window.htmlSanitizeWriter)) return;

0 commit comments

Comments
 (0)