Add markdown_escape setting

This setting allows to escape HTML in markdown rendering or not.
The goal behind it is to avoid XSS issue in shared instances.

More info:

  * the setting is set to true by default
  * it is set to false for anyone who already have the plugin enabled
  (avoid breaking existing entries)
  * improve the HTML sanitization when the setting is set to false - but don't consider it XSS proof
  * mention the setting in the plugin README
This commit is contained in:
ArthurHoaro 2017-02-27 19:45:55 +01:00
parent 5978588578
commit e037610115
6 changed files with 181 additions and 27 deletions
plugins/markdown

View file

@ -50,9 +50,20 @@ If the tag `nomarkdown` is set for a shaare, it won't be converted to Markdown s
> Note: this is a special tag, so it won't be displayed in link list.
### HTML rendering
### HTML escape
Markdown support HTML tags. For example:
By default, HTML tags are escaped. You can enable HTML tags rendering
by setting `security.markdwon_escape` to `false` in `data/config.json.php`:
```json
{
"security": {
"markdown_escape": false
}
}
```
With this setting, Markdown support HTML tags. For example:
> <strong>strong</strong><strike>strike</strike>
@ -60,12 +71,14 @@ Will render as:
> <strong>strong</strong><strike>strike</strike>
If you want to shaare HTML code, it is necessary to use inline code or code blocks.
**If your shaared descriptions containing HTML tags before enabling the markdown plugin,
enabling it might break your page.**
> Note: HTML tags such as script, iframe, etc. are disabled for security reasons.
**Warning:**
* This setting might present **security risks** (XSS) on shared instances, even though tags
such as script, iframe, etc should be disabled.
* If you want to shaare HTML code, it is necessary to use inline code or code blocks.
* If your shaared descriptions contained HTML tags before enabling the markdown plugin,
enabling it might break your page.
### Known issue

View file

@ -14,18 +14,19 @@ define('NO_MD_TAG', 'nomarkdown');
/**
* Parse linklist descriptions.
*
* @param array $data linklist data.
* @param array $data linklist data.
* @param ConfigManager $conf instance.
*
* @return mixed linklist data parsed in markdown (and converted to HTML).
*/
function hook_markdown_render_linklist($data)
function hook_markdown_render_linklist($data, $conf)
{
foreach ($data['links'] as &$value) {
if (!empty($value['tags']) && noMarkdownTag($value['tags'])) {
$value = stripNoMarkdownTag($value);
continue;
}
$value['description'] = process_markdown($value['description']);
$value['description'] = process_markdown($value['description'], $conf->get('security.markdown_escape', true));
}
return $data;
}
@ -34,17 +35,18 @@ function hook_markdown_render_linklist($data)
* Parse feed linklist descriptions.
*
* @param array $data linklist data.
* @param ConfigManager $conf instance.
*
* @return mixed linklist data parsed in markdown (and converted to HTML).
*/
function hook_markdown_render_feed($data)
function hook_markdown_render_feed($data, $conf)
{
foreach ($data['links'] as &$value) {
if (!empty($value['tags']) && noMarkdownTag($value['tags'])) {
$value = stripNoMarkdownTag($value);
continue;
}
$value['description'] = process_markdown($value['description']);
$value['description'] = process_markdown($value['description'], $conf->get('security.markdown_escape', true));
}
return $data;
@ -53,11 +55,12 @@ function hook_markdown_render_feed($data)
/**
* Parse daily descriptions.
*
* @param array $data daily data.
* @param array $data daily data.
* @param ConfigManager $conf instance.
*
* @return mixed daily data parsed in markdown (and converted to HTML).
*/
function hook_markdown_render_daily($data)
function hook_markdown_render_daily($data, $conf)
{
// Manipulate columns data
foreach ($data['cols'] as &$value) {
@ -66,7 +69,10 @@ function hook_markdown_render_daily($data)
$value2 = stripNoMarkdownTag($value2);
continue;
}
$value2['formatedDescription'] = process_markdown($value2['formatedDescription']);
$value2['formatedDescription'] = process_markdown(
$value2['formatedDescription'],
$conf->get('security.markdown_escape', true)
);
}
}
@ -250,7 +256,7 @@ function sanitize_html($description)
$description);
}
$description = preg_replace(
'#(<[^>]+)on[a-z]*="[^"]*"#is',
'#(<[^>]+)on[a-z]*="?[^ "]*"?#is',
'$1',
$description);
return $description;
@ -265,10 +271,11 @@ function sanitize_html($description)
* 5. Wrap description in 'markdown' CSS class.
*
* @param string $description input description text.
* @param bool $escape escape HTML entities
*
* @return string HTML processed $description.
*/
function process_markdown($description)
function process_markdown($description, $escape = true)
{
$parsedown = new Parsedown();
@ -278,7 +285,7 @@ function process_markdown($description)
$processedDescription = reverse_text2clickable($processedDescription);
$processedDescription = unescape($processedDescription);
$processedDescription = $parsedown
->setMarkupEscaped(false)
->setMarkupEscaped($escape)
->setBreaksEnabled(true)
->text($processedDescription);
$processedDescription = sanitize_html($processedDescription);