Agent Wranglers

DSK-7Recommended

Refuse updates older than the installed version

The app installs only a version higher than the one it runs, and it reads that version from the signed update data. A downgrade happens only when a person chooses it.

How to do it

An attacker who can replay an old, validly signed update can bring back a hole you already fixed. Put the version inside the signed part of the update, not only in the file name. Compare versions as numbers, part by part, so 1.10.0 sorts above 1.9.0. To roll back a bad release, ship the old code under a new, higher version number, as plan to fix forward says.

Examples

JavaScript example

const parts = version => version.split('.').map(Number);

export function isNewer(candidate, installed) {
  const [a, b] = [parts(candidate), parts(installed)];
  for (let i = 0; i < Math.max(a.length, b.length); i += 1) {
    if ((a[i] ?? 0) !== (b[i] ?? 0)) return (a[i] ?? 0) > (b[i] ?? 0);
  }
  return false;
}

Python example

def is_newer(candidate: str, installed: str) -> bool:
    as_tuple = lambda version: tuple(int(part) for part in version.split("."))
    return as_tuple(candidate) > as_tuple(installed)

How to check

Serve a validly signed update with a lower version than the installed one. The app does not install it and logs the refusal. A unit test sorts 1.10.0 above 1.9.0.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/desktop-apps/update-integrity/no-downgrades">Agent Wranglers desktop apps, extensions and CLIs playbook</a>. In code you write, add a comment next to it with the same link.