diff --git a/Gruntfile.js b/Gruntfile.js index cafe7a0..ac713b6 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -12,7 +12,9 @@ module.exports = function(grunt) { options: { scripturl: true, camelcase: true, - unused: true + unused: true, + curly: true, + node: true } }, jsdoc : { @@ -41,18 +43,28 @@ module.exports = function(grunt) { banner: '/**\n' + ' * <%= pkg.name %> - v<%= pkg.version %>\n' + ' * Yahoo! Inc. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.\n' - + ' */\n' + + ' */\n', + compress: { + join_vars: true + } }, - build: { + buildBrowserified: { src: 'dist/<%= pkg.name %>.js', + dest: 'dist/<%= pkg.name %>.js' + }, + buildMin: { + options: { + wrap: 'xssFilters' + }, + src: 'src/<%= pkg.name %>.js', dest: 'dist/<%= pkg.name %>.min.js' - } - }, - copy: { - buildFile: { - files: [ - { dest: 'dist/<%= pkg.name %>.<%= pkg.version %>.min.js', src: 'dist/<%= pkg.name %>.min.js'} - ] + }, + buildMinWithVersion: { + options: { + wrap: 'xssFilters' + }, + src: 'src/<%= pkg.name %>.js', + dest: 'dist/<%= pkg.name %>.<%= pkg.version %>.min.js' } }, mocha_istanbul: { @@ -69,7 +81,7 @@ module.exports = function(grunt) { } }, clean: { - all: ['dist', 'artifacts', 'node_modules'] + all: ['artifacts', 'node_modules', 'bower_components'] } }); @@ -78,11 +90,10 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-jsdoc'); grunt.registerTask('test', ['jshint', 'mocha_istanbul']); - grunt.registerTask('dist', ['browserify', 'uglify', 'copy:buildFile']) + grunt.registerTask('dist', ['browserify', 'uglify']) grunt.registerTask('docs', ['jsdoc']); grunt.registerTask('default', ['test', 'dist']); diff --git a/README.md b/README.md index 318ed9f..412779f 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,7 @@ Secure XSS Filters - **More Secure.** Context-dependent output filters that are developer-friendly. It is safe to apply these filters like so: - ```javascript -el.innerHTML = "" - + xssFilters.uriInHTMLData(url) + ""; -``` + `document.write("" + xssFilters.uriInHTMLData(url) + "");` In this example, the traditional wisdom of blindly escaping the five well-known characters (`&` `<` `>` `'` `"`) would not stop XSS (e.g., when `url` is equal to `javascript:alert(1)` or ` onclick=alert(1)`). diff --git a/bower.json b/bower.json index 64b212c..dbdea7a 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "xss-filters", - "version": "1.0.2", + "version": "1.0.3", "homepage": "https://github.com/yahoo/xss-filters", "authors": [ "Nera Liu ", diff --git a/dist/xss-filters.1.0.3.min.js b/dist/xss-filters.1.0.3.min.js new file mode 100644 index 0000000..83c9925 --- /dev/null +++ b/dist/xss-filters.1.0.3.min.js @@ -0,0 +1,5 @@ +/** + * xss-filters - v1.0.3 + * Yahoo! Inc. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +!function(a,b){function c(a,b,c){return q.yubl(b((c||q.yufull)(a)))}b.xssFilters=a;var d="undefined",e="null",f=/"']/g,j=/(--!?>|--?!?$|\]>|\]$)/g,k=/^["']/,l=/[\t\n\f >]/g,m=["&","j","J","v","V"],n=null,o="^(?:&#[xX]0*(?:1?[1-9a-fA-F]|10|20);?|�*(?:[1-9]|[1-2][0-9]|30|31|32);?| | )*(?:(?:j|J|&#[xX]0*(?:6|4)[aA];?|�*(?:106|74);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:a|A|&#[xX]0*(?:6|4)1;?|�*(?:97|65);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:v|V|&#[xX]0*(?:7|5)6;?|�*(?:118|86);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:a|A|&#[xX]0*(?:6|4)1;?|�*(?:97|65);?)|(?:v|V|&#[xX]0*(?:7|5)6;?|�*(?:118|86);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:b|B|&#[xX]0*(?:6|4)2;?|�*(?:98|66);?))(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:s|S|&#[xX]0*(?:7|5)3;?|�*(?:115|83);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:c|C|&#[xX]0*(?:6|4)3;?|�*(?:99|67);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:r|R|&#[xX]0*(?:7|5)2;?|�*(?:114|82);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:i|I|&#[xX]0*(?:6|4)9;?|�*(?:105|73);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:p|P|&#[xX]0*(?:7|5)0;?|�*(?:112|80);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:t|T|&#[xX]0*(?:7|5)4;?|�*(?:116|84);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?::|&#[xX]0*3[aA];?|�*58;?)",p=/\/\/%5[Bb]([A-Fa-f0-9:]+)%5[Dd]/,q={FILTER_NOT_HANDLE:"y",FILTER_DATA:"yd",FILTER_COMMENT:"yc",FILTER_ATTRIBUTE_VALUE_DOUBLE_QUOTED:"yavd",FILTER_ATTRIBUTE_VALUE_SINGLE_QUOTED:"yavs",FILTER_ATTRIBUTE_VALUE_UNQUOTED:"yavu",FILTER_ENCODE_URI:"yu",FILTER_ENCODE_URI_COMPONENT:"yuc",FILTER_URI_SCHEME_BLACKLIST:"yubl",FILTER_FULL_URI:"yufull",y:function(a){return typeof a===d?d:null===a?e:a.toString().replace(i,function(a){return"&"===a?"&":"<"===a?"<":">"===a?">":'"'===a?""":"'"})},yd:function(a){return typeof a===d?d:null===a?e:a.toString().replace(f,"<")},yc:function(a){return typeof a===d?d:null===a?e:a.toString().replace(j,function(a){return"-->"===a?"-- >":"--!>"===a?"--! >":"--!"===a?"--! ":"--"===a?"-- ":"-"===a?"- ":"]>"===a?"] >":"] "})},yavd:function(a){return typeof a===d?d:null===a?e:a.toString().replace(g,""")},yavs:function(a){return typeof a===d?d:null===a?e:a.toString().replace(h,"'")},yavu:function(a){return typeof a===d?d:null===a?e:(a=a.toString().replace(l,function(a){return" "===a?" ":"\n"===a?" ":"\f"===a?" ":" "===a?" ":">"}),a=a.replace(k,function(a){return'"'===a?""":"'"}),""===a?"\x00":a)},yu:encodeURI,yuc:encodeURIComponent,yubl:function(a){return-1===m.indexOf(a[0])?a:(null===n&&(n=new RegExp(o)),n.test(a)?"x-"+a:a)},yufull:function(a){return encodeURI(a).replace(p,function(a,b){return"//["+b+"]"})}};a.inHTMLData=q.yd,a.inHTMLComment=q.yc,a.inSingleQuotedAttr=q.yavs,a.inDoubleQuotedAttr=q.yavd,a.inUnQuotedAttr=q.yavu,a.uriInSingleQuotedAttr=function(a){return c(a,q.yavs)},a.uriInDoubleQuotedAttr=function(a){return c(a,q.yavd)},a.uriInUnQuotedAttr=function(a){return c(a,q.yavu)},a.uriInHTMLData=q.yufull,a.uriInHTMLComment=function(a){return q.yc(q.yufull(a))},a.uriPathInSingleQuotedAttr=function(a){return c(a,q.yavs,q.yu)},a.uriPathInDoubleQuotedAttr=function(a){return c(a,q.yavd,q.yu)},a.uriPathInUnQuotedAttr=function(a){return c(a,q.yavu,q.yu)},a.uriPathInHTMLData=q.yu,a.uriPathInHTMLComment=function(a){return q.yc(q.yu(a))},a.uriQueryInSingleQuotedAttr=a.uriPathInSingleQuotedAttr,a.uriQueryInDoubleQuotedAttr=a.uriPathInDoubleQuotedAttr,a.uriQueryInUnQuotedAttr=a.uriPathInUnQuotedAttr,a.uriQueryInHTMLData=a.uriPathInHTMLData,a.uriQueryInHTMLComment=a.uriPathInHTMLComment,a.uriComponentInSingleQuotedAttr=function(a){return q.yavs(q.yuc(a))},a.uriComponentInDoubleQuotedAttr=function(a){return q.yavd(q.yuc(a))},a.uriComponentInUnQuotedAttr=function(a){return q.yavu(q.yuc(a))},a.uriComponentInHTMLData=q.yuc,a.uriComponentInHTMLComment=function(a){return q.yc(q.yuc(a))},a.uriFragmentInSingleQuotedAttr=function(a){return q.yubl(q.yavs(q.yuc(a)))},a.uriFragmentInDoubleQuotedAttr=function(a){return q.yubl(q.yavd(q.yuc(a)))},a.uriFragmentInUnQuotedAttr=function(a){return q.yubl(q.yavu(q.yuc(a)))},a.uriFragmentInHTMLData=a.uriComponentInHTMLData,a.uriFragmentInHTMLComment=a.uriComponentInHTMLComment,a._privFilters=q}({},function(){return this}()); \ No newline at end of file diff --git a/dist/xss-filters.js b/dist/xss-filters.js index 2b9afb7..0790e57 100644 --- a/dist/xss-filters.js +++ b/dist/xss-filters.js @@ -1,1019 +1,5 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.xssFilters = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o - Adonis Fung - Albert Yu -*/ -(function () { -"use strict"; - -/* -* ===================================================== -* NOT TO BE DIRECTLY USED. USE xss-filters.js INSTEAD -* ===================================================== -*/ - - -// TODO: remove the following mappings -exports.FILTER_NOT_HANDLE = "y"; -exports.FILTER_DATA = "yd"; -exports.FILTER_COMMENT = "yc"; -exports.FILTER_ATTRIBUTE_VALUE_DOUBLE_QUOTED = "yavd"; -exports.FILTER_ATTRIBUTE_VALUE_SINGLE_QUOTED = "yavs"; -exports.FILTER_ATTRIBUTE_VALUE_UNQUOTED = "yavu"; -exports.FILTER_ENCODE_URI = "yu"; -exports.FILTER_ENCODE_URI_COMPONENT = "yuc"; -exports.FILTER_URI_SCHEME_BLACKLIST = "yubl"; -exports.FILTER_FULL_URI = "yufull"; - - -var STR_UD = 'undefined', - STR_NL = 'null', - LT = /"']/g; - -/* - * @param {string} s - An untrusted user input - * @returns {string} s - The original user input with & < > " ' encoded respectively as & < > " and '. - * - * @description - *

