Improve ad security, add CMP changes (#2399)

This commit is contained in:
Geometrically
2024-09-13 20:33:51 -07:00
committed by GitHub
parent 3d619e6a98
commit 95cd48571e
16 changed files with 220 additions and 169 deletions

View File

@@ -226,6 +226,8 @@ fn main() {
"hide_ads_window",
"scroll_ads_window",
"show_ads_window",
"record_ads_click",
"open_link",
])
.default_permission(
DefaultPermissionRule::AllowAllCommands,

View File

@@ -9,7 +9,6 @@
"ads-window"
],
"permissions": [
"shell:allow-open",
"ads:default"
]
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"ads":{"identifier":"ads","description":"","remote":{"urls":["https://modrinth.com/*","http://localhost:3000/*"]},"local":false,"webviews":["ads-window"],"permissions":["shell:allow-open","ads:default"]},"core":{"identifier":"core","description":"","local":true,"windows":["main"],"permissions":["core:default","core:path:default","core:event:default","core:window:default","core:app:default","core:resources:default","core:menu:default","core:tray:default","core:window:allow-create","core:window:allow-maximize","core:window:allow-toggle-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-set-decorations","core:window:allow-start-dragging","core:webview:allow-set-webview-zoom"]},"plugins":{"identifier":"plugins","description":"","local":true,"windows":["main"],"permissions":["dialog:allow-open","dialog:allow-confirm","shell:allow-open","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","deep-link:default","window-state:default","window-state:allow-restore-state","window-state:allow-save-window-state","auth:default","import:default","jre:default","logs:default","metadata:default","mr-auth:default","profile-create:default","pack:default","process:default","profile:default","cache:default","settings:default","tags:default","utils:default","ads:default"]},"updater":{"identifier":"updater","description":"","local":true,"windows":["main"],"permissions":["updater:default"]}}
{"ads":{"identifier":"ads","description":"","remote":{"urls":["https://modrinth.com/*","http://localhost:3000/*"]},"local":false,"webviews":["ads-window"],"permissions":["ads:default"]},"core":{"identifier":"core","description":"","local":true,"windows":["main"],"permissions":["core:default","core:path:default","core:event:default","core:window:default","core:app:default","core:resources:default","core:menu:default","core:tray:default","core:window:allow-create","core:window:allow-maximize","core:window:allow-toggle-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-set-decorations","core:window:allow-start-dragging","core:webview:allow-set-webview-zoom"]},"plugins":{"identifier":"plugins","description":"","local":true,"windows":["main"],"permissions":["dialog:allow-open","dialog:allow-confirm","shell:allow-open","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","deep-link:default","window-state:default","window-state:allow-restore-state","window-state:allow-save-window-state","auth:default","import:default","jre:default","logs:default","metadata:default","mr-auth:default","profile-create:default","pack:default","process:default","profile:default","cache:default","settings:default","tags:default","utils:default","ads:default"]},"updater":{"identifier":"updater","description":"","local":true,"windows":["main"],"permissions":["updater:default"]}}

View File

