Skip to content

Commit

Permalink
Update 1.2.1
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
Keith Robertson committed Nov 29, 2017
1 parent 4d1d7b6 commit bb533ee
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 71 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ Markdown (.md) file viewer [WebExtension](https://developer.mozilla.org/en-US/Ad
* Required:
* [nodejs](https://nodejs.org/) with npm
* [web-ext](https://github.com/mozilla/web-ext/) (npm install -g web-ext)
* [browserify](https://github.com/browserify/browserify/) (npm install -g browserify)
* Run `build.bat` (Windows) or `build.sh` (Linux)

## Test
Expand Down
9 changes: 3 additions & 6 deletions build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@
LICENSE
manifest.json
ext\*.*
lib\highlightjs\highlight.pack.min.js
lib\highlightjs\styles\default.css
lib\markdown-it\dist\markdown-it.min.js
lib\markdown-it-checkbox\dist\markdown-it-checkbox.min.js
lib\sss\sss.css
lib\sss\sss.print.css
) do @call :copyfile %%f staging\%%f

@call browserify .\ext\content.js^
-r .\lib\highlightjs\highlight.pack.min.js:highlight.js^
-r .\lib\markdown-it\dist\markdown-it.min.js:markdown-it^
-r .\lib\markdown-it-checkbox\dist\markdown-it-checkbox.min.js:markdown-it-checkbox^
-o .\staging\ext\content.js

@call web-ext build -s staging
@goto :EOF

Expand Down
11 changes: 4 additions & 7 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,15 @@ rm -r web-ext-artifacts 2>/dev/null
for f in LICENSE \
manifest.json \
ext/* \
ib/highlightjs/styles/default.css \
lib/highlightjs/highlight.pack.min.js \
lib/highlightjs/styles/default.css \
lib/markdown-it/dist/markdown-it.min.js \
lib/markdown-it-checkbox/dist/markdown-it-checkbox.min.js \
lib/sss/sss.css \
lib/sss/sss.print.css
do
mkdir -p `dirname staging/$f`
cp $f staging/$f
done

browserify ./ext/content.js\
-r ./lib/highlightjs/highlight.pack.min.js:highlight.js\
-r ./lib/markdown-it/dist/markdown-it.min.js:markdown-it\
-r ./lib/markdown-it-checkbox/dist/markdown-it-checkbox.min.js:markdown-it-checkbox\
-o ./staging/ext/content.js

web-ext build -s staging
2 changes: 1 addition & 1 deletion ext/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
return false;
});

browser.tabs.executeScript(id, { file: "ext/content.js" });
browser.tabs.executeScript(id, { file: "/ext/content.js" });
}
});
123 changes: 72 additions & 51 deletions ext/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,38 @@
if (media) { style.setAttribute('media', media); }
document.head.appendChild(style);
}
function addExtensionStylesheet(href, media) {
addStylesheet(browser.extension.getURL(href), media);
}

function processMarkdown(textContent) {
// Parse the content Markdown => HTML
var md = markdownit({
html: true,
linkify: true,
// Shameless copypasta https://github.com/markdown-it/markdown-it#syntax-highlighting
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (__) {}
}

var hljs = require('highlight.js');

var md = require('markdown-it')({
html: true,
linkify: true,
// Shameless copypasta https://github.com/markdown-it/markdown-it#syntax-highlighting
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (__) {}
}

try {
return hljs.highlightAuto(str).value;
} catch (__) {}
return ''; // use external default escaping
}
})
//markdown-it plugins:
.use(require('markdown-it-checkbox')); //to format [ ] and [x]
try {
return hljs.highlightAuto(str).value;
} catch (__) {}
return ''; // use external default escaping
}
})
//markdown-it plugins:
.use(markdownitCheckbox); //to format [ ] and [x]

var html = md.render(textContent);

// Style the page and code highlights.
addStylesheet(browser.extension.getURL('lib/sss/sss.css'));
addStylesheet(browser.extension.getURL('lib/sss/sss.print.css'), 'print');
addStylesheet(browser.extension.getURL('lib/highlightjs/styles/default.css'));
addExtensionStylesheet('/lib/sss/sss.css');
addExtensionStylesheet('/lib/sss/sss.print.css', 'print');
addExtensionStylesheet('/lib/highlightjs/styles/default.css');
// User-defined stylesheet.
addStylesheet('_markdown.css');

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

// Trample out script elements.
markdownRoot.querySelectorAll('script').forEach(each => {
each.innerText = '';
each.src = '';
});
// Remove hrefs that don't look like URLs.
const likeUrl = /^[-a-z]*:\/\//i;
markdownRoot.querySelectorAll('[href]').forEach(each => {
if (!likeUrl.test(each.href)) {
each.href = '';
var title = null;
var headers = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
const jsLink = /^\s*javascript:/i;
var eachElement,
allElements = document.createNodeIterator(markdownRoot, NodeFilter.SHOW_ELEMENT);
while (eachElement = allElements.nextNode()) {
var tagName = eachElement.tagName.toUpperCase();

// Find a header to use as the page title.
if (!title && headers.includes(tagName)) {
title = eachElement.textContent.trim();
}
});
// Remove event handlers. (Others?)
var events = ['onclick', 'onload', 'onmouseover', 'onmouseout'];
var eventsJoined = '[' + events.join('],[') + ']';
markdownRoot.querySelectorAll(eventsJoined).forEach(each => {
events.forEach(attr => {
if (each.getAttribute(attr)) { each.setAttribute(attr, null); }
});
});
// Crush scripts.
if (tagName === 'SCRIPT') {
eachElement.innerText = '';
eachElement.src = '';
}
// Trample JavaScript hrefs.
if (eachElement.getAttribute("href") && jsLink.test(eachElement.href)) {
eachElement.setAttribute("href", "javascript:;");
}
// Remove event handlers.
var eachAttributes = Array.from(eachElement.attributes);
for (var j = 0; j < eachAttributes.length; j++) {
var attr = eachAttributes[j];
if (attr.name.toLowerCase().startsWith('on')) {
eachElement.removeAttribute(attr.name);
}
}
}

// Set the page title.
var title = markdownRoot.querySelector('h1, h2, h3, h4, h5, h6'); // First header
if (title) {
title = title.textContent.trim();
} else {
title = markdownRoot.textContent.trim().split("\n", 1)[0].trim(); // First line
if (!title) {
// Get first line if no header.
title = markdownRoot.textContent.trim().split("\n", 1)[0].trim();
}
if (title.length > 50) {
title = title.substr(0, 50) + "...";
if (title.length > 128) {
// Limit its length.
title = title.substr(0, 125) + "...";
}
document.title = title;

// Finally insert the markdown.
document.body.appendChild(markdownRoot);
}

function loadScriptThen(path, nextStep) {
browser.runtime.sendMessage({ scriptToInject: path }, (response) => {
if (response.success) { nextStep(); }
});
}

// Execute only if .md is unprocessed text.
var body = document.body;
if (body.childNodes.length === 1 &&
Expand All @@ -98,5 +113,11 @@ if (body.childNodes.length === 1 &&
var textContent = body.textContent;
body.textContent = '';

processMarkdown(textContent);
loadScriptThen('/lib/markdown-it/dist/markdown-it.min.js', () => {
loadScriptThen('/lib/markdown-it-checkbox/dist/markdown-it-checkbox.min.js', () => {
loadScriptThen('/lib/highlightjs/highlight.pack.min.js', () => {
processMarkdown(textContent);
})
})
});
}
5 changes: 4 additions & 1 deletion ext/markdown-mark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Markdown Viewer Webext",
"version": "1.2.0",
"version": "1.2.1",
"homepage_url": "https://github.com/KeithLRobertson/markdown-viewer",
"description": "Displays markdown documents beautified in your browser.",

Expand Down
8 changes: 5 additions & 3 deletions test/test-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ function myFunction() {

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

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

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

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

<script type="text/javascript">console.log('XSS KLR');</script>
<script type="text/javascript">console.log('XSS');</script>

<a href=" JavaScript:alert('XSS')">JavaScript links are trampled out, too</a>

0 comments on commit bb533ee

Please sign in to comment.