mirror of
https://github.com/janeczku/calibre-web
synced 2026-08-25 04:08:52 +00:00
Fix for xss on author page
This commit is contained in:
+34
-2
@@ -22,6 +22,7 @@ import inspect
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
from flask import Blueprint, request, url_for, make_response, jsonify
|
||||
from .cw_login import current_user
|
||||
@@ -38,6 +39,37 @@ meta = Blueprint("metadata", __name__)
|
||||
|
||||
log = logger.create()
|
||||
|
||||
|
||||
def _safe_metadata_url(value):
|
||||
if not isinstance(value, str):
|
||||
return ""
|
||||
value = value.strip()
|
||||
if not value:
|
||||
return ""
|
||||
parsed = urlsplit(value)
|
||||
if parsed.scheme in ("http", "https"):
|
||||
return value
|
||||
if not parsed.scheme and value.startswith("/"):
|
||||
return value
|
||||
return ""
|
||||
|
||||
|
||||
def _sanitize_metadata_record(record):
|
||||
record["url"] = _safe_metadata_url(record.get("url"))
|
||||
record["cover"] = _safe_metadata_url(record.get("cover"))
|
||||
source = record.get("source")
|
||||
if isinstance(source, dict):
|
||||
source["link"] = _safe_metadata_url(source.get("link"))
|
||||
return record
|
||||
|
||||
|
||||
def _serialize_metadata_records(records):
|
||||
return [
|
||||
_sanitize_metadata_record(asdict(record))
|
||||
for record in (records or [])
|
||||
if record
|
||||
]
|
||||
|
||||
try:
|
||||
from dataclasses import asdict
|
||||
except ImportError:
|
||||
@@ -114,7 +146,7 @@ def metadata_change_active_provider(prov_name):
|
||||
provider = next((c for c in cl if c.__id__ == prov_name), None)
|
||||
if provider is not None:
|
||||
data = provider.search(new_state.get("query", ""))
|
||||
return make_response(jsonify([asdict(x) for x in data]))
|
||||
return make_response(jsonify(_serialize_metadata_records(data)))
|
||||
return ""
|
||||
|
||||
|
||||
@@ -135,5 +167,5 @@ def metadata_search():
|
||||
if active.get(c.__id__, True)
|
||||
}
|
||||
for future in concurrent.futures.as_completed(meta):
|
||||
data.extend([asdict(x) for x in (future.result() or []) if x])
|
||||
data.extend(_serialize_metadata_records(future.result()))
|
||||
return make_response(jsonify(data))
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<div class="cover">
|
||||
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
||||
<span class="img" title="{{entry.Books.title}}">
|
||||
{{ image.book_cover(entry.Books, alt=author.name|safe) }}
|
||||
{{ image.book_cover(entry.Books, alt=author.name) }}
|
||||
{% if entry[2] == True %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@@ -263,26 +263,26 @@
|
||||
|
||||
{% block js %}
|
||||
<script type="text/template" id="template-book-result">
|
||||
<li class="media" data-related="<%= source.id %>">
|
||||
<li class="media" data-related="<%- source.id %>">
|
||||
<img class="pull-left img-responsive"
|
||||
data-toggle="modal"
|
||||
data-target="#metaModal"
|
||||
src="<%= cover || "{{ url_for('static', filename='img/academicpaper.svg') }}" %>"
|
||||
src="<%- cover || '{{ url_for('static', filename='img/academicpaper.svg') }}' %>"
|
||||
alt="Cover"
|
||||
>
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading">
|
||||
<a class="meta_title" href="<%= url %>" target="_blank" rel="noopener"><%= title %></a>
|
||||
<a class="meta_title" href="<%- url %>" target="_blank" rel="noopener"><%- title %></a>
|
||||
</h4>
|
||||
<p class="meta_author">{{_('Author')}}:<%= authors.join(" & ") %></p>
|
||||
<p class="meta_author">{{_('Author')}}:<%- authors.join(" & ") %></p>
|
||||
<% if (publisher) { %>
|
||||
<p class="meta_publisher">{{_('Publisher')}}:<%= publisher %></p>
|
||||
<p class="meta_publisher">{{_('Publisher')}}:<%- publisher %></p>
|
||||
<% } %>
|
||||
<% if (description) { %>
|
||||
<p class="meta_description">{{_('Description')}}: <%= description %></p>
|
||||
<p class="meta_description">{{_('Description')}}: <%- description %></p>
|
||||
<% } %>
|
||||
<p>{{_('Source')}}:
|
||||
<a class="meta_source" href="<%= source.link %>" target="_blank" rel="noopener"><%= source.description %></a>
|
||||
<a class="meta_source" href="<%- source.link %>" target="_blank" rel="noopener"><%- source.description %></a>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -353,6 +353,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
|
||||
Reference in New Issue
Block a user