Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions app/lib/shared/markdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,19 @@ class _UnsafeUrlFilter extends html_parsing.TreeVisitor {
void visitElement(html.Element element) {
super.visitElement(element);

final isUnsafe =
_isUnsafe(element, 'a', 'href') || _isUnsafe(element, 'img', 'src');
final isUnsafe = _isUnsafe(element, 'a', 'href') ||
_isUnsafe(element, 'img', 'src', allowDataBase64: true);
if (isUnsafe) {
element.replaceWith(html.Text(element.text));
}
}

bool _isUnsafe(html.Element element, String tag, String attr) {
bool _isUnsafe(
html.Element element,
String tag,
String attr, {
bool allowDataBase64 = false,
}) {
if (element.localName != tag) {
return false;
}
Expand All @@ -194,14 +199,30 @@ class _UnsafeUrlFilter extends html_parsing.TreeVisitor {
return false;
}
final uri = Uri.tryParse(url);
if (uri == null || uri.isInvalid) {
var isInvalid = uri == null || uri.isInvalid;
if (allowDataBase64 &&
uri != null &&
uri.scheme == 'data' &&
_isValidDataBase64ImageUrl(uri.path)) {
isInvalid = false;
}
if (isInvalid) {
element.attributes.remove(attr);
return true;
}
return false;
}
}

bool _isValidDataBase64ImageUrl(String value) {
// NOTE: This is only a high-level check. It doesn't decode the image bytes,
// and it doesn't check if the content is valid and matching the specified type.
if (RegExp(r'^image/[a-z0-9\+\-]+;base64,.*$').matchAsPrefix(value) == null) {
return false;
}
return true;
}

/// Rewrites relative URLs with the provided [urlResolverFn].
class _RelativeUrlRewriter extends html_parsing.TreeVisitor {
final UrlResolverFn? urlResolverFn;
Expand Down
22 changes: 22 additions & 0 deletions app/test/shared/markdown_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,26 @@ void main() {
]);
});
});

group('data URLs', () {
final dataUrl =
'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';

test('rejected in links', () {
final output = markdownToHtml('[link]($dataUrl)');
expect(output, '<p>link</p>\n');
});

test('accepted in image', () {
// TODO: also enable data: URLs in sanitize_html
final output = markdownToHtml('![link]($dataUrl)');
expect(output, '<p><img alt="link"></p>\n');
});

test('rejected non-image', () {
final output =
markdownToHtml('![link](data:text/plain;base64,invalid-content)');
expect(output, '<p></p>\n');
});
});
}