Problem
upgrade() downloads a binary from GitHub and immediately POSTs it as a firmware image to the device:
async with self.session.get(download_url, raise_for_status=True) as download:
form = aiohttp.FormData()
form.add_field("file", await download.read(), filename=update_file)
await self.session.post(url, data=form)
There is no signature check, no SHA256 verification against the GitHub release asset digest, and no validation of the binary's structure. The integrity of the transferred firmware rests entirely on (a) TLS to github.com and (b) the path-construction logic — both of which are undermined by the URL-injection finding above and by the user-supplied repo argument (line 639). The POST to the device is plain HTTP (scheme="http"), so the firmware is also visible/modifiable on the LAN segment.
Why This Matters
Combined with the URL-injection issue or with a user being convinced to pass repo="attacker/wled-fork", an attacker can install arbitrary firmware on the ESP device. Without independent integrity checks, callers of this library have no way to detect that they uploaded the wrong binary.
Suggested Fix
Before POSTing, fetch the GitHub release metadata for the requested tag (https://api.github.com/repos/{repo}/releases/tags/v{version}), look up the asset by name, and verify the downloaded bytes against the asset's published digest/sha256 (now exposed by the GitHub releases API) or against a known-good SHA distributed out-of-band. Reject the upload if the digest does not match. At minimum, log/expose the computed SHA256 so callers can pin it.
Details
|
|
| Severity |
🟠 High |
| Category |
crypto |
| Location |
src/wled/wled.py:718-730 |
| Effort |
🛠️ Moderate effort |
🤖 Created by Kōan from audit session
Problem
upgrade()downloads a binary from GitHub and immediately POSTs it as a firmware image to the device:There is no signature check, no SHA256 verification against the GitHub release asset digest, and no validation of the binary's structure. The integrity of the transferred firmware rests entirely on (a) TLS to github.com and (b) the path-construction logic — both of which are undermined by the URL-injection finding above and by the user-supplied
repoargument (line 639). The POST to the device is plain HTTP (scheme="http"), so the firmware is also visible/modifiable on the LAN segment.Why This Matters
Combined with the URL-injection issue or with a user being convinced to pass
repo="attacker/wled-fork", an attacker can install arbitrary firmware on the ESP device. Without independent integrity checks, callers of this library have no way to detect that they uploaded the wrong binary.Suggested Fix
Before POSTing, fetch the GitHub release metadata for the requested tag (
https://api.github.com/repos/{repo}/releases/tags/v{version}), look up the asset by name, and verify the downloaded bytes against the asset's publisheddigest/sha256(now exposed by the GitHub releases API) or against a known-good SHA distributed out-of-band. Reject the upload if the digest does not match. At minimum, log/expose the computed SHA256 so callers can pin it.Details
src/wled/wled.py:718-730🤖 Created by Kōan from audit session