Help/QtWebEngine: Prevent remote content

Showing remote content adds security implications

Change-Id: I0b5672d9c814b55aca05ea8a28da4f5e0e9f42fd
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Eike Ziller
2019-09-13 15:18:02 +02:00
parent 6b31f9cf23
commit 8d3e4c03f0
3 changed files with 67 additions and 3 deletions

View File

@@ -33,6 +33,7 @@
#ifdef QTC_WEBENGINE_HELPVIEWER #ifdef QTC_WEBENGINE_HELPVIEWER
#include "webenginehelpviewer.h" #include "webenginehelpviewer.h"
#include <QWebEngineUrlScheme>
#endif #endif
#ifdef QTC_LITEHTML_HELPVIEWER #ifdef QTC_LITEHTML_HELPVIEWER
#include "litehtmlhelpviewer.h" #include "litehtmlhelpviewer.h"
@@ -323,6 +324,13 @@ QVector<HelpViewerFactory> LocalHelpManager::viewerBackends()
{ {
QVector<HelpViewerFactory> result; QVector<HelpViewerFactory> result;
#ifdef QTC_WEBENGINE_HELPVIEWER #ifdef QTC_WEBENGINE_HELPVIEWER
static bool schemeRegistered = false;
if (!schemeRegistered) {
schemeRegistered = true;
QWebEngineUrlScheme scheme("qthelp");
scheme.setFlags(QWebEngineUrlScheme::LocalScheme | QWebEngineUrlScheme::LocalAccessAllowed);
QWebEngineUrlScheme::registerScheme(scheme);
}
result.append( result.append(
{kQtWebEngineBackend, tr("QtWebEngine"), []() { return new WebEngineHelpViewer; }}); {kQtWebEngineBackend, tr("QtWebEngine"), []() { return new WebEngineHelpViewer; }});
#endif #endif

View File

@@ -34,6 +34,7 @@
#include <QBuffer> #include <QBuffer>
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDesktopServices>
#include <QTimer> #include <QTimer>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWebEngineContextMenuData> #include <QWebEngineContextMenuData>
@@ -72,10 +73,40 @@ static HelpUrlSchemeHandler *helpUrlSchemeHandler()
return schemeHandler; return schemeHandler;
} }
HelpUrlRequestInterceptor::HelpUrlRequestInterceptor(QObject *parent)
: QWebEngineUrlRequestInterceptor(parent)
{}
void HelpUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
{
if (!HelpViewer::isLocalUrl(info.requestUrl())
&& info.navigationType() != QWebEngineUrlRequestInfo::NavigationTypeLink) {
info.block(true);
}
}
static HelpUrlRequestInterceptor *helpurlRequestInterceptor()
{
static HelpUrlRequestInterceptor *interceptor = nullptr;
if (!interceptor)
interceptor = new HelpUrlRequestInterceptor(LocalHelpManager::instance());
return interceptor;
}
WebEngineHelpViewer::WebEngineHelpViewer(QWidget *parent) : WebEngineHelpViewer::WebEngineHelpViewer(QWidget *parent) :
HelpViewer(parent), HelpViewer(parent),
m_widget(new WebView(this)) m_widget(new WebView(this))
{ {
// some of these should already be that way by default, but better be sure
QWebEngineSettings *settings = m_widget->settings();
settings->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, false);
settings->setAttribute(QWebEngineSettings::XSSAuditingEnabled, true);
settings->setAttribute(QWebEngineSettings::PluginsEnabled, false);
settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, false);
settings->setAttribute(QWebEngineSettings::AllowGeolocationOnInsecureOrigins, false);
settings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, false);
m_widget->setPage(new WebEngineHelpPage(this)); m_widget->setPage(new WebEngineHelpPage(this));
auto layout = new QVBoxLayout; auto layout = new QVBoxLayout;
setLayout(layout); setLayout(layout);
@@ -121,6 +152,7 @@ WebEngineHelpViewer::WebEngineHelpViewer(QWidget *parent) :
QTC_ASSERT(viewProfile, return); QTC_ASSERT(viewProfile, return);
if (!viewProfile->urlSchemeHandler("qthelp")) if (!viewProfile->urlSchemeHandler("qthelp"))
viewProfile->installUrlSchemeHandler("qthelp", helpUrlSchemeHandler()); viewProfile->installUrlSchemeHandler("qthelp", helpUrlSchemeHandler());
viewProfile->setUrlRequestInterceptor(helpurlRequestInterceptor());
} }
QFont WebEngineHelpViewer::viewerFont() const QFont WebEngineHelpViewer::viewerFont() const
@@ -286,12 +318,23 @@ WebEngineHelpPage::WebEngineHelpPage(QObject *parent)
{ {
} }
WebView::WebView(WebEngineHelpViewer *viewer) bool WebEngineHelpPage::acceptNavigationRequest(const QUrl &url,
: QWebEngineView(viewer), QWebEnginePage::NavigationType type,
m_viewer(viewer) bool isMainFrame)
{ {
Q_UNUSED(type)
Q_UNUSED(isMainFrame)
if (HelpViewer::isLocalUrl(url))
return true;
QDesktopServices::openUrl(url);
return false;
} }
WebView::WebView(WebEngineHelpViewer *viewer)
: QWebEngineView(viewer)
, m_viewer(viewer)
{}
bool WebView::event(QEvent *ev) bool WebView::event(QEvent *ev)
{ {
// work around QTBUG-43602 // work around QTBUG-43602

View File

@@ -27,6 +27,7 @@
#include "helpviewer.h" #include "helpviewer.h"
#include <QWebEngineUrlRequestInterceptor>
#include <QWebEngineUrlSchemeHandler> #include <QWebEngineUrlSchemeHandler>
#include <QWebEngineView> #include <QWebEngineView>
@@ -42,10 +43,22 @@ public:
void requestStarted(QWebEngineUrlRequestJob *job) override; void requestStarted(QWebEngineUrlRequestJob *job) override;
}; };
class HelpUrlRequestInterceptor : public QWebEngineUrlRequestInterceptor
{
public:
explicit HelpUrlRequestInterceptor(QObject *parent = nullptr);
void interceptRequest(QWebEngineUrlRequestInfo &info) override;
};
class WebEngineHelpPage : public QWebEnginePage class WebEngineHelpPage : public QWebEnginePage
{ {
public: public:
explicit WebEngineHelpPage(QObject *parent = nullptr); explicit WebEngineHelpPage(QObject *parent = nullptr);
protected:
bool acceptNavigationRequest(const QUrl &url,
QWebEnginePage::NavigationType type,
bool isMainFrame) override;
}; };
class WebView : public QWebEngineView class WebView : public QWebEngineView