Skip to content

Commit bb533ee

Browse files
author
Keith Robertson
committed
Update 1.2.1
- Reverts script embedding with browserify, since it was rejected by AMO. - Removes all event handlers starting with "on", not just four of them. - Walks the tree just once. - Made Mardown icon square as now required by AMO.
1 parent 4d1d7b6 commit bb533ee

File tree

8 files changed

+90
-71
lines changed

8 files changed

+90
-71
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ Markdown (.md) file viewer [WebExtension](https://developer.mozilla.org/en-US/Ad
55
* Required:
66
* [nodejs](https://nodejs.org/) with npm
77
* [web-ext](https://github.com/mozilla/web-ext/) (npm install -g web-ext)
8-
* [browserify](https://github.com/browserify/browserify/) (npm install -g browserify)
98
* Run `build.bat` (Windows) or `build.sh` (Linux)
109

1110
## Test

build.bat

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,14 @@
55
LICENSE
66
manifest.json
77
ext\*.*
8+
lib\highlightjs\highlight.pack.min.js
89
lib\highlightjs\styles\default.css
10+
lib\markdown-it\dist\markdown-it.min.js
11+
lib\markdown-it-checkbox\dist\markdown-it-checkbox.min.js
912
lib\sss\sss.css
1013
lib\sss\sss.print.css
1114
) do @call :copyfile %%f staging\%%f
1215

13-
@call browserify .\ext\content.js^
14-
-r .\lib\highlightjs\highlight.pack.min.js:highlight.js^
15-
-r .\lib\markdown-it\dist\markdown-it.min.js:markdown-it^
16-
-r .\lib\markdown-it-checkbox\dist\markdown-it-checkbox.min.js:markdown-it-checkbox^
17-
-o .\staging\ext\content.js
18-
1916
@call web-ext build -s staging
2017
@goto :EOF
2118

build.sh

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,15 @@ rm -r web-ext-artifacts 2>/dev/null
44
for f in LICENSE \
55
manifest.json \
66
ext/* \
7-
ib/highlightjs/styles/default.css \
7+
lib/highlightjs/highlight.pack.min.js \
8+
lib/highlightjs/styles/default.css \
9+
lib/markdown-it/dist/markdown-it.min.js \
10+
lib/markdown-it-checkbox/dist/markdown-it-checkbox.min.js \
811
lib/sss/sss.css \
912
lib/sss/sss.print.css
1013
do
1114
mkdir -p `dirname staging/$f`
1215
cp $f staging/$f
1316
done
1417

15-
browserify ./ext/content.js\
16-
-r ./lib/highlightjs/highlight.pack.min.js:highlight.js\
17-
-r ./lib/markdown-it/dist/markdown-it.min.js:markdown-it\
18-
-r ./lib/markdown-it-checkbox/dist/markdown-it-checkbox.min.js:markdown-it-checkbox\
19-
-o ./staging/ext/content.js
20-
2118
web-ext build -s staging

ext/background.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
return false;
1616
});
1717

18-
browser.tabs.executeScript(id, { file: "ext/content.js" });
18+
browser.tabs.executeScript(id, { file: "/ext/content.js" });
1919
}
2020
});

ext/content.js

Lines changed: 72 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,38 @@
66
if (media) { style.setAttribute('media', media); }
77
document.head.appendChild(style);
88
}
9+
function addExtensionStylesheet(href, media) {
10+
addStylesheet(browser.extension.getURL(href), media);
11+
}
912

1013
function processMarkdown(textContent) {
1114
// Parse the content Markdown => HTML
15+
var md = markdownit({
16+
html: true,
17+
linkify: true,
18+
// Shameless copypasta https://github.com/markdown-it/markdown-it#syntax-highlighting
19+
highlight: function (str, lang) {
20+
if (lang && hljs.getLanguage(lang)) {
21+
try {
22+
return hljs.highlight(lang, str).value;
23+
} catch (__) {}
24+
}
1225

13-
var hljs = require('highlight.js');
14-
15-
var md = require('markdown-it')({
16-
html: true,
17-
linkify: true,
18-
// Shameless copypasta https://github.com/markdown-it/markdown-it#syntax-highlighting
19-
highlight: function (str, lang) {
20-
if (lang && hljs.getLanguage(lang)) {
21-
try {
22-
return hljs.highlight(lang, str).value;
23-
} catch (__) {}
24-
}
25-
26-
try {
27-
return hljs.highlightAuto(str).value;
28-
} catch (__) {}
29-
return ''; // use external default escaping
30-
}
31-
})
32-
//markdown-it plugins:
33-
.use(require('markdown-it-checkbox')); //to format [ ] and [x]
26+
try {
27+
return hljs.highlightAuto(str).value;
28+
} catch (__) {}
29+
return ''; // use external default escaping
30+
}
31+
})
32+
//markdown-it plugins:
33+
.use(markdownitCheckbox); //to format [ ] and [x]
3434

3535
var html = md.render(textContent);
3636

3737
// Style the page and code highlights.
38-
addStylesheet(browser.extension.getURL('lib/sss/sss.css'));
39-
addStylesheet(browser.extension.getURL('lib/sss/sss.print.css'), 'print');
40-
addStylesheet(browser.extension.getURL('lib/highlightjs/styles/default.css'));
38+
addExtensionStylesheet('/lib/sss/sss.css');
39+
addExtensionStylesheet('/lib/sss/sss.print.css', 'print');
40+
addExtensionStylesheet('/lib/highlightjs/styles/default.css');
4141
// User-defined stylesheet.
4242
addStylesheet('_markdown.css');
4343

@@ -52,43 +52,58 @@ function processMarkdown(textContent) {
5252
markdownRoot.className = "markdownRoot";
5353
markdownRoot.innerHTML = html;
5454

55-
// Trample out script elements.
56-
markdownRoot.querySelectorAll('script').forEach(each => {
57-
each.innerText = '';
58-
each.src = '';
59-
});
60-
// Remove hrefs that don't look like URLs.
61-
const likeUrl = /^[-a-z]*:\/\//i;
62-
markdownRoot.querySelectorAll('[href]').forEach(each => {
63-
if (!likeUrl.test(each.href)) {
64-
each.href = '';
55+
var title = null;
56+
var headers = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
57+
const jsLink = /^\s*javascript:/i;
58+
var eachElement,
59+
allElements = document.createNodeIterator(markdownRoot, NodeFilter.SHOW_ELEMENT);
60+
while (eachElement = allElements.nextNode()) {
61+
var tagName = eachElement.tagName.toUpperCase();
62+
63+
// Find a header to use as the page title.
64+
if (!title && headers.includes(tagName)) {
65+
title = eachElement.textContent.trim();
6566
}
66-
});
67-
// Remove event handlers. (Others?)
68-
var events = ['onclick', 'onload', 'onmouseover', 'onmouseout'];
69-
var eventsJoined = '[' + events.join('],[') + ']';
70-
markdownRoot.querySelectorAll(eventsJoined).forEach(each => {
71-
events.forEach(attr => {
72-
if (each.getAttribute(attr)) { each.setAttribute(attr, null); }
73-
});
74-
});
67+
// Crush scripts.
68+
if (tagName === 'SCRIPT') {
69+
eachElement.innerText = '';
70+
eachElement.src = '';
71+
}
72+
// Trample JavaScript hrefs.
73+
if (eachElement.getAttribute("href") && jsLink.test(eachElement.href)) {
74+
eachElement.setAttribute("href", "javascript:;");
75+
}
76+
// Remove event handlers.
77+
var eachAttributes = Array.from(eachElement.attributes);
78+
for (var j = 0; j < eachAttributes.length; j++) {
79+
var attr = eachAttributes[j];
80+
if (attr.name.toLowerCase().startsWith('on')) {
81+
eachElement.removeAttribute(attr.name);
82+
}
83+
}
84+
}
7585

7686
// Set the page title.
77-
var title = markdownRoot.querySelector('h1, h2, h3, h4, h5, h6'); // First header
78-
if (title) {
79-
title = title.textContent.trim();
80-
} else {
81-
title = markdownRoot.textContent.trim().split("\n", 1)[0].trim(); // First line
87+
if (!title) {
88+
// Get first line if no header.
89+
title = markdownRoot.textContent.trim().split("\n", 1)[0].trim();
8290
}
83-
if (title.length > 50) {
84-
title = title.substr(0, 50) + "...";
91+
if (title.length > 128) {
92+
// Limit its length.
93+
title = title.substr(0, 125) + "...";
8594
}
8695
document.title = title;
8796

8897
// Finally insert the markdown.
8998
document.body.appendChild(markdownRoot);
9099
}
91100

101+
function loadScriptThen(path, nextStep) {
102+
browser.runtime.sendMessage({ scriptToInject: path }, (response) => {
103+
if (response.success) { nextStep(); }
104+
});
105+
}
106+
92107
// Execute only if .md is unprocessed text.
93108
var body = document.body;
94109
if (body.childNodes.length === 1 &&
@@ -98,5 +113,11 @@ if (body.childNodes.length === 1 &&
98113
var textContent = body.textContent;
99114
body.textContent = '';
100115

101-
processMarkdown(textContent);
116+
loadScriptThen('/lib/markdown-it/dist/markdown-it.min.js', () => {
117+
loadScriptThen('/lib/markdown-it-checkbox/dist/markdown-it-checkbox.min.js', () => {
118+
loadScriptThen('/lib/highlightjs/highlight.pack.min.js', () => {
119+
processMarkdown(textContent);
120+
})
121+
})
122+
});
102123
}

ext/markdown-mark.svg

Lines changed: 4 additions & 1 deletion
Loading

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 2,
33
"name": "Markdown Viewer Webext",
4-
"version": "1.2.0",
4+
"version": "1.2.1",
55
"homepage_url": "https://github.com/KeithLRobertson/markdown-viewer",
66
"description": "Displays markdown documents beautified in your browser.",
77

test/test-file.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,12 @@ function myFunction() {
6262

6363
![Large image (should be resized)](http://lorempixel.com/1200/200/)
6464

65-
<strong onload="console.log('loaded')">HTML is supported</strong>
65+
<strong>HTML is supported</strong>
6666

6767
<strong onclick="alert('XSS')">But scripts (in script elements or from events) are not accepted</strong>
6868

69-
<button onclick="alert('XSS KLR')">Therefore clicking me does nothing</button>
69+
<button onclick="alert('XSS')" onload="console.log('loaded')">Therefore clicking me does nothing</button>
7070

71-
<script type="text/javascript">console.log('XSS KLR');</script>
71+
<script type="text/javascript">console.log('XSS');</script>
72+
73+
<a href=" JavaScript:alert('XSS')">JavaScript links are trampled out, too</a>

0 commit comments

Comments
 (0)