Skip to content

Commit

Permalink
feat(ngSanitize): accept SVG elements and attributes
Browse files Browse the repository at this point in the history
SVG elements and attributes are now accepted and sanitized by ngSanitize.

Closes angular#9578
Closes angular#9751
  • Loading branch information
Christian Liebel authored and caitp committed Oct 23, 2014
1 parent 36666f6 commit a54b25d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 9 deletions.
49 changes: 40 additions & 9 deletions src/ngSanitize/sanitize.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ var $sanitizeMinErr = angular.$$minErr('$sanitize');
* @kind function
*
* @description
* The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
* The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
* then serialized back to properly escaped html string. This means that no unsafe input can make
* it into the returned string, however, since our parser is more strict than a typical browser
* parser, it's possible that some obscure input, which would be recognized as valid HTML by a
* browser, won't make it through the sanitizer.
* browser, won't make it through the sanitizer. The input may also contain SVG markup.
* The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
* `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
*
* @param {string} html Html input.
* @returns {string} Sanitized html.
* @param {string} html HTML input.
* @returns {string} Sanitized HTML.
*
* @example
<example module="sanitizeExample" deps="angular-sanitize.js">
Expand Down Expand Up @@ -193,6 +193,12 @@ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a
"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
"samp,small,span,strike,strong,sub,sup,time,tt,u,var"));

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

// Special Elements (can contain anything)
var specialElements = makeMap("script,style");
Expand All @@ -201,16 +207,41 @@ var validElements = angular.extend({},
voidElements,
blockElements,
inlineElements,
optionalEndTagElements);
optionalEndTagElements,
svgElements);

//Attributes that have href and hence need to be sanitized
var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
var validAttrs = angular.extend({}, uriAttrs, makeMap(
'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xmlns:href");

var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
'scope,scrolling,shape,size,span,start,summary,target,title,type,'+
'valign,value,vspace,width'));
'valign,value,vspace,width');

// SVG attributes (without "id" and "name" attributes)
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,'+
'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,'+
'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,'+
'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,'+
'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,'+
'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,'+
'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,'+
'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,'+
'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,'+
'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,'+
'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,'+
'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,'+
'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,'+
'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,'+
'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,'+
'zoomAndPan');

var validAttrs = angular.extend({},
uriAttrs,
svgAttrs,
htmlAttrs);

function makeMap(str) {
var obj = {}, items = str.split(','), i;
Expand Down
10 changes: 10 additions & 0 deletions test/ngSanitize/sanitizeSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,16 @@ describe('HTML', function() {
expectHTML(false).toBe('false');
});

it('should accept SVG tags', function() {
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>')
.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>');
});

it('should sanitize SVG xmlns:xlink attribute values', function() {
expectHTML('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><a xmlns:xhref="javascript:alert()"></a></svg>')
.toEqual('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><a></a></svg>');
});

describe('htmlSanitizerWriter', function() {
/* global htmlSanitizeWriter: false */
if (angular.isUndefined(window.htmlSanitizeWriter)) return;
Expand Down

0 comments on commit a54b25d

Please sign in to comment.