computler

joined 4 months ago
 

What could possibly be the motivation for pushing out a release like this now? I can't put my finger on it.

Source: Bellingcat

Yeah I know what you are bruh

[2026-07-30] Henk van Ess

UPDATED, see Nano Banana removed
Tonight I typed just one sentence into Google Earth and put refugees near the Mexican border. Then I planted a nuclear plant in Iran. Then I put a fatal crash on a street in Amsterdam. Google’s own satellite imagery underneath all three. What on earth is Google doing?

Google spent twenty years building the reference the world checks against.Today it added a button that makes things up.

[

](https://substackcdn.com/image/fetch/$s_!aAS8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08c7239e-2975-489f-b359-340376157262_1486x386.jpeg)

Image generation went live in Google Earth on the web this afternoon, powered by Nano Banana 2, worldwide, for everyone, with no waitlist and no application.

You zoom to any coordinates on the planet, click create image, and type what you want to see. The model takes Google’s satellite, aerial and 3D imagery of that exact spot as its starting point and hands back a photorealistic picture. If it isn’t quite right, you refine it.

[

](https://substackcdn.com/image/fetch/$s_!sslg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7af5e2d2-491c-461d-903e-aa767aad4058_892x1244.jpeg)

I added a hospital and a bomb crater in Gaza in seconds with Google Earth. I can’t believe I just typed this.

Google describes the feature as creating “concepts grounded in the real world,” which is the problem stated as a selling point. Grounded means the invented thing is welded to genuine coordinates and drawn on genuine imagery, often in the same colours and the same light and at the same angle as the picture beside it. A forgery built that way doesn’t have to be convincing on its own. It inherits the credibility of the map it was born on.

The announcement runs to 487 words, written by Bryan Horowitz, Product Manager, Google Earth. Horowitz gives the planet a six-word instruction: type whatever you want to see. That is the whole gate. Elsewhere in the same post he suggests it’s fun to let your imagination run wild, and the piece signs off by inviting you to pick a spot on the map and start bringing your ideas to life.

Somebody is going to bring an idea to life before morning. It will not be a community garden, trust me.

The people who want this are not hard to picture. A government official wants a strike to look bigger than it was. A faction wants a hospital to look flattened, or intact, depending which one is holding it this week. A troll wants forty thousand reposts before lunch. This morning all three needed a screenshot, a second browser tab and a little patience. Tonight they need a sentence.

Google responded to this article and said:

We take misinformation seriously - every image created with Nano Banana in Google Earth includes the SynthID digital watermark, so if someone is unsure about an image, they can ask the Gemini app or use Lens in Search to see if the image was Al-generated. In addition, we prevent image creation on harmful topics and are continually updating our protections.

One clause in there is checkable, so I checked it. Refugees at a border, a nuclear plant in Iran, a fatal crash on an Amsterdam street, a hospital with a bomb crater in Gaza. Nothing was refused, nothing was softened, and nothing suggested I try a different prompt.

The rest of the answer has a shape worth noticing. The watermark is Google’s, the app that reads it is Google’s, and the search that reads it is Google’s. Every road out of the problem runs back through the company that built it. I understand that Google has Google products to run Google checks, but planet Earth is bigger than Google.

So I put one of tonight’s clips on X and asked nobody to check it. Hive, one of the biggest names in AI detection outside Google, scanned the post automatically and published its verdict underneath: AI Generated Video 1%, Deepfake 0%, AI Generated Speech 0%, AI Generated Music 36%.

[

](https://substackcdn.com/image/fetch/$s_!fswD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd91dc6ba-4c07-46b0-8d13-1ef4f5ad6193_2960x1566.jpeg)

It's a strange world.... the fake image is not seen as fake, but there is some fake sound in a clip that has no sound at all.

The clip had come out of Google’s model minutes earlier, and its audio track is silence — I measured it at minus 91 decibels, first frame to last. The only thing Hive found suspicious was music that does not exist.

Hive has a fair defence, so let me make it for them. What I posted was a screen recording, and a recording of a screen is a real recording. But that defence is the problem rather than the excuse, because fakes do not travel as clean files with their credentials intact. They travel as screen recordings, re-encodes, screenshots of screenshots, filmed off somebody’s phone in a hurry. The one case where the detector has an excuse is the only case that ever happens. The watermark was there the whole time. Outside Google, it reads as authentic.

If you have never verified anything in your life, the stakes are simpler than they sound. When a photograph turns up claiming to show a bombed hospital or a refugee camp, somebody has to decide whether it is true before a newspaper prints it. What they have is a reference: a picture of that same place, taken from above or from the street, that everybody agrees is real. They put the claim next to the reference and look at the gap.

Google built that reference. Street View passed 10 million miles of road in 2019 and now holds more than 280 billion images across over 110 countries. Google Earth turned twenty this year. Between them they are a photographic record of the physical world, and every frame of it is dated. If you know when a picture was taken, you can prove when something appeared.

In July 2014 the Russian Ministry of Defence held a press conference and produced satellite images about the downing of MH17. Bellingcat compared them against the dated archive in Google Earth, found the landscape didn’t match the dates claimed, and showed the images were fabricated. They published the walkthrough under the headline Who to Trust, Google or the Russian MoD?

In 2015 that was a rhetorical question.

There is a village in North Brabant, ninety minutes from my desk, called Volkel, and it has an air base that stores American B61 nuclear bombs — a fact the Dutch government has never confirmed, which surfaced through a leaked diplomatic cable and was later described by a former Dutch prime minister as absolutely pointless. On Google’s maps, Volkel spent years as a rash of coloured pixels. So did the ammunition depot at Staphorst, a Patriot missile site in Limburg, and several royal palaces, because the Dutch approach to hiding a military installation was to paint a large abstract artwork on top of it. The photographer Mishka Henner collected them into a gallery and sold them as art, which tells you how well the hiding worked.

Notice what that entire twenty-year argument assumed. You only censor a map that works. Every blur, every polygon, every diplomatic request was an admission that Google Earth was accurate enough to be dangerous. Governments were never worried the map would lie. They were worried it would tell the truth.

Google’s own position never wavered: it does not blur satellite imagery by choice, and sites arrive pre-obscured because a government or a supplier demands it as a condition of flying over. So to take one real building out of Google Earth, you need a state. To put a nuclear plant into Iran, I needed a sentence.

[

](https://substackcdn.com/image/fetch/$s_!AuAH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b5de6ad-903b-4a84-9ff1-ba88b38036b6_2082x1012.jpeg)

That asymmetry is not meant to be funny. For twenty years the danger was a map that revealed something true, and there was a procedure for it — a law, a ministry, a condition on the overflight permit. Tonight the danger is a map that shows something which was never there, and for that there is no procedure at all.

In February 2025 a Google Earth satellite pass photographed a parking lot at the US Navy’s Fifth Fleet headquarters in Manama, Bahrain — ordinary cars, ordinary rows. A year later those cars were on X, in a photograph of the same base supposedly flattened by an Iranian drone strike. Same cars, same rows, same spaces, vehicle for vehicle.

Somebody generated a war zone and forgot to move the Toyotas.

The Tehran Times posted it as a before-and-after of a US radar site in Qatar. It was not Qatar, it was Bahrain, and the “before” was a genuine Google Earth capture from 10 February 2025. AFP and BBC Verify both ran the “after” through Google’s watermark detector and got a hit, though not before it passed 950,000 views. Building it had taken six steps — screenshot Earth, open Gemini, upload, prompt, download, crop — which is six chances to get bored, and the forger got bored at the parking lot. Tonight Manama can be changed in seconds.

So can you still trust Google Earth?

Nothing was taken away today. Every satellite pass Google has ever flown is still there, still dated, still the thing that caught the Russian Ministry of Defence. The generated picture is a separate object that somebody has to deliberately ask for. All of that is true, and Google Earth remains full of genuine imagery.

It just doesn’t help the person looking at a JPEG on X at two in the morning. That person is not inside Google Earth. They are holding something that came out of it, and the thing that came out no longer says which half of the product it came from. The archive is intact; the output is not distinguishable. Only one of the two travels.

And there is a further problem Google doesn’t count. An official can now look at a genuine photograph of a genuine atrocity and say: AI. He doesn’t need the tool for that. He needs everyone to know the tool exists..

Upload a suspicious satellite image to Gemini, add @verifyai. Google’s watermark is there, you have an answer in seconds. If it isn’t, you have learned one thing only: Google didn’t make it. Google has renamed this shortcut before, so if it fails, just ask in plain words whether the image was created with Google AI.

[

](https://substackcdn.com/image/fetch/$s_!SkF1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffad0765a-e8df-4ff6-9a7a-63472a1234a7_2028x908.jpeg)

Then settle the question somewhere that cannot generate anything. Sentinel-2 is free and refreshes every five or six days, and there is Landsat, Planet, Airbus, Vantor besides. You want a sensor with an orbit, a collection time and a resolution you can check — then a second one, because as Todd Myers at the National Geospatial-Intelligence Agency put it long before any of this existed, for every collect you need a duplicate collect from different sources.

The dullest check is the strongest. If an image claims a specific satellite at a specific hour, published orbital elements will tell you whether anything was up there at all. No model can fake that, because it has nothing to do with the pixels.

Which is what broke Bahrain in the end. Not a detector. A person, counting cars.

Disclosure

I build ImageWhisperer. Google technology is part of it, not the whole of it. No single score is ever the finding.

Sources

[–] computler 2 points 1 month ago

Not as good as SomaliSpot.com, but pretty close!

 

First reply advertising Claude to the Linux community lol

So many horrible websites in the computer

[–] computler 1 points 1 month ago

Oh good was hoping people were jumping the gun

 

Addon enjoyers, is this our last stand?

[–] computler 1 points 2 months ago

Why, because the most popularized "out of the box" solution failed you? Tuta provides the same services anyways, without trying to get another email and phone number out of you. It just uses recovery keys.

They both kind of limit you, though, as they don't play nicely (well not at all actually, weird phrasing, nevermind) with email clients which enable easy offline backup. You might regret not having that in a couple years! I really value easy workflows like forwarding an email within Arcane Chat to a bot that processes the message into my Orgmode inbox, things like that. They end up saving you lots of time within a few months of making them.

[–] computler 0 points 2 months ago

Yes, very good. Typos and surliness will definitely prove I was wrong about the joke being racist. Why don't you threaten to fly across the Pacific? You wouldn't be the first.

[–] computler 0 points 2 months ago

That's not what grok means you complete goof! I'm using the terminology Elon named "Grok" the groombot after. Would you give it a rest?

Buddy, if I was angry with you, I wouldn't be explaining the basics of conversation to you. Imagine having this kind of discussion off the internet. You would never be like this. You would suddenly remember the versatility of language, and the point I am making, because otherwise you'd feel ridiculous.

[–] computler 2 points 2 months ago
[–] computler 1 points 2 months ago

It all makes sense

[–] computler 1 points 2 months ago (2 children)

Americans, when you remind them they live in a world of shit they created: "You have to want me to like you or you're a bad person lol"

No, I don't. You are pond scum. Put me on the phone with your mother. I'll give that slag what for. You were raised up wrong.

[–] computler 1 points 2 months ago* (last edited 2 months ago) (2 children)

[sees someone doing truly burger-brained shit] what are we, a bunch of ASIANS?

as usual clods act like you misparsed a message to pretend they're unable to grok it, rather than unwilling

[–] computler -2 points 2 months ago* (last edited 2 months ago) (8 children)

Well, I'm happy to stop talking if you're the type more interested in catfighting than even interpreting the conversation correctly. GreenBottles did in fact start off saying Microsoft is using Temu encryption. If Microsoft was using Temu encryption then their customers would be safe & they would have a record of zero data breaches. I don't think farmers would buy anything important on Temu, I never said no Chinese person would use it. This is anecdotal from speaking to urbanites who were more interested in high-quality manufacturing for throwing some money around in the markets. Nevermind!

I'm glad you buy your Chinese stuff directly instead of through Bezos, but I hope you can see that the kids using Temu synonymously with "dogshit" are being somewhat racist. Since this isn't based off a comparison with durable good from Amazon or the supermarket. Amazon support just isn't worth the markup. It's informed by propaganda spreading through unconventional means such as gore websites plastered with Russian and Chinese industrial accidents or hit-and-runs from the 2000s. Things change, and when that change is accompanied by a meme where a Chinese company is used as an adjective meaning dogshit, I think, well, the advertising firms that these Fortune 500 companies employ would feel quite chickenshit if they got beaten to the punch by natural slang developments. They'd be saying gee, I wish we got them talking like this five years before.

[–] computler -1 points 2 months ago* (last edited 2 months ago) (10 children)

How specious. Yes, Temu is trash mixed with treasure, but it's the exact same garbage you pay a premium for at online or brick-and-mortar retailers, so I find it quite funny when USonians act above it. You don't have an option for better quality that isn't as Chinese as possible without getting ripped off, unless you need cameras or the latest graphics cards. Temu encryption is good. American corporate encryption leans very bad. Just watch some cybersecurity conferences. More than racism I'm irritated by people using terminology wrong.

 

TLDR: We used depthfirst’s system to analyze the NGINX source code, and it autonomously discovered 4 remote memory corruption issues, including a critical heap buffer overflow introduced in 2008. We further investigated the exploitability of the issues, and developed a working proof of concept demonstrating RCE with ASLR off. If you use rewrite and set directives in your NGINX configuration, you’re at risk.

In mid-April, I was chatting with a colleague about the most vulnerable spot in our infrastructure. Since most of our services live entirely inside a private network, our app platform is the only exposed surface. He joked that achieving remote code execution on our web service would mean hacking into depthfirst completely. Hacking the web service itself is not my usual focus. However, the idea of hacking the underlying web server intrigued me, which directed my attention to NGINX.

NGINX is the most popular web server today, powering nearly a third of all websites globally. Its high performance architecture makes it the undisputed leader for handling massive volumes of web traffic. From serving static content to acting as an essential reverse proxy, it sits at the critical edge of the modern internet. A single vulnerability in this core infrastructure can therefore expose countless backend systems to severe risks.

Internally, we have an autonomous system that specializes in analyzing low level software. Analyzing NGINX simply required a single click to onboard the repository and trigger the analysis. After six hours of scanning, the system identified 5 security issues including a high severity finding, which is a heap overflow issue when handling NGINX rewrite directive.

The depthfirst system identified 4 remote memory corruption issues in NGINX

Figure 1: The depthfirst system identified 4 remote memory corruption issues in NGINX.

After briefly reviewing the findings, we reported the issues to NGINX via github security advisory. For each finding, we provided a detailed vulnerability description, root cause analysis, and a proof of concept generated directly by our system. 4 of the findings were confirmed by NGINX:

  • CVE-2026-42945 (Critical, CVSS 9.2): A heap buffer overflow issue in ngx_http_rewrite_module, an unpropagated is_args flag during a rewrite and set sequence causes an undersized buffer allocation. The copy phase then writes attacker-controlled escaped URI data past the heap boundary, leading to RCE.
  • CVE-2026-42946 (High, CVSS 8.3): An excessive memory allocation issue in ngx_http_scgi_module and ngx_http_uwsgi_module, a state mismatch after an incomplete upstream status line read causes a cross-buffer pointer subtraction. This produces a ~1 TB key length, crashing the worker process.
  • CVE-2026-40701 (Medium, CVSS 6.3): A use after free issue in ngx_http_ssl_module, if a TLS connection closes before asynchronous OCSP DNS resolution completes, the context pool is destroyed without cancelling the resolver request. The DNS timer later dereferences the freed pointer.
  • CVE-2026-42934 (Medium, CVSS 6.3): An out-of-bounds read issue in ngx_http_charset_module, an off-by-one error when handling incomplete UTF-8 sequences across proxy buffer boundaries corrupts the length state. This computes a negative source offset, reading 2 bytes before the allocated upstream buffer.

Among the 4 confirmed issues, CVE-2026-42945 is the most critical one. It is a heap buffer overflow issue that was introduced in 2008, impacting NGINX versions from 0.6.27 to 1.30.0. Given the high severity and the fact that it has been around for 18 years, we decided to investigate it in depth.

CVE-2026-42945

This vulnerability requires rewrite and set directives to trigger, but what are these directives?

Imagine you are migrating a legacy API to a new system. You need to seamlessly route incoming requests to the new endpoints. The rewrite directive allows you to modify the request path on the fly. However, your backend application might still need to know the original requested path. This is exactly where the set directive proves essential. It lets you capture and store the original path in a custom variable before the rewrite occurs. Together, these two directives are common building blocks in API gateway configurations.

The rewrite directive changes the request URI based on regular expressions. When a request matches the specified pattern, NGINX replaces the URI with a new string. For example, rewrite ^/api/(.*)$ /v2/api/$1 takes the matched part in the parentheses (a capture group) and appends it to the new path using the $1 variable. If the replacement string contains a question mark, NGINX treats the rest of the string as a query string and appends the original request arguments to it.

The set directive is used to assign a value to a custom variable. This is incredibly useful in practice for temporarily storing parts of the original request, dynamically routing endpoints, or maintaining state throughout the request lifecycle before subsequent rewrites alter the URI. Similar to the rewrite directive, it can also reference capture groups from the most recently executed regular expression. For instance, a configuration might use set $original_path $1 to save the value of the first capture group into a variable named original_path. This ensures that backend applications or access logs still have access to the original requested endpoint even after the URI has been completely rewritten.

Under the hood, NGINX optimizes these operations using its script engine. When parsing the configuration, the script engine compiles these directives into a sequence of operations. During runtime, it executes them in a two pass process. The first pass calculates the total length of the final string to allocate the exact amount of memory needed from its memory pool. The second pass then executes copy operations to write the actual data into the newly allocated buffer. This design avoids multiple small memory allocations, but it requires the length calculated in the first pass perfectly matches the amount of data written in the second pass. If the engine state changes between these two passes, a memory corruption vulnerability can occur.

The Root Cause

As mentioned, the script engine uses a two pass process. First, it calculates the required memory length. Then, it copies the actual data. A heap buffer overflow occurs here because the internal engine state changes between these two passes.

Specifically, the vulnerability resides in src/http/ngx_http_script.c. The flaw is triggered when a rewrite directive contains a question mark in its replacement string. This causes the ngx_http_script_start_args_code function to permanently set the e->is_args = 1 flag on the script engine:

void
ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
{
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
                   "http script args");

    e->is_args = 1;
    e->args = e->pos;
    e->ip += sizeof(uintptr_t);
}

This flag is never reset between script code evaluations. When a subsequent set directive references a regex capture group, it triggers the ngx_http_script_complex_value_code function. This is where the two pass design breaks down. During the length calculation pass, this function uses a fresh, completely zeroed out sub engine called le.

void
ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
{
    size_t                                 len;
    ngx_http_script_engine_t               le;
    ngx_http_script_len_code_pt            lcode;
    ngx_http_script_complex_value_code_t  *code;

    code = (ngx_http_script_complex_value_code_t *) e->ip;

    e->ip += sizeof(ngx_http_script_complex_value_code_t);

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
                   "http script complex value");

    ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); // fully zeroed sub engine

    le.ip = code->lengths->elts;

Because it is initialized with zeros, le.is_args is zero. The length calculation function, ngx_http_script_copy_capture_len_code, checks the following condition to decide if escaping is needed:

size_t
ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
{
    ...
    if ((e->is_args || e->quote)
        && (e->request->quoted_uri || e->request->plus_in_uri))
    {
        p = r->captures_data;

        return cap[n + 1] - cap[n]
                + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
                                    NGX_ESCAPE_ARGS);
    } else {
        return cap[n + 1] - cap[n];
    }
    ...

Because le.is_args is zero, this condition evaluates to false. It falls through to the else branch and simply returns the raw, unescaped capture length. However, during the second copy pass, the copy function ngx_http_script_copy_capture_code runs on the main engine where e->is_args is still set to 1. The exact same condition now evaluates to true, entering a different logic branch:

void
ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
{
    ...
    if ((e->is_args || e->quote)
        && (e->request->quoted_uri || e->request->plus_in_uri))
    {
        ...

        // OVERFLOW HAPPENS HERE
        // The destination buffer `pos` was allocated with `raw_size`,
        // but `ngx_escape_uri` expands the characters and writes
        // the much larger `raw_size + 2 * N` bytes directly into it!
        e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
                                           cap[n + 1] - cap[n],
                                           NGX_ESCAPE_ARGS);
    } else {
        e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
    }

It calls ngx_escape_uri with the NGX_ESCAPE_ARGS flag. This function expands every escapable character, like a plus sign or ampersand, from one byte to three bytes.

Consider the following trigger configuration:

location ~ ^/api/(.*)$ {
    rewrite ^/api/(.*)$ /internal?migrated=true;
    set $original_endpoint $1;
}

Because of the unexpected state change, the copy function writes raw_size + 2 * N bytes into a buffer allocated for only raw_size bytes, where N is the number of escapable characters. The escaped output written during the second pass becomes significantly larger. This mismatch causes the data to completely overflow the allocated pool boundary.

Exploitation

Luckily, NGINX uses a multi process architecture where worker processes fork from a single master process. Because of this design, the memory space is duplicated exactly for every child worker. This means the heap layout remains entirely deterministic across different workers. If our exploit fails and crashes a worker, the master process simply spawns a new one with the exact same memory layout. This allows us to safely try multiple times until we succeed without worrying about the worker crashing and changing the memory layout. Theoretically, we could leverage this design to leak ASLR by progressively overwriting pointers byte by byte. In this post, we discuss the exploitation technique assuming ASLR has already been bypassed.

The vulnerability gives us a highly controllable heap buffer overflow. By padding the request URI with plus signs, we can force the escaping function to expand each byte into three bytes, overflowing the allocated chunk. The size of the overflow is completely under our control based on the number of escapable characters we provide. However, we face a major restriction. The bytes we use to overwrite adjacent memory are passed through the URI parser and the escaping function. This means we cannot simply inject arbitrary bytes. Our payload is strictly limited to URI safe characters. So, without null bytes, how can we craft a pointer?

Overwriting ngx_pool

To turn this overflow into code execution, we need a reliable target. NGINX uses memory pools to manage allocations per connection and per request. The memory pool is defined by the ngx_pool_t structure, which contains essential metadata for managing the allocator state.

struct ngx_pool_s {
    ngx_pool_data_t       d;
    size_t                max;
    ngx_pool_t           *current;
    ngx_chain_t          *chain;
    ngx_pool_large_t     *large;
    ngx_pool_cleanup_t   *cleanup;
    ngx_log_t            *log;
};

Our ultimate goal is to overwrite the cleanup pointer at offset 64. This field points to a linked list of ngx_pool_cleanup_t structures, which hold function pointers (handler) and their arguments (data) to be executed when the pool is destroyed:

typedef void (*ngx_pool_cleanup_pt)(void *data);

struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler;
    void                 *data;
    ngx_pool_cleanup_t   *next;
};

However, because our heap overflow is contiguous, we face a major challenge. To reach the cleanup pointer, we must first overwrite all the preceding fields in the pool structure: d, max, current, chain, and large.

Filling these metadata fields with our URI safe padding bytes (like %2B) completely corrupts the internal state of the pool allocator. If the victim connection attempts to allocate more memory, read from the network, or process further data, NGINX will inevitably dereference one of these corrupted pointers and crash prematurely. This premature crash would completely prevent our exploit from succeeding.

To bypass this, we must ensure the pool is destroyed immediately after the corruption occurs, before any of the corrupted allocation fields are used. We achieve this perfect timing using a cross request heap feng shui technique. The attacker controls the heap layout and the exact lifecycle of the pools through connection ordering:

  1. Open an initial connection and send partial headers. NGINX allocates a request pool for this connection.
  2. Open a second victim connection, which allocates a victim pool exactly adjacent to the first pool.
  3. Complete the initial headers, triggering the rewrite overflow directly out of the first pool and into the adjacent victim pool header.
  4. Immediately close the victim connection, which will call ngx_destroy_pool to destroy the victim pool.

This precision allows us to reliably corrupt the victim pool header, without crashing the worker process. This works because when destroying the pool, NGINX iterates the cleanup linked list but not touching any of the corrupted fields in the pool structure. After this, we obtain the primitive of dereferencing arbitrary ngx_pool_cleanup_s.

Spraying Fake ngx_pool_cleanup_s

As we can only write URI safe characters, we need a way to inject arbitrary binary pointers (which often contain null bytes) into the victim pool header. We achieve this by spraying the heap with POST request bodies. Unlike HTTP headers or request URIs which are strictly parsed, POST bodies are treated as raw data streams and can contain arbitrary binary payloads, including null bytes. We construct a spray payload containing a fake cleanup structure pointing to the libc system function, followed by a user-supplied command string.

for (c = pool->cleanup; c; c = c->next) {
    if (c->handler) {
        c->handler(c->data);
    }
}

Because the heap layout is highly predictable across workers, our fake structures sprayed via POST will land at fixed offsets. We could bruteforce this address where our fake structures land, and explicitly filters them to find an address that consists entirely of URI-safe bytes. This guarantees the address used to overwrite the cleanup pointer will survive the escaping function intact. Note that we can’t overflow with null bytes, we can just overwrite the lower address of the cleanup pointer, making it referencing the faked ngx_pool_cleanup_s object we sprayed. Finally, we close the victim socket from the client side, triggering ngx_destroy_pool in NGINX worker process, which iterates pool->cleanup linked list to execute all registered handlers, and executing our injected command with system function.

Proof of concept demonstrating unauthenticated RCE against NGINX via CVE-2026-42945.

The source code of the proof of concept is available on our GitHub repository.

Affected Versions

  • NGINX Open Source 0.6.27 through 1.30.0
  • NGINX Plus R32 through R36.
  • NGINX Instance Manager 2.16.0 through 2.21.1.
  • F5 WAF for NGINX 5.9.0 through 5.12.1.
  • NGINX App Protect WAF 4.9.0 through 4.16.0 and 5.1.0 through 5.8.0.
  • F5 DoS for NGINX 4.8.0.
  • NGINX App Protect DoS 4.3.0 through 4.7.0.
  • NGINX Gateway Fabric 1.3.0 through 1.6.2 and 2.0.0 through 2.5.1.
  • NGINX Ingress Controller 3.5.0 through 3.7.2, 4.0.0 through 4.0.1, and 5.0.0 through 5.4.1.

Timeline

  • 4/18/2026: We used depthfirst’s internal system to analyze the NGINX source code, and it reported 5 memory corruption issues.
  • 4/21/2026: We reported all 5 issues to NGINX via a GitHub security advisory.
  • 4/24/2026: NGINX confirmed 4 of the reported issues.
  • 4/28/2026: We informed NGINX that we had developed a working PoC demonstrating RCE.
  • 5/5/2026: We shared our RCE PoC with NGINX and attached a demo video.
  • 5/13/2026: F5 released the NGINX security advisory.
  • 5/13/2026: This blog post was published.
view more: next ›