Skip to content

Commit 9e78eff

Browse files
Ensure String#extractScripts and String#evalScripts ignore SCRIPT tags with a type attribute set to a non-JavaScript MIME-type. (Closes prototypejs#304)
1 parent 63a0174 commit 9e78eff

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

src/prototype/lang/string.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,25 @@ Object.extend(String.prototype, (function() {
337337
function extractScripts() {
338338
var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
339339
matchOne = new RegExp(Prototype.ScriptFragment, 'im');
340-
return (this.match(matchAll) || []).map(function(scriptTag) {
341-
return (scriptTag.match(matchOne) || ['', ''])[1];
340+
var matchMimeType = new RegExp(Prototype.ExecutableScriptFragment, 'im');
341+
var matchTypeAttribute = /type=/i;
342+
343+
var results = [];
344+
(this.match(matchAll) || []).each(function(scriptTag) {
345+
var match = scriptTag.match(matchOne);
346+
var attributes = match[1];
347+
if (attributes !== '') {
348+
// If the script has a `type` attribute, make sure it has a
349+
// JavaScript MIME-type. If not, ignore it.
350+
attributes = attributes.strip();
351+
var hasTypeAttribute = (matchTypeAttribute).test(attributes);
352+
var hasMimeType = (matchMimeType).test(attributes);
353+
if (hasTypeAttribute && !hasMimeType) return;
354+
}
355+
results.push(match ? match[2] : '');
342356
});
357+
358+
return results;
343359
}
344360

345361
/**

src/prototype/prototype.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ var Prototype = {
120120
SpecificElementExtensions: true
121121
},
122122

123-
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script\\s*>',
123+
ScriptFragment: '<script([^>]*)>([\\S\\s]*?)<\/script\\s*>',
124+
ExecutableScriptFragment: /(?:text|application)\/(?:x-)?(?:java|ecma)script/i,
124125
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
125126

126127
/**

test/unit/tests/string.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ suite('String', function () {
238238
('foo <script>boo();<'+'/script><script type="text/javascript">boo();\nmoo();<'+'/script>bar').extractScripts());
239239
assert.enumEqual(['boo();','boo();\nmoo();'],
240240
('foo <script>boo();<'+'/script>blub\nblub<script type="text/javascript">boo();\nmoo();<'+'/script>bar').extractScripts());
241+
242+
assert.enumEqual([], ('<' + 'script type="x-something">wat();<' + '/script>').extractScripts());
243+
assert.enumEqual(['wat();'], ('<' + 'script type="text/javascript">wat();<' + '/script>').extractScripts());
241244
});
242245

243246
test('#evalScripts', function () {
@@ -250,6 +253,27 @@ suite('String', function () {
250253
(3).times(function(){ stringWithScripts += 'foo <script>evalScriptsCounter++<'+'/script>bar' });
251254
stringWithScripts.evalScripts();
252255
assert.equal(4, evalScriptsCounter);
256+
257+
// Other executable MIME-types.
258+
('foo <script type="text/javascript">evalScriptsCounter++<'+'/script>bar')
259+
.evalScripts();
260+
('foo <script type="application/javascript">evalScriptsCounter++<'+'/script>bar')
261+
.evalScripts();
262+
('foo <script type="application/x-javascript">evalScriptsCounter++<'+'/script>bar')
263+
.evalScripts();
264+
('foo <script type="text/x-javascript">evalScriptsCounter++<'+'/script>bar')
265+
.evalScripts();
266+
('foo <script type="application/ecmascript">evalScriptsCounter++<'+'/script>bar')
267+
.evalScripts();
268+
('foo <script type="text/ecmascript">evalScriptsCounter++<'+'/script>bar')
269+
.evalScripts();
270+
271+
assert.equal(10, evalScriptsCounter);
272+
273+
// a wrong one
274+
('foo <script type="text/x-dot-template">evalScriptsCounter++<'+'/script>bar').evalScripts();
275+
276+
assert.equal(10, evalScriptsCounter);
253277
});
254278

255279
test('#escapeHTML', function () {

0 commit comments

Comments
 (0)