This filter is a fallback to use the standard HTML escaping (i.e., encoding &<>"') - * in contexts that are currently not handled by the automatic context-sensitive templating solution.

- * - * Workaround this problem by following the suggestion below: - * Use - * and retrieve your data with document.getElementById('strJS').value. - * - */ -exports.y = function(s) { - return typeof s === STR_UD ? STR_UD - : s === null ? STR_NL - : s.toString() - .replace(SPECIAL_HTML_CHARS, function (m) { - if (m === '&') { return '&'; } - if (m === '<') { return '<'; } - if (m === '>') { return '>'; } - if (m === '"') { return '"'; } - /* if (m === "'") */ return '''; - }); -}; - - -// FOR DETAILS, refer to inHTMLData() -// Reference: https://html.spec.whatwg.org/multipage/syntax.html#data-state -exports.yd = function (s) { - return typeof s === STR_UD ? STR_UD - : s === null ? STR_NL - : s.toString() - .replace(LT, '<'); -}; - - -var COMMENT_SENSITIVE_CHARS = /(--!?>|--?!?$|\]>|\]$)/g; -// FOR DETAILS, refer to inHTMLComment() -// '-->' and '--!>' are modified as '-- >' and '--! >' so as stop comment state breaking -// for string ends with '--!', '--', or '-' are appended with a space, so as to stop collaborative state breaking at {{s}}>, {{s}}!>, {{s}}-> -// Reference: https://html.spec.whatwg.org/multipage/syntax.html#comment-state -// ']>' and 'ends with ]' patterns deal with IE conditional comments. verified in IE that '] >' can stop that. -// Reference: http://msdn.microsoft.com/en-us/library/ms537512%28v=vs.85%29.aspx -exports.yc = function (s) { - return typeof s === STR_UD ? STR_UD - : s === null ? STR_NL - : s.toString() - .replace(COMMENT_SENSITIVE_CHARS, function(m){ - if (m === '-->') { return '-- >'; } - if (m === '--!>') { return '--! >'; } - if (m === '--!') { return '--! '; } - if (m === '--') { return '-- '; } - if (m === '-') { return '- '; } - if (m === ']>') { return '] >'; } - /*if (m === ']')*/ return '] '; - }); -}; - -// Reference: https://html.spec.whatwg.org/multipage/syntax.html#before-attribute-value-state -var BEFORE_ATTR_VALUE_CHARS = /^["']/; -var ATTR_VALUE_UNQUOTED_CHARS = /[\t\n\f >]/g; - -// FOR DETAILS, refer to inDoubleQuotedAttr() -// Reference: https://html.spec.whatwg.org/multipage/syntax.html#attribute-value-(double-quoted)-state -exports.yavd = function (s) { - return typeof s === STR_UD ? STR_UD - : s === null ? STR_NL - : s.toString() - .replace(QUOT, '"'); -}; - -// FOR DETAILS, refer to inSingleQuotedAttr() -// Reference: https://html.spec.whatwg.org/multipage/syntax.html#attribute-value-(single-quoted)-state -exports.yavs = function (s) { - return typeof s === STR_UD ? STR_UD - : s === null ? STR_NL - : s.toString() - .replace(SQUOT, '''); -}; - -// FOR DETAILS, refer to inUnQuotedAttr() -// Reference: https://html.spec.whatwg.org/multipage/syntax.html#attribute-value-(unquoted)-state -// Reference: https://html.spec.whatwg.org/multipage/syntax.html#before-attribute-value-state -exports.yavu = function (s) { - if (typeof s === STR_UD) return STR_UD; - if (s === null) return STR_NL; - - s = s.toString().replace(ATTR_VALUE_UNQUOTED_CHARS, function (m) { - if (m === '\t') { return ' '; } - if (m === '\n') { return ' '; } - if (m === '\f') { return ' '; } // in hex: 0C - if (m === ' ') { return ' '; } // in hex: 20 - /*if (m === '>')*/ return '>'; - }); - - // if s starts with ' or ", encode it resp. as ' or " to enforce the attr value (unquoted) state - // if instead starts with some whitespaces [\t\n\f ] then optionally a quote, - // then the above encoding has already enforced the attr value (unquoted) state - // therefore, no need to encode the quote - // Reference: https://html.spec.whatwg.org/multipage/syntax.html#before-attribute-value-state - s = s.replace(BEFORE_ATTR_VALUE_CHARS, function (m) { - if (m === '"') { return '"'; } - /*if (m === "'")*/ return '''; - }); - - // Inject NULL character if an empty string is encountered in - // unquoted attribute value state. - // - // Example: - // - // - // Rationale 1: our belief is that developers wouldn't expect an - // empty string would result in ' name="firstname"' rendered as - // attribute value, even though this is how HTML5 is specified. - // Rationale 2: an empty string can effectively alter its immediate - // subsequent state, which violates our design principle. As per - // the HTML 5 spec, NULL or \u0000 is the magic character to end - // the comment state, which therefore will not mess up later - // contexts. - // Reference: https://html.spec.whatwg.org/multipage/syntax.html#before-attribute-value-state - return (s === '') ? '\u0000' : s; -}; - -exports.yu = encodeURI; -exports.yuc = encodeURIComponent; - -// Reference: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Null_breaks_up_JavaScript_directive -// Reference: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_newline_to_break_up_XSS -// Reference: https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference -// Reference for named characters: https://html.spec.whatwg.org/multipage/entities.json -/* -var URI_BLACKLIST_INTERIM_WHITESPACE = [ - '(?:', - [ - // encodeURI/encodeURIComponent has percentage encoded ASCII chars of decimal 0-32 - // '\u0000', - // '\t', '\n', '\r', // tab, newline, carriage return - '&#[xX]0*[9aAdD];?', // , , in hex - '�*(?:9|10|13);?', // , , in dec - ' ', ' ' // tab, newline in char entities - ].join('|'), - ')*' -].join(''); - -// delay building the following as an RegExp() object until the first hit -var URI_BLACKLIST, URI_BLACKLIST_REGEXPSTR = [ - - // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Spaces_and_meta_chars_before_the_JavaScript_in_images_for_XSS - '^(?:', - [ - // encodeURI/encodeURIComponent has percentage encoded ASCII chars of decimal 0-32 - // '\u0001', '\u0002', '\u0003', '\u0004', - // '\u0005', '\u0006', '\u0007', '\u0008', - // '\u0009', '\u000A', '\u000B', '\u000C', - // '\u000D', '\u000E', '\u000F', '\u0010', - // '\u0011', '\u0012', '\u0013', '\u0014', - // '\u0015', '\u0016', '\u0017', '\u0018', - // '\u0019', '\u001A', '\u001B', '\u001C', - // '\u001D', '\u001E', '\u001F', '\u0020', - '&#[xX]0*(?:1?[1-9a-fA-F]|10|20);?', // -20 in hex - '�*(?:[1-9]|[1-2][0-9]|30|31|32);?', // -32 in dec - ' ', ' ' // space, newline in char entities - - ].join('|'), - ')*', - - - // java java java - // JAVA JAVA JAVA - // vb vb vb - // VB VB VB - // script script script - // SCRIPT SCRIPT SCRIPT - // : : : - - // java|vb - '(?:', - [ - // java - [ - '(?:j|J|&#[xX]0*(?:6|4)[aA];?|�*(?:106|74);?)', - '(?:a|A|&#[xX]0*(?:6|4)1;?|�*(?:97|65);?)', - '(?:v|V|&#[xX]0*(?:7|5)6;?|�*(?:118|86);?)', - '(?:a|A|&#[xX]0*(?:6|4)1;?|�*(?:97|65);?)', - - ].join(URI_BLACKLIST_INTERIM_WHITESPACE), - // vb - [ - '(?:v|V|&#[xX]0*(?:7|5)6;?|�*(?:118|86);?)', - '(?:b|B|&#[xX]0*(?:6|4)2;?|�*(?:98|66);?)' - - ].join(URI_BLACKLIST_INTERIM_WHITESPACE) - - ].join('|'), - ')', - - URI_BLACKLIST_INTERIM_WHITESPACE, - - // script: - [ - '(?:s|S|&#[xX]0*(?:7|5)3;?|�*(?:115|83);?)', - '(?:c|C|&#[xX]0*(?:6|4)3;?|�*(?:99|67);?)', - '(?:r|R|&#[xX]0*(?:7|5)2;?|�*(?:114|82);?)', - '(?:i|I|&#[xX]0*(?:6|4)9;?|�*(?:105|73);?)', - '(?:p|P|&#[xX]0*(?:7|5)0;?|�*(?:112|80);?)', - '(?:t|T|&#[xX]0*(?:7|5)4;?|�*(?:116|84);?)', - '(?:\:|&#[xX]0*3[aA];?|�*58;?)' - - ].join(URI_BLACKLIST_INTERIM_WHITESPACE) -].join(''); -*/ - -var URI_SLOWLANE = ['&', 'j', 'J', 'v', 'V'], - URI_BLACKLIST = null, - // delay building URI_BLACKLIST as an RegExp() object until the first hit - // the following str is generated by the above commented logic - URI_BLACKLIST_REGEXPSTR = "^(?:&#[xX]0*(?:1?[1-9a-fA-F]|10|20);?|�*(?:[1-9]|[1-2][0-9]|30|31|32);?| | )*(?:(?:j|J|&#[xX]0*(?:6|4)[aA];?|�*(?:106|74);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:a|A|&#[xX]0*(?:6|4)1;?|�*(?:97|65);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:v|V|&#[xX]0*(?:7|5)6;?|�*(?:118|86);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:a|A|&#[xX]0*(?:6|4)1;?|�*(?:97|65);?)|(?:v|V|&#[xX]0*(?:7|5)6;?|�*(?:118|86);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:b|B|&#[xX]0*(?:6|4)2;?|�*(?:98|66);?))(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:s|S|&#[xX]0*(?:7|5)3;?|�*(?:115|83);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:c|C|&#[xX]0*(?:6|4)3;?|�*(?:99|67);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:r|R|&#[xX]0*(?:7|5)2;?|�*(?:114|82);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:i|I|&#[xX]0*(?:6|4)9;?|�*(?:105|73);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:p|P|&#[xX]0*(?:7|5)0;?|�*(?:112|80);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?:t|T|&#[xX]0*(?:7|5)4;?|�*(?:116|84);?)(?:&#[xX]0*[9aAdD];?|�*(?:9|10|13);?| | )*(?::|&#[xX]0*3[aA];?|�*58;?)"; - -/* - * ============================= - * Rationale on data: protocol - * ============================= - * Given there're two execution possibilities: - * 1. data:text/html, in <(i)frame>'s src - * expected script execution but it's of a different origin than the included page. hence not CROSS-SITE scripting - * 2. data:application/javascript,alert(1) or data:,alert(1) in in <(i)frame>'s src - * expected script execution but it's of a different origin than the included page. hence not CROSS-SITE scripting - * 2. data:application/javascript,alert(1) or data:,alert(1) in in <(i)frame>'s src + * expected script execution but it's of a different origin than the included page. hence not CROSS-SITE scripting + * 2. data:application/javascript,alert(1) or data:,alert(1) in