Age | Commit message (Collapse) | Author |
|
We don't know if this is a valid Qt.Key at this point.
See #7045 and #7047
|
|
Workaround for #7047, supersedes #7045
|
|
Follow the advice in #7049
|
|
When double-clicking a network resource in the devtools, one
get AttributeError: 'WebEnginePage' object has no attribute 'view'.
|
|
|
|
|
|
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)
|
|
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.
|
|
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.
|
|
FindFlags -> FindFlag
int() argument must be a string, a bytes-like object or a number, not 'FindFlag'
I didn't look for other occurances
|
|
Change it from a truthy check to a != Nomatch check.
Also to to improve formatting but the line is probably still too long.
|
|
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()`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
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.
|
|
|
|
|
|
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)
|
|
|
|
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.
|
|
`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
|
|
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.
|
|
`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'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|