summaryrefslogtreecommitdiff
path: root/qutebrowser
AgeCommit message (Collapse)Author
2022-04-01Store raw key in modeman.KeyEventqt6-testFlorian Bruhin
We don't know if this is a valid Qt.Key at this point. See #7045 and #7047
2022-03-31Ignore invalid keysFlorian Bruhin
Workaround for #7047, supersedes #7045
2022-03-04Avoid confusion by static method forPage()JingMatrix
Follow the advice in #7049
2022-03-03Qt6 WebEnginePage creatWindow api changeJingMatrix
When double-clicking a network resource in the devtools, one get AttributeError: 'WebEnginePage' object has no attribute 'view'.
2022-01-06FIXME: Rely on QtWebEngine for mouse back/forward for nowFlorian Bruhin
2022-01-05Fix clicking downloads with new enumsFlorian Bruhin
2022-01-04CVE-2021-41146: Add --untrusted-args to avoid argument injectionFlorian Bruhin
On Windows, if an application is registered as an URL handler like this: HKEY_CLASSES_ROOT https URL Protocol = "" [...] shell open command (Default) = ".../qutebrowser.exe" "%1" one would think that Windows takes care of making sure URLs can't inject arguments by containing a quote. However, this is not the case, as stated by the Microsoft docs: https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85) Security Warning: Applications that handle URI schemes must consider how to respond to malicious data. Because handler applications can receive data from untrusted sources, the URI and other parameter values passed to the application may contain malicious data that attempts to exploit the handling application. and As noted above, the string that is passed to a pluggable protocol handler might be broken across multiple parameters. Malicious parties could use additional quote or backslash characters to pass additional command line parameters. For this reason, pluggable protocol handlers should assume that any parameters on the command line could come from malicious parties, and carefully validate them. Applications that could initiate dangerous actions based on external data must first confirm those actions with the user. In addition, handling applications should be tested with URIs that are overly long or contain unexpected (or undesirable) character sequences. Indeed it's trivial to pass a command to qutebrowser this way - given how trivial the exploit is to recreate given the information above, here's a PoC: https:x" ":spawn calc (or qutebrowserurl: instead of https: if qutebrowser isn't registered as a default browser) Some applications do escape the quote characters before calling qutebrowser - but others, like Outlook Desktop or .url files, do not. As a fix, we add an --untrusted-args flag and some early validation of the raw sys.argv, before parsing any arguments or e.g. creating a QApplication (which might already allow injecting Qt flags there). We assume that there's no way for an attacker to inject flags *before* the %1 placeholder in the registry, and add --untrusted-args as the last argument of the registry entry. This way, it'd still be possible for users to customize their invocation flags without having to remove --untrusted-args. After --untrusted-args, however, we have some rather strict checks: - There should be zero or one arguments, but not two (or more) - Any argument may not start with - (flag) or : (qutebrowser command) We also add the --untrusted-args flag to the Linux .desktop file, though it should not be needed there, as the specification there is sane: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables Implementations must take care not to expand field codes into multiple arguments unless explicitly instructed by this specification. This means that name fields, filenames and other replacements that can contain spaces must be passed as a single argument to the executable program after expansion. There is no comparable mechanism on macOS, which opens the application without arguments and then sends an "open" event to it: https://doc.qt.io/qt-5/qfileopenevent.html This issue was introduced in qutebrowser v1.7.0 which started registering it as URL handler: baee2888907b260881d5831c68500941937261a0 / #4086 This is by no means an issue isolated to qutebrowser. Many other projects have had similar trouble with Windows' rather unexpected behavior: Electron / Exodus Bitcoin wallet: - http://web.archive.org/web/20190702112128/https://medium.com/0xcc/electrons-bug-shellexecute-to-blame-cacb433d0d62 - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000006 - https://medium.com/hackernoon/exploiting-electron-rce-in-exodus-wallet-d9e6db13c374 IE/Firefox: - https://bugzilla.mozilla.org/show_bug.cgi?id=384384 - https://bugzilla.mozilla.org/show_bug.cgi?id=1572838 Others: - http://web.archive.org/web/20210930203632/https://www.vdoo.com/blog/exploiting-custom-protocol-handlers-in-windows - https://parsiya.net/blog/2021-03-17-attack-surface-analysis-part-2-custom-protocol-handlers/ - etc. etc. See CVE-2021-41146 / GHSA-vw27-fwjf-5qxm: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-41146 https://github.com/qutebrowser/qutebrowser/security/advisories/GHSA-vw27-fwjf-5qxm Thanks to Ping Fan (Zetta) Ke of Valkyrie-X Security Research Group (VXRL/@vxresearch) for finding and responsibly disclosing this issue. (cherry picked from commit 8f46ba3f6dc7b18375f7aa63c48a1fe461190430)
2021-12-31Support fullscreen requests on Qt6Jimmy
QApplication.desktop() (And the QDesktopWidget that returns) has been deprecated since 5.11, we only support Qt 5.12+ (ref #3839). The recommended alternative is to use `QGuiApplication::screenAt(QPoint)`, but that doesn't support passing a widget. Stackoverflow [points out](https://stackoverflow.com/a/53490851) that you can get to the current screen of a widget, so that's what I'm using here. Once you get the screen there is both `geometry()` and `availableGeometry()` available. The later, sometimes, excludes window manager status bars and such, which fullscreen apps should cover. This approach works on both 5.15 and 6.2, so no version checks necessary.
2021-12-31sql: Make Query.bound_values() return a dict againJimmy
SqlQuery.boundValues() changed in Qt6 from returning a map of placeholders -> values to just providing a list of values. We can either: 1. follow that change and always return a list * this has the effect of making the return value have more items if the caller uses a placeholder more than once in a query, like histcategory does 2. maintain the current return type Here I have chosen to do (2). Although (1) is an option since it looks like no caller actually cares about the contents of the response at this point (apart from tests), just that it is Truthy/Falsy and the right length (if Truthy). And callers should know how many times they re-used placeholders so should be able to adjust their length comparison themselves. There is no API for enumerating placeholder labels anymore, if we want to maintain our API we must either 1) store the placeholders so we can look them up based on label later, 2) guess what they are (eg assume the caller always used sequential integers starting at 0), or 3) always return the dict keys as the positional indexes instead of labels (and return a larger dict if the caller used single placeholders multiple times). I've chosen to do 3 which should have the same result as the 5.15 implementation, at the cost of some more list allocations. So now we store the placeholders so we can query for them directly later. And the existing tests should all pass, if you can get them to run. This approach works on both 5.15 and 6.2, so no version checks necessary.
2021-12-14enum: fix search previousJimmy
FindFlags -> FindFlag int() argument must be a string, a bytes-like object or a number, not 'FindFlag' I didn't look for other occurances
2021-12-08Fix keyhint widget sequence match enum comparisonJimmy
Change it from a truthy check to a != Nomatch check. Also to to improve formatting but the line is probably still too long.
2021-12-04Let inspector know about on-the-record profiles.Jimmy
The developer tools only saves preferences to disk, and reads them from disk, if the profile of the page they are drawing to isn't off-the-record. So if you want it to remember your dark mode preference the page hosting the inspector needs to be linked to an on-the-record profile. So we need to create a new page linked to a specific profile and then set that on the view. Options at this point: 1. (in `__init__()` always make a new page linked to the qute default profile and add that to the view 2. delay creating the view and page until `inspect()` is called and get a pointer to the profile of the page being inspected (1) is actually what we have done on previous Qt versions because there the inspector was started with WebEngine's default, global, profile, which used to be on-the-record. I'm not sure if there are any specific ramifications to having the inspector data persistent when the page it is attached to isn't, but there might be stuff like per-domain preferences saved in that case which would be an information leak. So I've went with (2) even though it is probably going to be more disruptive to the tests. In the future if we re-use inspectors across different tabs/windows again we can make a new page on demand if the profile of the inspected page differs form the initial one. For now I've put an assert there because I am lazy. It's a bit awkward having most of the setup in `inspect()` and not `__init__()`. `_init_inspector()` and `inspect()` are only ever called once right beside each other though (now) so we could just pass the page to `__init__()` and get rid of `inspect()`.
2021-12-04elf: find webengine lib with wildcardJimmy
2021-11-28More QUrl problemsFlorian Bruhin
2021-11-28Another overloaded signalFlorian Bruhin
2021-11-28fix castFlorian Bruhin
2021-11-28download fixupFlorian Bruhin
2021-11-28Fix jseval JS worldFlorian Bruhin
2021-11-28More download APIFlorian Bruhin
2021-11-28Hide/Ignore some messagesFlorian Bruhin
2021-11-28QPointF needs to be explicit - PyQt bug?Florian Bruhin
2021-11-28Fix castFlorian Bruhin
2021-11-28Fix download APIFlorian Bruhin
2021-11-28Make default webengineprofile persistent again.Jimmy
Qt6 has switched to the global default profile being off-the-record, which is not the default for qutebrowser. Restore the previous default object name (although we always point it elsewhere anyway so that name should appear in any file paths). ref https://bugreports.qt.io/browse/QTBUG-66068
2021-11-28Switch back to JS WorldId Enums with .valueJimmy
ba6055d5d38a3f3 included some hasty fixups that caused a couple of places to the from ApplicationWorld to 1, instead of 2. This change mostly reverts that can calls .value in a couple of places since the WebEngine APIs wants ints for some reason.
2021-11-26Fix IPCFlorian Bruhin
2021-11-26Fix URL formatting issueFlorian Bruhin
2021-11-13fix matching bindings with modifiersJimmy
Doing `Qt.Key | Qt.KeyboardModifier` now results in a QKeyCombination. append_event() always does that (even if the modifier is NoModifier). Previous hacks round this area: e61597ca817e369c95 (initial keyhack, partially corrected in this commit) 1cc87d4d47bc15754d (initial QKeyCombination introduction) ab447bd396b46247f6 (Earlier attempt at a fix, mostly corrected in this commit)
2021-10-04Use new signal name for QNetworkReply::errorFlorian Bruhin
2021-10-03Make `go` work.Jimmy
Various QUrl methods that take a UrlFormattingOption enum member can also take ComponentFormattingOption ones but something doesn't know that and throws a TypeError. `url.toString(QUrl.UrlFormattingOption.RemovePassword | QUrl.ComponentFormattingOption.FullyEncoded)` works, `url.toString(QUrl.ComponentFormattingOption.FullyEncoded | QUrl.UrlFormattingOption.RemovePassword )` doesn't.
2021-10-03Make notifications mostly work.Jimmy
`QVariant.Type` has moved to `QMetaType.Type`[1][] and QMeta.Type doesn't work with int(). `QImage(':/icons/qutebrowser-64x64.png')` yields and empty QImage. This is not fixed but things don't crash because of it anymore. For instance the "Title & Body" test on https://web-push-book.gauntface.com/demos/notification-examples/ `QtWebEngineCore.QWebEnginePage.Feature` doesn't work with int(), so add it to the maps twice. `for s in scripts` was from a previous hack [1]: https://www.qt.io/blog/whats-new-in-qmetatype-qvariant
2021-10-03Make :search workJimmy
FindFlag doesn't work with int() either, use .value. FindTextResult doesn't act like a bool, call `numberOfMatches()`. Undo some disabled stuff that has been fixed upstream Emit a bool, not the FindTextResult object.
2021-10-03even more keypress related hacksJimmy
`QKeySequence.SequenceMatch` is one of the enums for which `Enum(0)` is no-longer falsey, compare to NoMatch instead. Otherwise the conditional is always false and forwarded keys don't work. Eg > from PyQt6.QtGui import QKeySequence, QKeyEvent > bool(QKeySequence.SequenceMatch.NoMatch) True > bool(QKeySequence.SequenceMatch(0)) True For `QKeySequence.SequenceMatch` and `QtCore.Qt.Key` and `QtCore.Qt.KeyboardModifier` int(enum_value) no longer works, eg > int(QtCore.Qt.KeyboardModifier(0)) TypeError: int() argument must be a string, a bytes-like object or a number, not 'KeyboardModifier'
2021-08-26FIXME QMouseEvent weirdnessFlorian Bruhin
2021-08-26More keyboard hacksFlorian Bruhin
2021-08-26Fix style enum accessFlorian Bruhin
2021-08-26key hacksFlorian Bruhin
2021-08-26QUrl hacksFlorian Bruhin
2021-08-26Fix findingFlorian Bruhin
2021-08-26Adjust importsFlorian Bruhin
2021-08-26QUrl issue?Florian Bruhin
2021-08-26Work around world id issueFlorian Bruhin
2021-08-26API stuffFlorian Bruhin
2021-08-26More enum changesFlorian Bruhin
2021-08-26More random API changesFlorian Bruhin
2021-08-26ImportsFlorian Bruhin
2021-08-26enum pluralFlorian Bruhin
2021-08-26Invalid keyFlorian Bruhin
2021-08-26OpenGL fixupFlorian Bruhin
2021-08-26Some more enum changesFlorian Bruhin