Chrome: Heap buffer overflow in WebP
chromereleases.googleblog.com
chromereleases.googleblog.com
Since the renderer is very complex, there are lots of exploits discovered each year for it. However, when someone manages to get code execution in a renderer they don't get much more access than a webpage would normally get. Specifically, they can't see or leave files on the filesystem of your machine, nor even read cookies for other domains.
Unless of course there is a sandbox break-out exploit to combine this with. So not an immediate priority, unless there is such an exploit in the wild that I don't know about, but important to patch as soon as not terribly inconvenient.
It doesn't say if it breached the sandbox (I'd expect another CVE if there is an active sandbox flaw also), or indeed if the exploit targeted Chrome specifically at all or the library more generally.
1. First, once you "local root" within the sandboxed process what can you compromise?
a. Can the session cookies be stolen? (Think gmail inline attachment rendering a malicious webp image).
b. Can you launch attack on other local network resources from within the compromised sandbox – read insecure filesystems, make tcp sockets to local resources etc – these are not prevented by OS sandboxing capabilities that Chrome depends on.
2. Second, can you probe for vulnerabilities in OS sandboxing that chrome depends on to break out of sandbox? On older unpatched OS versions this is definitely possible. These attack vectors may have been fixed in newer patches of OS already so you won't see a new CVE and patch for the same from the OS vendors.
Huh? Chrome on Linux uses a network namespace to remove all networking from the renderer process, and then uses seccomp to forbid most system calls, and can very easily prevent e.g. opening new sockets with that.
https://chromium.googlesource.com/chromiumos/docs/+/HEAD/san...
https://blog.chromium.org/2012/11/a-safer-playground-for-you...
https://blog.cr0.org/2012/09/introducing-chromes-next-genera...
2, as they mentioned, is the separate CVE they suggested.
https://chromium.googlesource.com/chromium/src/+/main/docs/p...
It was initially reported as an exploit in Apple's ImageIO library, which is not properly sandboxed on iOS. https://citizenlab.ca/2023/09/blastpass-nso-group-iphone-zer...
The exploit could be a PoC that at the moment does something noticeable but relatively innocuous. If there was a sandbox exploit that is already exploited along with this one, I'd expect this announcement to have been held back until when (or after) the other is announced.
ACE & RCE bugs should be taken this seriously even if another (as yet not known to exist) bug needs to be chained with it in order to do _real_ damage, because for all we know a black-hat out there could be sat on such a bug hoping no one else notices (and therefore it gets fixed) before something like this comes along to provide the other half of a really serious zero-day PitA.
Why would you exploit some DC lawyer with a POC?
The Fucking Article
You can say "The Fine Article" if you're feeling nice. :)
Unless you're saying "Did you even read the TFA?!?" but that would violate the code of conduct around here.
Chrome doesn't spin up another process to render the image and then transfer the pixels.
Exploits aside, there are quite a few undesirable behaviours you can cause with media, such as the bouncing video file which changes it's height every frame and makes content around it reflow.
Otherwise an evil client uploads a malicious webp image, which then gets hosted and 'shared' by the server to other users, who upon viewing said image get exploited and share more malicious images...
Not transcoding user-uploaded files is borderline negligent.
(The game would generate a "card" with a visual preview, but would stuff the XML encoding of the creation into some PNG metadata field so the image could be dragged onto someone else's game.)
(oops, wrong thread, meant to reply to https://news.ycombinator.com/item?id=37479576 "jpeg is good enough")
Also, perhaps you turned off JavaScript, and now all of a sudden the website can still execute code?
That doesn’t mean we shouldn’t do new things but I think as developers we’re prone to underestimate the cost pretty heavily.
One example: that’s great for Firefox but that helps a format become more common, which increases the likelihood of tools integrating a library but not using a browser-grade sandbox. How many apps end up passing user uploads through something like ImageMagick, for example? (And how many years will it be before the last container image is updated?)
(I've contributed to wasm2c and think it's a cool tool.)
But your reasoning is valid, it seems like a few weeks ago, netizen were arguing that jpeg xl should be adopted as fast as possible, and for that to be possible the browser developer "only needed to include the reference decoder code into their codebase" at "very little cost".
Because otherwise AVIF should not have made into the codebase. High-profile C/C++ projects can't prevent all security bugs, but they can make them easier to find and harder to get in. AVIF and JPEG XL roughly have the same impact in this regard (written in C++, uses Google's standard convention, tested and fuzzed regularly, and so on).
HEIF container parsing was the additional attack surface added by AVIF, and while it's probably more complex than JPEG-XL's container alone, it's definitely less complex than a full JPEG-XL decoder.
Isn’t all of that true of libwebp? I’m sympathetic to the argument that it’s a lot of work to replace C but I’ve been hearing that C/C++ will be safer with enough diligence and better tools since the 90s and it hasn’t happened yet.
What I wonder is whether this is saying there should be two tiers, where stuff like JPEG XL might be implemented in WASM for better sandboxing so browsers could more easily add support with less security risk and then possibly “promote” it to a core format if it proves successful and there’s enough performance win.
https://citizenlab.ca/2023/09/blastpass-nso-group-iphone-zer...
That said, I also blame the culture of making code more complex than necessary, along with developers who barely understand the details.
Second, I don’t think this is preventing better formats due to safety conservatism - AVIF is at roughly 83% and climbing – but it does support the argument that the Chrome team has too much unilateral control over the web. I don’t think their opposition to JPEG-XL is solely based on the support cost.
If you're interested in an open source (AGPL-3.0) solution for zero trust browser isolation check out BrowserBox on GitHub. We are using JPEG (now WebP) for viewport pixels: https://github.com/dosyago/BrowserBoxPro
Technically, we did try using WebP due to its significant bandwidth gains. However, the compute overhead for encoding versus JPEG introduced unacceptable latency into our streaming pipeline, so for now, we're still against it. Security is an additional mark against the newer standard, as good as it is!
And I would argue that beside Facebook, the end user right clicking and saving the image for them to use in an inappropriate manner ( downloading the image is not the issue, using it without permission would cause copyright infringement ) would be an issue for some of the website that are hosting the image.
No argument - my point was simply that very few sites on the web fall into that category.
> And I would argue that beside Facebook, the end user right clicking and saving the image for them to use in an inappropriate manner
That’s only true for a subset of sites, only to the extent that this wasn’t covered by fair use, and it came up enough that it was a common objection.
(We evaluated it for storing a bunch of other stuff but didn't find it worth the compatibility and need to transcode problems)
Why I love features like Fastly's Image Optimizer. No extra work on our end but we get the bandwidth savings https://www.fastly.com/products/image-optimization
Maybe I’ll use an open, safe but feature incomplete webp implementation because I don’t care if three pixes are missing or the colors are not quite correct. Maybe I’ll provide a NULL renderer because I just don’t care.
I know this sounds stupid, but a man can wonder.
There is also WebCodecs API: https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_A...
It used to be quite incomplete for a long time, but work last year has implemented many webp features. Chromium now has a policy of allowing the use of Rust dependencies, so maybe Chromium could start adopting it?
I don't think that's the whole story. Chrome aggressively marketed itself around its sandboxing and security at a time when browser drive bys were huge. Anyone I recommended Chrome to, I did so because of security, not performance.
> if 99.99% of users aren't going to use it,
Ideally the crate would get closer and closer to the performance required to enable it entirely. I just meant as a temporary state.
Also, I think more than .01% of users would enable it if there were a checkbox on install like "We can make your browser a tiny bit slower but potentially increase its security".
> it's probably not worth it to bloat the binary size either.
eh, there's so much in `chrome://flags` I don't think that they mind too much? idk
The commit that fixes this bug: https://github.com/webmproject/libwebp/commit/902bc919033134...
The original commit optimizes a Huffman decoder. The decoder uses a well-known optimization: it reads N bits in advance and determines how many bits have to be actually consumed and which symbol should be decoded, or, if it's an N-bit prefix of multiple symbols, which table should be consulted for remaining bits.
The old version did use lookup tables for short symbols, but longer symbols needed a graph traversal. The new version improved this by using an array of lookup tables. Each entry contains (nbits, value) where `nbits` is # bits to be consumed and `value` is normally a symbol, but if `nbits` exceeds N `value` is interpreted as a table index and `nbits` is reinterpreted as the longest code length in that subtree. So each subsequent table should have `2^(nbits - N)` entries (the root table is always fixed to 2^N entries).
The new version calculated the maximum number of entries based on the number of symbols (kTableSize). Of course, the Huffman tree comes from an untrusted source and you can easily imagine the case where `nbits` is very big. VP8 Lossless specifically allows up to 15 bits, so the largest possible table has 2^N + 2^15 entries when every single LUT is mapped to its own secondary table, and doing this doesn't need that many symbols (you only need 16-N symbols for each table). Amusingly enough the code itself had a mode where only the table size is calculated (VP8LBuildHuffmanTable called with `root_table == NULL`), but it wasn't somehow unused and the fixed maximum size was assumed. So if the Huffman tree was crafted in the way that maximizes the number of entries, it will overflow the allocation.
To be fair, I can see why this happened; the Huffman decoding step is one of the most computationally intensive part of many compression format and any small improvement matters. The Huffman decoder optimization described above is well known, but the longer code case is commonly considered less important to optimize because longer code should rarely appear in general. The original commit message refuted this, and was able to be merged. I'm not even sure that a memory safe language could have prevented this; this is a rare case where you actively want to avoid the overflow check [1].
[1] I should note that the memory corruption occurs during the table construction, which is not a tight loop, so a partial overflow check would be very helpful. The actual fix never altered the `ReadSymbol` function at all! But the safety of the tight loop should be still justified, so the wrong justification can ruin everything.
This component should be written in WUFFS. If you were correct, that the bounds check isn't needed that's fine, WUFFS doesn't emit runtime bounds checks. If, as was the case here, the software is wrong because it has a bounds miss, that won't compile in WUFFS.
You might be thinking, "That's impossible" and if WUFFS was a general purpose programming language you'd be correct. Rice's Theorem, non-trivial semantic properties are Undecidable. Fortunately WUFFS isn't a general purpose language. The vast majority of software can't be written with WUFFS. But you can write image codecs.
[1] https://github.com/google/wuffs/blob/main/doc/wuffs-the-lang...
[2] https://github.com/google/wuffs/blob/main/doc/note/memory-sa...
It's better that the codec is 100% safe but there's a tiny amount of unsafe glue code, than make the codec unsafe to add generality.
Google has smart people, finding the bug in 15 lines of glue code before it goes out the door is definitely easier than finding this C bug.
This is the same thing that powers Rust successfully, but taking it further.
I meant that many codec cannot be easily made in such way because memory allocation can occur here and there.
This is an extremely vague complaint and thus suspicious. Of course we could imagine an image format which decides to allow you to declaratively construct cloud servers which transmit XML and so it needs DRM to protect your cloud service credentials - but I claim (and I feel like most people will agree) the fact WUFFS can't do that is a good thing and we should not use this hypothetical "image" format aka massive security hole.
Try specifics. This is a WebP bug. For a WebP codec, where does it need memory allocation? My guess is it does allocations only during a table creation step, and after it figures out how big the final image is. So, twice, in specific parts of the code, like JPEG.
Oh, you could design a more complex API to avoid that - but I'm a programmer of very average ability, ask me to juggle too many buffers and struts and I'll probably introduce a buffer overflow by mistake.
Look I have nothing against using WUFFS but I don’t think you’re in a strong position to determine what’s suspicious: https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
It's not going to stop being true, and I don't get the impression most HN readers already knew this sort of work should be WUFFS, so I'm going to keep saying it.
You can pair me with lots of things, "tialaramex vaccine" works, "tialaramex oil", "tialaramex UTF8", "tialaramex Minecraft".
What about HW decoders? Of video formats (that are much more complex than image decoders)? Such as MPEG, H.264, H.265, VP9, AV1 and similar. If memory allocation is needed here and there, I guess there is always known maximum size of such allocation in advance. Written in the spec. Think of at chip design time, or at software decoder compile time. How else would HW decoders be even possible?
Also: Hey Google, do you even fuzz-test? Your own stuff?
Of course the issue with transpiled code ( same for generated code ), is that is making debugging a lot more difficult.
[1] https://source.chromium.org/chromium/chromium/src/+/main:thi...
A fair chunk out of that 1000 lines of glue code is adapting Wuffs' API to Skia's API. (Skia is the 2-D graphics library used by Chromium and many other projects). Specifically, GIFs can be animated, Wuffs' animation API is designed for sequential access and its state needs O(1) memory but Skia's SkCodec animation API allows random access and needs O(N) memory, where N is the number of animation frames.
Random access means that, after decoding frame 100, the SkCodec can rewind and produce frame 70 (by scanning backwards through its O(N) state to find the most recent I-Frame equivalent that's <= 70 and replaying forward from there).
Random access seems a bit of a weird feature to me, but Chrome/Skia's old GIF codec could do it, for whatever historical reasons, so the new Wuffs-backed one does too (even though it needed a chunk of glue code).
I’m not a C programmer over the past decade+ and was never very good at it anyway. But I was thinking, based on your description, I agree that a bounds check would have caught the issue, but I’m also curious if an automated test could have been constructed to catch this sort of thing. I personally work with code where you could factor out some calculations to their own function and test them in isolation. Perhaps that would be tough to do here because of performance; I am really not sure.
That said, this particular bug could have been avoided by a careful coding; VP8LBuildHuffmanTable could have received the maximum size of `root_table`, just like snprintf. It still would have needed much time to find but at least it could never be a security bug.
[1] https://math.stackexchange.com/questions/265397/inversion-of...
> Each entry contains (nbits, value) where `nbits` is # bits to be consumed and `value` is normally a symbol, but if `nbits` exceeds N `value` is interpreted as a table index and `nbits` is reinterpreted as the longest code length in that subtree. So each subsequent table should have `2^(nbits - N)` entries (the root table is always fixed to 2^N entries).
Given that, wouldn't it be only natural to construct a test where nbits exceeds N, so that you exercise the code where `value` was being interpreted as an index, and `nbits` as the longest code length in that subtree?
Hmm, I guess that this could have been done and perhaps was done (I took a quick glance at the code and didn't really grok it in a couple mins), and the issue would be that even if you did do what I suggest, you would likely not exceed the maximum fixed size with your crafted test, and thus not catch the bug.
I have mentioned that there was the hard-coded maximum number of entries. This is derived from zlib's enough.c [1], which determines the maximum possible size of 2-level table for given number of symbols, N and the maximum allowed bit length (here 15). I've verified that those numbers indeed come from this program:
for ((color_cache_size = 0; color_cache_size < 12; ++color_cache_size)); do
# Note that color_cache_size = 0 entirely disables the color cache, so no symbols
./enough $((256 + 24 + (($color_cache_size > 0) << $color_cache_size))) 8 15
done
So at the worst case, there are 256 + 24 + 2^11 = 2328 symbols possible, and the maximum table size is 2704. (Caveat: I couldn't verify values for color_cache_size >= 8 with the current version of enough.c. Probably the value was calculated with an alternative implementation using bigints.) So this bug cannot be found if any randomly constructed Huffman tree was thrown!But enough.c states that it covers "all possible valid and complete prefix codes". In the other words it assumes that the Huffman tree has been already verified to be correct. If it's not the case, it is very easy to make much worse cases. For example `enough.c 280 8 15` returns 654, which is possible with the following tree:
Len Code range # Root entry Overhead #
--- ------------------------------------ --- ----------------- -------- ---
1 0 1 0xxxxxxx 0 128
9 10000000:0 .. 11110110:1 238 10000000-11110110 2^1 119
11110111:0 1 11110111 2^2 1
10 11110111:10 .. 11110111:11 2
11111000:00 .. 11111110:11 28 11111000-11111110 2^2 7
11111111:00 .. 11111111:10 3 11111111 2^7 1
11 11111111:110 1
12 11111111:1110 1
13 11111111:11110 1
15 11111111:1111100 .. 11111111:1111111 4
But the following partial tree should be able to reach 768 entries: Len Code range # Root entry Overhead #
--- ------------------------------------ --- ----------------- -------- ---
9 00000000:0 1 00000000 2^7 1
10 00000000:10 1
11 00000000:110 1
12 00000000:1110 1
13 00000000:11110 1
14 00000000:111110 1
15 00000000:1111110 .. 00000000:1111111 2
00000001:0000000 .. 00000010:1111111 256 00000001-00000010 2^7 2
00000011:0000000 .. 00000011:0001111 1 00000011 2^7 1
So the real issue here is that the lack of tree validation before the tree construction, I believe. I'm surprised that this check was not yet implemented (I actually checked libwebp to make sure that I wasn't missing one). Given this blind spot, an automated test based on the domain knowledge is likely useless to catch this bug.[1] https://github.com/madler/zlib/blob/master/examples/enough.c
https://github.com/webmproject/libwebp/commit/902bc919033134...
This could mean Google optimized their fuzzers for libwebp after finding that bug and now they're finding more.
[0] https://github.com/electron/electron/pull/39824
But the lack of sandboxing when it’s available, for something like Signal, is kind of weird. I wonder what the reasoning was.
But seriously, depending on the attack vector in mind, using those "browser over VNC" technologies may address a lot of that risk if the objective is to read content without risking the local workstation running arbitrary code
This bug is the initial vector of last week's NSO Group zero-click exploit for iPhones: https://citizenlab.ca/2023/09/blastpass-nso-group-iphone-zer...
Applications parse crazy complex stuff to do everything they do, so obviously have a really big attack surface. Often the complexity is unavoidable - if you are a web browser, you cannot avoid parsing html for example.
However the sandbox is designed to have an attack surface as small as possible (and be configurable via permissions to have the bare minimum needed). The sandbox interfaces with the rest of the system are fully controllable by Apple, so there is no need to be passing complex and dangerous legacy datastructures across the boundary either.
Therefore, it should be the sandbox that is 'hardest' to break out of.
> so there is no need to be passing complex and dangerous legacy datastructures across the boundary either.
lol, by same logic there is no need to be passing complex and dangerous legacy stuff to browser to parse, just rewrite the world to be simpler.
Oh wait, that whole LLM thing...
1. Send payload to a process (image in a browser say)
2. Use payload to get code execution
3. If your current process has all the access you need then go forth and conquer; else
4. Send a payload to another process, go to step 2
Sandboxes are mitigations and roadblocks that increase the complexity of an attack they don’t make them go away.
https://chromium.googlesource.com/webm/libwebp.git/+/4619a48...
I'm pretty sure that you can find a buffer overflow in these decoders.
libwebp is relatively simple and clean C code, and has been around for over a decade. There are definitely scarier codec implementations than this.
> Last week, while checking the device of an individual employed by a Washington DC-based civil society organization with international offices, Citizen Lab found an actively exploited zero-click vulnerability being used to deliver NSO Group’s Pegasus mercenary spyware.
And since the initial bug appears to be in Google's webp library other programs are also vulnerable.
Yep, of course it is: https://github.com/webmproject/libwebp/commit/902bc919033134...
I guess libwebp could be excused as it was started when there were no alternatives, but even for new projects today we're still committing the same mistake[1][2][3].
[1] -- https://code.videolan.org/videolan/dav1d
[2] -- https://github.com/AOMediaCodec/libavif
[3] -- https://github.com/AOMediaCodec/libiamf
Yep. Keep writing these in C; surely nothing will go wrong.
[1] In my definition, this translates to "as popular and user-friendly as sanitizers".
There are actually already tools built for this very purpose in Rust (see Kani [1] for instance).
Formal verification has a serious scaling problem, so forming programs in such a way that there are a few performance-critical areas that use unsafe routines seems like the best route. I feel like Rust leans into this paradigm with `unsafe` blocks.
Google just did enable Memory Tagging Extension (ARM's hardware accelerated sanitizers) on the Pixels last year. May be sanitizing ISAs offer hope?
See: https://source.android.com/docs/security/test/memory-safety/...
The answer is that it's literally impossible to write a "safe C compiler" since the language is inherently memory unsafe.
There are various static analysis tools that can try to simulate C programs and try to automatically discover memory management bugs, but due to fundamental limitations of computation they can never catch all possible faults.
It doesn't sound impossible to me but I know nothing about compiler development :)
Rolling out this sort of change across a large codebase is hard as shit. While it sounds like it is mostly transparent, as soon as you run into a sufficiently large codebase all sorts of things start blowing up that you need to fix by hand before such a feature can be rolled out.
You can also do this with pointer tagging and some other techniques, but without hardware support this is amazingly slow. You can see just how much slower an asan build is, for example.
There are some big issues with this:
1. It's slow. Symbolic execution involves the interpretation of your program.
2. It would be imperfect and you'd likely have false positives.
3. It would likely be incomplete - for example, how would you handle the situation of only having a header?
So it's a good idea but it's very hard to make practically useful.
Where?
Once you have a bare pointer, you've lost track of what the original definition might have been, so you (the compiler / runtime / programmer) have no way of knowing that you've exceeded the size.
https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Object-Size-Che...
Which is why I harp on the idea that the real problem is the gold bricks on WG14 who are intentionally blocking improvements to make C safer.
Also point out that if you can implement C on 16bit 0x86's segmented architecture you can certainly implement C with phat pointers too.
Or it's hard like everyone keeps saying.
I'm going with the second option
Although I think all the C compilers are safe ish lately. I haven't seen exploits that target defects in output. Usually the error is ID10T located in the prekeyboard device.
The only problem is that these options are not the default and most C developers do not use them, especially for release versions.
I always use them, including for releases. In the relatively rare cases when this has a performance impact, I disable the sanitize options only for the functions where this matters and only after an analysis that guarantees that events like overflows or out-of-bounds accesses cannot happen.
Despite the hype, by default Rust is not safer than C compiled with the right options, because the default for Rust releases is also to omit many run-time checks.
Only when Rust will change the default to keep all run-time checks also in release builds, it will be able to claim that by default it is safer than C.
For now, when safety is desired, both C and Rust must be compiled with non-default options.
Which checks are you thinking of? The only thing that comes to mind is that integer overflow wraps instead of panics, but given that bounds are checked, it is still going to be a panic or logic bug rather than a buffer overflow.
1. Notably, some sanitizers are not intended for production use. I think this has changed a bit for asan but at one point it made vulns easier to exploit. These aren't mitigations.
2. They're extremely expensive. You need tons of bookkeeping for pointers for them to work. If you're willing to take that hit I don't really understand why you're using C, just use a GC'd language, which is probably going to be faster at that point.
> Only when Rust will change the default to keep all run-time checks also in release builds, it will be able to claim that by default it is safer than C.
The only thing Rust turns off at release is that unsigned integer overflows panic in debug but wrap on release. That wrap can not lead to memory unsafety.
I don't think anyone has built anything practically usable that is meant for production, though it wouldn't be impossible to do so.
But sometimes DoS is considered an exploit, and in that case you don't want to make things easier to crash.
...because the type system and borrow checker satisfies them at compile-time?
The only checks that are omitted at runtime are:
- checks that are exhaustively proven to be unnecessary by LLVM - checks that can never be triggered in the absence of UB
You shouldn't be triggering UB checks at runtime. If you rely on these checks, you're relying on UB itself, when all UB should be provably impossible.
The proof is much, much more work than the microkernel itself. A proof for something as large as webP might take decades.
Assuming that it is even provable in the first place.
When they ask "Which one?" I am answering "I don't care, as long as it's a programming language that uses a VM".
Every time I hear the discussions about how fast and perfect C is, people seem to miss the point that new programming languages try to avoid complexity, because they were using C/C++ themselves in the past and they fell on their noses more than once.
It's not about what is faster. It is about how often you make mistakes, statistically. And chances are you make dozens of mistakes per day in C that you will never be aware of, whereas in other memory constrained languages they have hundreds of mechanisms implemented to catch those common mistakes.
How does Rust deal with buffer overflows? Bounds checking. What an innovative solution, congratulations to the Rust people for this groundbreaking innovation. And they keep acting like they've fucking discovered hot water.
But if you're having the "memory safe replacement for C/C++" conversation it shouldn't surprise you that people bring up Rust.
I'm not even saying that bounds checking should be used everywhere, just that it really does seem like unsafe shouldn't be the default for so many projects.
"Many years later we asked our customers whether they wished us to provide an option to switch off these checks in the interests of efficiency on production runs. Unanimously, they urged us not to--they already knew how frequently subscript errors occur on production runs where failure to detect them could be disastrous. I note with fear and horror that even in 1980, language designers and users have not learned this lesson. In any respectable branch of engineering, failure to observe such elementary precautions would have long been against the law."
Showering with cold water is obviously safer (no chance of accidentally scalding yourself). But most people prefer showering with hot water because it's the way they've always done it, they're more comfortable with it, and while they could get burned by it, they view the risk of significant damage to be relatively low (if you discover the water is too hot, fix it quickly and you'll probably be fine).
Man can make it, man can break it.
If anything, that’s still underselling it: there are entire categories of bug which are widespread even in well-tested, heavily-fuzzed C codebases like Chrome but would not be likely or often possible in Rust.
Additionally imo possible that some developers would intentionally make such mistakes to sell these to interested persons, there are millions to be made here.
[0] https://github.com/webmproject/libwebp/commit/21735e06f7c1cb...
[1] https://github.com/webmproject/libwebp/commit/c3f41cb47e5f32...
A more robust approach is to implement appropriate checks (like fuzzing, code analysis etc) that offer an opportunity to review and correct issues before they ship (and for people to learn from).
- Android apps?
- Cross-platform Flutter apps?
- Electron apps?
- Microsoft Edge and Brave (and all other Chromium based web browsers)?
- Signal and Telegram displaying WebP stickers?
- Which image editors are affected? Affinity tools, Gimp and Inkscape seem to use libwebp.
- LibreOffice displaying WebP images?
- server software such as WordPress (does it decode images to re-encode them?)?
Apple devices were also affected, but they already got a fix.
Anything else?
* allegro
* emacs (lmao)
* ffmpeg
* freeimage
* gd (required for gnuplot, fceux, graphviz, etc)
* godot
* openimageio
* qt5/6-imageformats
* sdl2_image
* thunderbird
* webkit2gtk
* etc
optionally:
* gdal
* imagemagick
* python-pillow
* python-piexif
* etc
Should note that a vuln doesn't mean an exploit, of course.
Android WebView got patched so there's that.
Media codecs is one of the first things they turned into a module, specifically for this reason; it is one of the biggest source of security patches. I actually remember hearing a stat that 90%+ of security patches are limited to a very small handful of components (media codec, crypt lib, network stack). So by turning those into modules that can be updated independently of the OS, all Android devices get to benefit from it, even years after they're abandoned by their OEMs.
So C/C++ again.
(Similarly, it is nice that Google finds so many bugs in Javascript engines, but on the other hand they were one of the the main proponents of the bad idea of turning every web page into an executable program in the first place.)
ADDED. OK I was unfair in my guessing as to Google's motivation: the main motivation seems to have been to speed up page loading across the web.
This is inevitable. Even if none of the aforementioned companies did it, some other company will.
:barf:
The web was not always that way.
The secrecy is a little annoying. The page links to two places where you can supposedly find details, but both are internal resources. It's hard to judge how pervasive the bug is, and to find out if other software using Chrome as a render engine are also affected.
Also pretty comical that Google's Project Zero policy is to release details (edit: 7 days after) a public exploit is known to exist, yet the details are kept under wraps when their own software is vulnerable. Good for Apple that they didn't decide to pay Google back in kind.
Project Zero treats Google like any other vendor (much to the annoyance of other internal teams).
That is not true please stop spreading misinformation.
Google's page (https://googleprojectzero.blogspot.com/p/vulnerability-discl...) has their reasoning explained in some more detail.
In the case of the Chrome update, the fix is rolling out during the coming "days/weeks" and you originally complained about the vulnerability not being public. Which raised my question.
The two weeks grace period is in place for your run-of-the-mill 90-day disclosure time period, but for actively exploited bugs that extension period is up to three days.
After digging in deeper, it appears they have the fix rolling out 6 days after the report came in, so they're within their own deadline I suppose. Their statement about publishing the details doesn't mention releasing the details in a month like their own projects would, though: (https://www.bleepingcomputer.com/news/google/google-fixes-an...):
> "Access to bug details and links may be kept restricted until a majority of users are updated with a fix," Google said. "We will also retain restrictions if the bug exists in a third party library that other projects similarly depend on, but haven't yet fixed."
Google's inconsistencies when it comes to disclosure timelines irk me. "Wait until all third parties have also updated their software" isn't a luxury Google provides to others when they're the ones finding bugs. I'm all for swift disclosure timelines and pressure on manufacturers, but every Google team seems to have their own rules and guidelines written to serve themselves rather than general security.