fix(sec): patch vulnerable deps + add publication-age floors and npm script allow-list - #75037
Conversation
૮ >ﻌ< ა ci reviewran on bc49e98 ℹ️ InfoCI-sensitive file review · View jobPR touches sensitive files, but the Sensitive files changed: Desktop E2E visual evidence · View test artifacts · View job2 visual diffs. inline evidence is publishing... |
15b9fdd to
f1978a3
Compare
e645731 to
f2532ae
Compare
cbor2 5.8.0 has a known vulnerability PYSEC-2026-2123 it's fixed in >= 5.9.0
httplib2 0.31.0 has a known vulnerability PYSEC-2026-3444 it's fixed in >= 0.32.0
58f4998 to
536e09f
Compare
teknium1
left a comment
There was a problem hiding this comment.
Reviewed the full diff (72 files, 23 commits) plus CI. This is exactly the direction we want: it extends the AGENTS.md Dependency Pinning Policy from version ceilings to publication age + install-script execution, which addresses the actual mechanics of the recent worm campaigns rather than just today's advisory list.
What I checked:
- Python pins — all 12 bumps land on the fixed releases;
mcpkept in sync across[mcp],[computer-use],[dev],tools/lazy_deps.py, and thetest_computer_use.pyfixture. Thepynacl1.6.2override-dependenciesescape hatch for discord.py's<1.6pin is the right call and clearly commented for removal after the next discord.py release. - Age floors —
.npmrcmin-release-age=14+[tool.uv] exclude-newer = "14 days", with every exclusion individually commented with its removal condition. That per-entry "remove when X is >2wks old" discipline is what keeps a 14-day floor from silently decaying to 0 — appreciated. - allowScripts — allow-list covers exactly the packages that legitimately need lifecycle scripts (esbuild, node-pty, electron, electron-winstaller, agent-browser, fsevents; core-js on the website side). This closes the install-script execution path outright.
- CI — full 48-check matrix green:
uv lock --check, both Docker builds, every JS workspace check, Python suite, Desktop E2E. Mergeable against current main despite the fast-moving base.
Minor notes (non-blocking):
- Commit
d670c89a00says "update mcp to 1.29.0" but the final state consistently pins 1.28.1 — cosmetic, the tree is self-consistent. - The nodejs 22→26 nix bump and the
eslint-plugin-reactremoval widen the blast radius beyond pure pin bumps, but both are load-bearing (eslint 10 carries the vuln fix; the plugin was blocking it) and the resulting lint churn is mechanical autofix, verified by the green desktop/web check jobs. - The "NOT fixed here" section at the bottom is genuinely useful triage — #60841's
uv syncrevert problem and #59998's post-update CVE signal are real follow-ups worth their own PRs.
This supersedes a cluster of open dupes (#50902, #51471, #72878, #73703, #48816) — we'll close those with credit once this lands.
Approving. Thanks Ari — this is thorough, well-documented work.
mcp 1.26.0 has 3 known vulnerabilities: PYSEC-2026-3481, PYSEC-2026-3482, PYSEC-2026-3483 they're fixed in >= 1.28.1
msgpack 1.1.2 has 1 known vulnerability: GHSA-6v7p-g79w-8964 it's fixed in >= 1.2.1
pillow 12.2.0 has 26 known vulnerabilities: GHSA-45hq-cxwh-f6vc GHSA-4x4j-2g7c-83w6 GHSA-5x94-69rx-g8h2 GHSA-62p4-gmf7-7g93 GHSA-6r8x-57c9-28j4 GHSA-8v84-f9pq-wr9x GHSA-9hw9-ch79-4vh6 GHSA-fj7v-r99m-22gq GHSA-jjj6-mw9f-p565 GHSA-pg7v-jwj7-p798 GHSA-phj9-mv4w-65pm GHSA-vjc4-5qp5-m44j GHSA-xj96-63gp-2gmr PYSEC-2026-2253 PYSEC-2026-2254 PYSEC-2026-2255 PYSEC-2026-2256 PYSEC-2026-2257 PYSEC-2026-3451 PYSEC-2026-3452 PYSEC-2026-3453 PYSEC-2026-3454 PYSEC-2026-3493 PYSEC-2026-3494 PYSEC-2026-3495 PYSEC-2026-3496 they're fixed in >= 12.3.0
pyasn1 0.6.3 has 5 known vulnerabilities: GHSA-8ppf-4f7h-5ppj GHSA-hm4w-wwcw-mr6r PYSEC-2026-3455 PYSEC-2026-3456 PYSEC-2026-3457 they're fixed in >= 0.6.4
…age-exclude. that would break stuff :)
The repo's .npmrc sets engine-strict=true and package.json pins
engines.npm, so an npm outside that range aborts every npm ci /
npm install we run inside the checkout:
npm error code EBADENGINE
npm error notsup Required: {"npm":"<11.10.0 || >=12.0.0"}
npm error notsup Actual: {"npm":"11.10.0"}
Our callers made that worse: _run_npm_install_deterministic sees
`npm ci` fail and falls through to `npm install`, which fails
identically, so the user got a buried EBADENGINE and no remedy.
React to the failure instead of predicting it. npm states the
required range in its own error, so there is no need for a version
probe on the happy path or a semver range matcher — the recovery
reads the constraint out of the output it just produced, upgrades,
and retries once.
Scope is deliberately narrow. Hermes only upgrades an npm inside its
own managed Node tree ($HERMES_HOME/node), installing with --prefix
so bin/npm keeps resolving to the upgraded lib/node_modules/npm; a
managed install writes prefix=~/.local into node/etc/npmrc, so
without the override the "upgrade" would land elsewhere while the
managed npm stayed stale. A system / nvm / brew / Nix npm belongs to
the user, so that case prints the exact command and lets the original
failure stand.
The upgrade runs from a temp cwd with npm_config_min_release_age=0,
otherwise the checkout's own min-release-age gate would refuse the
npm release we need.
_run_npm_install_deterministic's capture_output=False callers (the
desktop install) streamed npm output and returned stderr=None, which
would leave the recovery nothing to read — stderr is now teed, so
live output is unchanged and the text stays inspectable.
Verified end to end against real npm binaries on copies of a managed
tree: managed npm 11.10.0 -> EBADENGINE -> upgraded to 12.0.2 ->
retry exits 0; a foreign npm 11.10.0 hard-fails with the manual
command and is left untouched.
|
updated to fix the mcp commit message, and added an important feature to HA to ensure the version of NPM we use can work with the publication-age floor. |
scripts/contributor_audit.py resolves Co-authored-by trailers through contributors/emails/, so a co-author with a plain (non-noreply) email and no mapping file silently drops out of the generated release notes. This PR consolidates ~30 open dependency/supply-chain PRs and credits their authors as co-authors on the merge commit. Nine of those emails had no mapping. Added via scripts/add_contributor.py, one file per email: vikyw89@gmail.com -> vikyw89 (#50902) fmy3@qq.com -> superafun (#60201) Steven.Leath@gmail.com -> Leathal1 (#69711) bbasketballer75@gmail.com -> bbasketballer75 (#69864, #73857) mudreac@gmail.com -> mudrii (#66871, #63099) agents@joinsensie.com -> Sensie-agents (#65150) dinmail@gmail.com -> sahlbergalfred4-lgtm (#70003) richard.ham@live.com -> zebadee2kk (#50052) jrcrittenden@gmail.com -> jrcrittenden (#28749) egilewski@egilewski.com, sunsky.lau@gmail.com and 1920071390@campus.ouj.ac.jp were already mapped. Every other co-author uses a GitHub id+login noreply address, which auto-resolves and needs no file. tests/scripts/test_contributor_map.py passes.
teknium1
left a comment
There was a problem hiding this comment.
Re-reviewed the two new commits. Both look right — and nice catch on the npm 11.10–12.0 gap.
3975e9d7 — engine gate. npm 11.10–12.0 enforcing min-release-age while silently ignoring min-release-age-exclude[] is exactly the failure mode that would make this policy worse than no policy: the floor half-applies and every documented exception (react-router, eslint 10, vite 8.2…) hard-fails with no explanation. engine-strict=true + engines.npm: "<11.10.0 || >=12.0.0" refuses the broken range up front in both trees. Correct fix, correctly placed.
e803c5ae — EBADENGINE self-heal. This handles the fallout #1 creates for Hermes-managed installs sitting on npm 11.10.x, and the design choices are the ones I'd want:
- Reacting to the failure instead of predicting it — no
npm --versionprobe or semver matcher on the happy path; the recovery reads theRequired:range straight out of npm's own error output. - Scope discipline: upgrades only an npm inside
$HERMES_HOME/node(with--prefixso the managed tree upgrades in place rather than landing a second npm at theprefix=~/.localfromnode/etc/npmrc); system/nvm/brew/Nix npm gets the exact manual command and the original failure stands. Symlink resolution inmanaged_npm_prefixcovers all three spellings of the managed npm. - The stderr tee in
_run_npm_watching_for_engine_failure— thecapture_output=Falsedesktop path would otherwise hand the recoverystderr=Nonewith nothing to parse. Live output unchanged, text retained. - Both npm call sites wired (
_run_npm_install_deterministicand the TUI install path), one retry max,Falseon every non-managed/non-npm/Node-mismatch case.
One noted tension, acceptable: the self-upgrade runs with npm_config_min_release_age=0 from a temp cwd — necessary, since the age floor would refuse the very npm release the repair needs. It's scoped to the single npm@<range> install and nothing else.
17 new tests + the E2E verification against real npm binaries in both directions (managed 11.10.0 → upgraded → retry green; foreign 11.10.0 → manual command, untouched) is exactly the standard we want for this kind of recovery path.
Approving. Merge once the new head's CI is green.
The 0.15 bump rode along with the npm audit pass in NousResearch#75037, but it was not required by any advisory — `npm audit` reports 0 vulnerabilities with 0.14.24 pinned. It is a breaking major that costs us a working transcript, so take the API stability instead.
The #75037 revert restored pyproject.toml's pre-sweep dependency bounds and removed the global exclude-newer floor, so the lockfile had to be re-resolved. Regenerated with --no-config: the worktree sits under the main checkout, and uv's ancestor-config discovery was leaking the parent pyproject's exclude-newer stamp into the lock — which CI (no ancestor config) then rejected.
fix(sec): patch vulnerable deps + add publication-age floors and npm script allow-list Co-authored-by: Kingsley Wong <7207924+datanerdie@users.noreply.github.com> Co-authored-by: viky <vikyw89@gmail.com> Co-authored-by: FT_IOxCS <237263164+ft-ioxcs@users.noreply.github.com> Co-authored-by: 方明元 <fmy3@qq.com> Co-authored-by: Yorkstone Supplies <58149681+sycamoregroupltd@users.noreply.github.com> Co-authored-by: Steven Cuz Leath <Steven.Leath@gmail.com> Co-authored-by: Kyle French <248366920+Dadmin88@users.noreply.github.com> Co-authored-by: Eugeniusz Gilewski <egilewski@egilewski.com> Co-authored-by: Christopher Gara <79837758+christopherrobin88@users.noreply.github.com> Co-authored-by: LironTTG <147833337+LironTTG@users.noreply.github.com> Co-authored-by: Austin Porada <bbasketballer75@gmail.com> Co-authored-by: cresslank <9219265+cresslank@users.noreply.github.com> Co-authored-by: Ion Mudreac <mudreac@gmail.com> Co-authored-by: martinramos002 <262243228+martinramos002-bot@users.noreply.github.com> Co-authored-by: Sensie-Agents <agents@joinsensie.com> Co-authored-by: alexwill87 <173086651+alexwill87@users.noreply.github.com> Co-authored-by: BullishMomentum56 <218643122+BullishMomentum56@users.noreply.github.com> Co-authored-by: pintadoai <240097310+pintadoai@users.noreply.github.com> Co-authored-by: Alfred Sahlberg <dinmail@gmail.com> Co-authored-by: liuhao1024 <sunsky.lau@gmail.com> Co-authored-by: Richard Ham <richard.ham@live.com> Co-authored-by: jrcrittenden <jrcrittenden@gmail.com> Co-authored-by: 峯岸 亮 <1920071390@campus.ouj.ac.jp> Co-authored-by: Marcus Martini <6473852+napoleonmm83@users.noreply.github.com>
The 0.15 bump rode along with the npm audit pass in NousResearch#75037, but it was not required by any advisory — `npm audit` reports 0 vulnerabilities with 0.14.24 pinned. It is a breaking major that costs us a working transcript, so take the API stability instead.
fix(sec): patch vulnerable deps + add publication-age floors and npm script allow-list Co-authored-by: Kingsley Wong <7207924+datanerdie@users.noreply.github.com> Co-authored-by: viky <vikyw89@gmail.com> Co-authored-by: FT_IOxCS <237263164+ft-ioxcs@users.noreply.github.com> Co-authored-by: 方明元 <fmy3@qq.com> Co-authored-by: Yorkstone Supplies <58149681+sycamoregroupltd@users.noreply.github.com> Co-authored-by: Steven Cuz Leath <Steven.Leath@gmail.com> Co-authored-by: Kyle French <248366920+Dadmin88@users.noreply.github.com> Co-authored-by: Eugeniusz Gilewski <egilewski@egilewski.com> Co-authored-by: Christopher Gara <79837758+christopherrobin88@users.noreply.github.com> Co-authored-by: LironTTG <147833337+LironTTG@users.noreply.github.com> Co-authored-by: Austin Porada <bbasketballer75@gmail.com> Co-authored-by: cresslank <9219265+cresslank@users.noreply.github.com> Co-authored-by: Ion Mudreac <mudreac@gmail.com> Co-authored-by: martinramos002 <262243228+martinramos002-bot@users.noreply.github.com> Co-authored-by: Sensie-Agents <agents@joinsensie.com> Co-authored-by: alexwill87 <173086651+alexwill87@users.noreply.github.com> Co-authored-by: BullishMomentum56 <218643122+BullishMomentum56@users.noreply.github.com> Co-authored-by: pintadoai <240097310+pintadoai@users.noreply.github.com> Co-authored-by: Alfred Sahlberg <dinmail@gmail.com> Co-authored-by: liuhao1024 <sunsky.lau@gmail.com> Co-authored-by: Richard Ham <richard.ham@live.com> Co-authored-by: jrcrittenden <jrcrittenden@gmail.com> Co-authored-by: 峯岸 亮 <1920071390@campus.ouj.ac.jp> Co-authored-by: Marcus Martini <6473852+napoleonmm83@users.noreply.github.com>
The 0.15 bump rode along with the npm audit pass in NousResearch#75037, but it was not required by any advisory — `npm audit` reports 0 vulnerabilities with 0.14.24 pinned. It is a breaking major that costs us a working transcript, so take the API stability instead.
fix(sec): patch vulnerable deps + add publication-age floors and npm script allow-list Co-authored-by: Kingsley Wong <7207924+datanerdie@users.noreply.github.com> Co-authored-by: viky <vikyw89@gmail.com> Co-authored-by: FT_IOxCS <237263164+ft-ioxcs@users.noreply.github.com> Co-authored-by: 方明元 <fmy3@qq.com> Co-authored-by: Yorkstone Supplies <58149681+sycamoregroupltd@users.noreply.github.com> Co-authored-by: Steven Cuz Leath <Steven.Leath@gmail.com> Co-authored-by: Kyle French <248366920+Dadmin88@users.noreply.github.com> Co-authored-by: Eugeniusz Gilewski <egilewski@egilewski.com> Co-authored-by: Christopher Gara <79837758+christopherrobin88@users.noreply.github.com> Co-authored-by: LironTTG <147833337+LironTTG@users.noreply.github.com> Co-authored-by: Austin Porada <bbasketballer75@gmail.com> Co-authored-by: cresslank <9219265+cresslank@users.noreply.github.com> Co-authored-by: Ion Mudreac <mudreac@gmail.com> Co-authored-by: martinramos002 <262243228+martinramos002-bot@users.noreply.github.com> Co-authored-by: Sensie-Agents <agents@joinsensie.com> Co-authored-by: alexwill87 <173086651+alexwill87@users.noreply.github.com> Co-authored-by: BullishMomentum56 <218643122+BullishMomentum56@users.noreply.github.com> Co-authored-by: pintadoai <240097310+pintadoai@users.noreply.github.com> Co-authored-by: Alfred Sahlberg <dinmail@gmail.com> Co-authored-by: liuhao1024 <sunsky.lau@gmail.com> Co-authored-by: Richard Ham <richard.ham@live.com> Co-authored-by: jrcrittenden <jrcrittenden@gmail.com> Co-authored-by: 峯岸 亮 <1920071390@campus.ouj.ac.jp> Co-authored-by: Marcus Martini <6473852+napoleonmm83@users.noreply.github.com>
The 0.15 bump rode along with the npm audit pass in NousResearch#75037, but it was not required by any advisory — `npm audit` reports 0 vulnerabilities with 0.14.24 pinned. It is a breaking major that costs us a working transcript, so take the API stability instead.
What does this PR do?
Supply-chain / vulnerability sweep across both dependency trees, plus two structural guardrails so the same drift doesn't creep back in.
Two halves:
1. Patch the known-vulnerable pins. Python deps bumped to the fixed releases (
Pillow,mcp,pygments,pynacl,pyasn1,pydantic-settings,pytest,msgpack,httplib2,cbor2,tornado,setuptools), npm deps updated to clearnpm audit.2. Shrink the window a new compromise has to land in. A malicious package version is usually yanked within days of publication, so the highest-leverage defence is not installing anything that was published in the last two weeks:
.npmrcgetsmin-release-age=14pyproject.toml[tool.uv]getsexclude-newer = "14 days"Both carry explicit, commented escape hatches for the packages that genuinely need a fresher release (either because they ship a vuln fix that is itself younger than 14 days, or because they release constantly —
@assistant-ui/*,@radix-ui/*). Every exclusion says when to remove it.Also adds
allowScriptsto the rootpackage.json, so npm lifecycle scripts run only for the handful of packages that legitimately need them (esbuild,node-pty,electron,electron-winstaller,agent-browser) and are denied everywhere else — that's the exact execution path the recent worm campaigns used.This follows the existing pinning policy in
AGENTS.md("Dependency Pinning Policy") and extends it from version ceilings to publication age + script execution.Related Issue
N/A — proactive supply-chain hardening, no single issue.
Type of Change
Changes Made
Publication-age floors (new)
.npmrc— new file:min-release-age=14with per-package, individually commented exclusionspyproject.toml—[tool.uv] exclude-newer = "14 days", withexclude-newer-packageopting outvercel/nemo-relayuv.lock— regenerated under the new constraintInstall-time script execution
package.json—allowScriptsallow-list; everything not named is deniedPython dependency bumps (
pyproject.toml,uv.lock,tools/lazy_deps.py)Pillow12.2.0 → 12.3.0 (kept in sync intools/lazy_deps.py::tool.vision)mcp1.26.0 → 1.28.1 ([mcp],[computer-use],[dev], andtools/lazy_deps.py::tool.computer_use)setuptools→ 83.0.0, incl.[build-system] requires(torch >= 2.13 requires 83)pytest9.0.2 → 9.1.1,pygments→ 2.20.0,pyasn1→ 0.6.4,pydantic-settings→ 2.14.2,msgpack→ 1.2.1,httplib2→ 0.32.0,cbor2→ 6.1.3,tornado→ 6.5.7pynacl→ 1.6.2 via[tool.uv] override-dependencies—discord.py2.7.1 pinspynacl<1.6and 1.5.0 is vulnerable; upstream has the fix onmainbut no release yet, so we force the override with a comment to drop it after the next discord.py releasenpm dependency bumps
package.json(apps/desktop,apps/bootstrap-installer,apps/shared,ui-tui,ui-tui/packages/hermes-ink,web,tests-js, root) — no more caret rangesbrace-expansionforced to 5.0.8 via rootoverridespackage-lock.jsonregeneratedToolchain
nix/hermes-agent.nix+flake.lock— nodejs 22 → 26, nixpkgs bumpedeslint.config.shared.mjs— dropeslint-plugin-react(its rules are already covered byreact-hooks+ the TS config; it was blocking the eslint 10 upgrade that carries the vuln fix). Call-site churn acrossapps/desktop/src/**is the resulting lint autofix.tests/tools/test_computer_use.py— follows themcpversion bumpHow to Test
npm ci && npm audit— cleanuv lock --check— lock matchespyproject.tomlunder the newexclude-newernix develop -c scripts/run_tests.sh— Python suite greennix develop -c npm run check— typecheck + lint + JS tests greennpm installanduv lockunless it's on an exclusion list.Checklist
Code
Documentation & Housekeeping
AGENTS.md's Dependency Pinning Policy still describes the pinning rules correctly. Happy to add a short "publication-age floor" paragraph there if reviewers want it documented.cli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.md/AGENTS.md— see above.npmrc/[tool.uv]are platform-neutral;exclude-newer-packageexplicitly opts out the platform-gatednemo-relayandvercelso non-Linux resolution isn't brokenNotes for the reviewer
The exclusion lists in
.npmrcare deliberately verbose — one comment per entry stating the reason and the removal condition — because an undocumented exclusion is how a 14-day floor quietly becomes a 0-day floor. Please push back on any entry whose justification looks weak.closes:
closes #72683
closes #72108
closes #50901
closes #43997
closes #68736
closes #73426
closes #50902
closes #51471
closes #60201
closes #73222
closes #69711
closes #68973
closes #63942
closes #73474
closes #73219
closes #72587
closes #73476
closes #73475
closes #72878
closes #69864
closes #73662
closes #73857
closes #66871
closes #63099
closes #68648
closes #65150
closes #68961
closes #65345
closes #61248
closes #70003
closes #51305
closes #54424
closes #50052
closes #47998
Issues that remain open and are NOT fixed here
pip-audit --fixis transient because the nextuv syncreverts touv.lock. That's a workflow bug, untouched by this PR.hermes updatereports success while leaving vulnerable deps installed. Needs a post-update CVE signal; out of scope here.Contributor attribution
This PR consolidates work from 24 contributors across the superseded PRs listed above.
Please use the block below verbatim in the squash-merge commit message so
each of them keeps authorship in git history.
Notes on how this list was built:
egilewski(fix(deps): secure Pillow across Linux installers (#72108) #73474, fix(deps): repair Google transitive security floors (#72108) #73475, fix(deps): enforce patched server dependency floors (#72108) #73476),mudrii(deps: raise vulnerable dependency floors #66871, fix(deps): enforce advisory-fixed optional dependency floors #63099),sycamoregroupltd(fix(deps): pin httplib2==0.32.0 across all 3 install paths (GHSA-j5g9-f88f-gfj3) #73222, fix: bump MCP security pin #73219) andbbasketballer75(chore(deps): clear desktop npm advisories #69864, chore(deps): refresh safe transitive npm dependencies #73857) each contributed more than one PR.dependabot[bot](chore(deps): bump pyasn1 from 0.6.3 to 0.6.4 #68973 — bot, and its pyasn1 bump iscredited via fix(deps): bump pyasn1 0.6.3 -> 0.6.4 (CVE-2026-59886) #69711), the various
Claude/Cursor/Hermes Agenttoolingidentities that appear as commit co-authors, and
Teknium(maintainercommits on contributor branches, not a contribution to credit here).
(
builder@local,alfred@openclaw.local,omar-oa@agentmail.to), thecontributor's canonical GitHub noreply address is used instead so the
attribution actually resolves to their account.
@DeployFaith(id 259692215)but its commit is authored by
Kyle French <248366920+Dadmin88@…>, adifferent account. I credited the commit author. Say the word if you'd
rather credit the PR opener.
contributors/emails/mappings addedscripts/contributor_audit.pyresolvesCo-authored-bytrailers throughcontributors/emails/, so a plain-email co-author with no mapping drops outof the generated release notes. Nine mappings were missing and are added in
this PR:
vikyw89@gmail.comvikyw89fmy3@qq.comsuperafunSteven.Leath@gmail.comLeathal1bbasketballer75@gmail.combbasketballer75mudreac@gmail.commudriiagents@joinsensie.comSensie-agentsdinmail@gmail.comsahlbergalfred4-lgtmrichard.ham@live.comzebadee2kkjrcrittenden@gmail.comjrcrittendenegilewski@egilewski.com,sunsky.lau@gmail.comand1920071390@campus.ouj.ac.jpwere already mapped. Every other co-author usesa GitHub
id+loginnoreply address, which auto-resolves and needs no file.tests/scripts/test_contributor_map.pypasses (7/7).Newly added to the
closes:listthe issue; the PR is security(deps): clear June 2026 Dependabot CVE batch #47998)
Deliberately NOT closed: #28749
#28749 (@jrcrittenden)
gates release age at
hermes updatetime for installed users viasecurity.minimum_release_age_days. This PR only puts a floor on installsfrom the repo. The two are orthogonal — repo-side floor plus user-side gate —
and #28749 should stay open and land on its own. Its author is credited above
because the idea overlaps, not because this supersedes it.