@@ -320,6 +320,20 @@
"ads:allow-init-ads-window"
]
},
{
"description": "ads:allow-open-link -> Enables the open_link command without any pre-configured scope.",
"type": "string",
"enum": [
"ads:allow-open-link"
]
},
{
"description": "ads:allow-record-ads-click -> Enables the record_ads_click command without any pre-configured scope.",
"type": "string",
"enum": [
"ads:allow-record-ads-click"
]
},
{
"description": "ads:allow-scroll-ads-window -> Enables the scroll_ads_window command without any pre-configured scope.",
"type": "string",
@@ -348,6 +362,20 @@
"ads:deny-init-ads-window"
]
},
{
"description": "ads:deny-open-link -> Denies the open_link command without any pre-configured scope.",
"type": "string",
"enum": [
"ads:deny-open-link"
]
},
{
"description": "ads:deny-record-ads-click -> Denies the record_ads_click command without any pre-configured scope.",
"type": "string",
"enum": [
"ads:deny-record-ads-click"
]
},
{
"description": "ads:deny-scroll-ads-window -> Denies the scroll_ads_window command without any pre-configured scope.",
"type": "string",

View File

@@ -320,6 +320,20 @@
"ads:allow-init-ads-window"
]
},
{
"description": "ads:allow-open-link -> Enables the open_link command without any pre-configured scope.",
"type": "string",
"enum": [
"ads:allow-open-link"
]
},
{
"description": "ads:allow-record-ads-click -> Enables the record_ads_click command without any pre-configured scope.",
"type": "string",
"enum": [
"ads:allow-record-ads-click"
]
},
{
"description": "ads:allow-scroll-ads-window -> Enables the scroll_ads_window command without any pre-configured scope.",
"type": "string",
@@ -348,6 +362,20 @@
"ads:deny-init-ads-window"
]
},
{
"description": "ads:deny-open-link -> Denies the open_link command without any pre-configured scope.",
"type": "string",
"enum": [
"ads:deny-open-link"
]
},
{
"description": "ads:deny-record-ads-click -> Denies the record_ads_click command without any pre-configured scope.",
"type": "string",
"enum": [
"ads:deny-record-ads-click"
]
},
{
"description": "ads:deny-scroll-ads-window -> Denies the scroll_ads_window command without any pre-configured scope.",
"type": "string",

View File

@@ -1,6 +1,8 @@
if (!window.modrinthClickListener) {
window.modrinthClickListener = true
document.addEventListener('click', function (e) {
document.addEventListener(
'click',
function (e) {
window.top.postMessage({ modrinthAdClick: true }, 'https://modrinth.com')
let target = e.target
while (target != null) {
if (target.matches('a')) {
@@ -12,8 +14,9 @@ if (!window.modrinthClickListener) {
}
target = target.parentElement
}
})
}
},
true,
)
window.open = (url, target, features) => {
window.top.postMessage({ modrinthOpenUrl: url }, 'https://modrinth.com')

View File

@@ -1,12 +1,19 @@
use serde::Serialize;
use std::collections::HashSet;
use std::time::{Duration, Instant};
use tauri::plugin::TauriPlugin;
use tauri::{Emitter, LogicalPosition, LogicalSize, Manager, Runtime};
use tauri::{
Emitter, Listener, LogicalPosition, LogicalSize, Manager, Runtime,
};
use tauri_plugin_shell::{open, ShellExt};
use tokio::sync::RwLock;
pub struct AdsState {
pub shown: bool,
pub size: Option<LogicalSize<f32>>,
pub position: Option<LogicalPosition<f32>>,
pub last_click: Option<Instant>,
pub malicious_origins: HashSet<String>,
}
pub fn init<R: Runtime>() -> TauriPlugin<R> {
@@ -16,6 +23,8 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
shown: true,
size: None,
position: None,
last_click: None,
malicious_origins: HashSet::new(),
}));
// We refresh the ads window every 5 minutes for performance
@@ -43,6 +52,8 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
hide_ads_window,
scroll_ads_window,
show_ads_window,
record_ads_click,
open_link,
])
.build()
}
@@ -75,7 +86,7 @@ pub async fn init_ads_window<R: Runtime>(
let _ = webview.set_size(LogicalSize::new(width, height));
}
} else if let Some(window) = app.get_window("main") {
let _ = window.add_child(
let window = window.add_child(
tauri::webview::WebviewBuilder::new(
"ads-window",
WebviewUrl::External(
@@ -93,6 +104,12 @@ pub async fn init_ads_window<R: Runtime>(
},
LogicalSize::new(width, height),
);
if let Ok(window) = window {
window.listen_any("click", |event| {
println!("click: {:?}", event);
});
}
}
Ok(())
@@ -159,3 +176,43 @@ pub async fn scroll_ads_window<R: Runtime>(
Ok(())
}
#[tauri::command]
pub async fn record_ads_click<R: Runtime>(
app: tauri::AppHandle<R>,
) -> crate::api::Result<()> {
let state = app.state::<RwLock<AdsState>>();
let mut state = state.write().await;
state.last_click = Some(Instant::now());
Ok(())
}
#[tauri::command]
pub async fn open_link<R: Runtime>(
app: tauri::AppHandle<R>,
path: String,
origin: String,
) -> crate::api::Result<()> {
let state = app.state::<RwLock<AdsState>>();
let mut state = state.write().await;
if url::Url::parse(&path).is_ok()
&& !state.malicious_origins.contains(&origin)
{
if let Some(last_click) = state.last_click {
if last_click.elapsed() < Duration::from_millis(100) {
let _ = app.shell().open(&path, None);
state.last_click = None;
return Ok(());
}
}
}
tracing::info!("Malicious click: {path} origin {origin}");
state.malicious_origins.insert(origin);
Ok(())
}