feat: add iframe proxy for enhanced security

Introduced a proxy mechanism for handling iframes to improve security by preventing direct embedding of external content. External iframe URLs are now encoded and passed through a proxy endpoint, which renders a new template warning users about potential security risks.

Additionally, added button styles to CSS for consistent user experience and created an iframe security notice template.
This commit is contained in:
Kumi 2024-09-19 18:53:37 +02:00
parent e96a39448a
commit 2afc069724
Signed by: kumi
GPG key ID: ECBCC9082395383F
4 changed files with 35 additions and 2 deletions

View file

@ -4,6 +4,7 @@ from flask import url_for
from small.models.nodes import Page, Paragraph, Text, Image, IFrame, GithubGist from small.models.nodes import Page, Paragraph, Text, Image, IFrame, GithubGist
from urllib.parse import quote
from datetime import datetime from datetime import datetime
@ -74,9 +75,12 @@ class MediumClient:
gist_id = iframe["href"].split("/")[-1] gist_id = iframe["href"].split("/")[-1]
children = [GithubGist(id=gist_id)] children = [GithubGist(id=gist_id)]
else: else:
src = quote(iframe["iframeSrc"] or iframe["href"], safe="")
url = url_for("proxy.iframe") + f"?url={src}"
children = [ children = [
IFrame( IFrame(
src=iframe["iframeSrc"] or iframe["href"], src=url,
width=iframe["iframeWidth"], width=iframe["iframeWidth"],
height=iframe["iframeHeight"], height=iframe["iframeHeight"],
) )

View file

@ -18,6 +18,24 @@ a:hover {
text-decoration: underline; text-decoration: underline;
} }
a .btn {
display: inline-block;
padding: 10px 20px;
background-color: #1a73e8;
color: #fff;
border-radius: 5px;
text-align: center;
margin-top: 20px;
}
a .btn:hover {
background-color: #0d6efd;
}
a .btn:active {
background-color: #0b5ed7;
}
/* Header Styles */ /* Header Styles */
header { header {
border-bottom: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0;

View file

@ -0,0 +1,6 @@
<div class="error-container">
<h1>iframe blocked</h1>
<p>The article you are viewing has embedded external content from <code>{{ url }}</code>.</p>
<p>For security reasons, this content is blocked by default. You can view the content by clicking the button below.</p>
<a href="{{ url }}" class="btn">View content</a>
</div>

View file

@ -1,4 +1,4 @@
from flask import Blueprint, abort from flask import Blueprint, abort, render_template, request
from requests import get from requests import get
@ -13,3 +13,8 @@ def image(original_width, id):
except Exception as e: except Exception as e:
print(f"Error fetching image: {str(e)}") print(f"Error fetching image: {str(e)}")
abort(500) abort(500)
@bp.route("/iframe/")
def iframe():
return render_template("iframe.html", url=request.args.get("url"))