ankitects / anki

Anki's shared backend and web components, and the Qt frontend
https://apps.ankiweb.net
Other
18.78k stars 2.13k forks source link

patch to bypass CORS for iframe-related cards #2007

Closed ericries closed 2 years ago

ericries commented 2 years ago

I hope this is the right place to post this. I have been doing a lot of Anki using cards that are generated by third-party open source programs like chessli and anki-ogs. Some websites have a restrictive security policy that prevents their pages from being run inside an iframe, which AFAICT is the only way to get a full-screen web-based card.

From the pyqt docs it looks like a relatively small change required to give the user the option to bypass this setting, which doesn't really provide any security for Anki (I understand why it's included in standard web browsers). If I produced a patch, would you accept it?

Alternatively, i could look into creating a way to specify a URL-based card that would direct pyqt to load that page as the top-level window. So http://example.com/id/{{itemId}} would work without an iframe

dae commented 2 years ago

What setting are you proposing to change? As far as I'm aware, the security policies are for the benefits of the sites themselves, not the site that is trying to embed them. Coincidentally, this popped up in my news feeds today: https://www.holovaty.com/writing/framebust-native-apps/.

Do those iframes work when viewing the cards on AnkiWeb? If not, then I would be reluctant to introduce a change to the desktop that didn't work on other platforms. If it just requires toggling a setting though, you can probably fairly easily do that in an add-on.

ericries commented 2 years ago

That's a funny coincidence. In this case, I think Anki is a legitimate browser unto itself. It's not trying to trick the user into not using the default browser. It's legitimately presenting the information (at the user's direction) that the user requested.

I just tried both card types on AnkiWeb. The behavior is the same as on desktop - the site without restrictive CORS renders perfectly and the other cannot render.

What do you think of the idea of allowing a card type that was simply a URL? that would avoid the problem of requiring an iframe

In terms of the change I would make, it might be to use the existing "--disable-web-security" command line option that PyQt used to support (if it still does). Or I think it's possible to pass the relevant options through to QtWebEngine. If this is achievable via an add-on, I will be happy to do it that way, keeping the complexity out of the main app. Does this sound plausible as an approach?

dae commented 2 years ago

Disabling web security is not an option in the core code, as it would allow JavaScript to exfiltrate data from the local filesystem. If you're happy to take that risk, you can set the QTWEBENGINE_CHROMIUM_FLAGS="--disable-web-security" env var before invoking Anki.

What do you think of the idea of allowing a card type that was simply a URL? that would avoid the problem of requiring an iframe

It's not practical, as the review screen has its own logic in JS.

ericries commented 2 years ago

I just gave that a try, thanks for the pointer to QTWEBENGINE_CHROMIUM_FLAGS. Unfortunately, it didn't seem to work. I wonder if they've removed --disable-web-security from Qt, as I don't see it in the documentation anymore.

I guess the only solution will be to push the user outside Anki to the system default browser, as in the link you shared above. Unfortunately for the Anki use case, that's going to be quite a few extra clicks per-card, which will slow down reviews. I'll keep thinking if there's some way to solve the problem, perhaps as a plugin. Thanks again for your help (and for Anki itself, obvs!)

dae commented 2 years ago

I was able to access a local file when setting that flag, so it does seem to work - maybe it's just not a solution for your particular case. And add-on does sound like the best path forward.

And thank you for the kind words :-)

khonkhortisan commented 8 months ago
This is more complex than "How do I bypass www.example.com refused to connect.?"; the real question is "How do I incorporate scripted content into Anki?" puzzle imported iframe default language linkless refused to connect
blackbox gamegix
⌵checkers / ⤫draughts / ✳frisian lidraughts checkercruncher
chess mate&advantage endgame
chess chinese wukong wukong xiangqi.com
chess japanese lishogi playshogi
chess korean pychess
chess laser laser-chess
connect four zeilberg zeilberg
dictionary sign signpuddle signingsavvy
dictionary spanish verbix dle spanishdict
dna alignment phylo
go online-go
gungi gungi.io
hashi-o-kakero gamegix
logic gates nandgame
nonograms gamegix
protein folding foldit
rna folding eterna
rush hour michaelfogleman
<script>
if ("{{iframe url}}".includes("eternagame.org")) {
  if(!document.querySelector(".firefox"))) // use an x-frame-options addon instead
    window.location.href="{{iframe url}}"; // automatically open in external browser
}
</script>
// ==UserScript==
// @name        close on focus loss
// @match       https://www.checkercruncher.com/problems/*
// @match       https://eternagame.org/puzzles/*/play
// @match       https://www.signingsavvy.com/sign/*
// ==/UserScript==

//discard second tab
document.addEventListener( 'visibilitychange' , function() {
    if (document.hidden) {
        console.log('bye');
        window.close();
    } else {
        console.log('well back');
    }
}, false );