Merge pull request #111320 from NousResearch/docs/plugin-catalog-no-self-update

Plugin catalog: no self-updaters instead of a 2-week pin age, enforced in CI
This commit is contained in:
Teknium
2026-09-14 17:34:43 -07:00
committed by GitHub
3 changed files with 25 additions and 10 deletions

View File

@@ -126,12 +126,23 @@ jobs:
fi
# Manifest schema + declared-vs-registered capability check.
if hermes plugins validate "$PLUGIN_DIR"; then
echo "✅ PASS: $entry"
else
if ! hermes plugins validate "$PLUGIN_DIR"; then
echo "::error file=$entry::hermes plugins validate failed"
FAILED=1
FAILED=1; echo "::endgroup::"; continue
fi
# SELF-UPDATER GATE (README rule 3): the pin is the only update path.
# A desktop bundle that both fetches from GitHub AND writes/renames
# plugin files is a self-updater; either half alone is fine (a
# plugin may read the API, or manage its own data files).
SELF_UPDATE=$(grep -rlE 'releases/latest|raw\.githubusercontent\.com' \
--include='*.js' --include='*.mjs' --include='*.cjs' --include='*.ts' "$PLUGIN_DIR" \
| xargs -r grep -lE 'writeTextFile|renamePath|writeFile\(' || true)
if [ -n "$SELF_UPDATE" ]; then
echo "::error file=$entry::self-updating code in catalog build (fetches GitHub AND writes plugin files): $SELF_UPDATE"
FAILED=1; echo "::endgroup::"; continue
fi
echo "✅ PASS: $entry"
echo "::endgroup::"
done <<< "$CHANGED_FILES"

View File

@@ -16,10 +16,13 @@ meaningful:
2. **Exact SHA pins are mandatory.** Every entry pins a full 40-character
commit SHA. Branches, tags, and short SHAs are rejected by the loader.
Installs clone the repository and check out exactly that commit.
3. **Pin maturity.** The pinned release should be **at least 2 weeks old**
at pin time, mirroring the supply-chain policy used for `optional-mcps/`
and pyproject dependencies. This gives the community time to notice a
compromised release before Hermes ships a pointer to it.
3. **No self-updating code.** A listed plugin must not fetch and replace
its own files (in-app "check for updates", signed release downloaders,
remote `plugin.js` loaders). The exact SHA pin *is* the trust model; a
self-updater lets an installed copy move to a commit nobody reviewed.
Updates reach users only through a SHA-bump PR here plus
`hermes plugins update <name>`. Keep the updater in the standalone
distribution if you want one; strip it from the catalog build.
4. **SHA bumps are new PRs.** Updating an entry's pin is a new PR whose diff
(old SHA → new SHA) is re-reviewed like any other change — reviewers are
expected to look at the upstream commit range being adopted.

View File

@@ -150,8 +150,9 @@ in short, an entry must be:
3. **Released** — the repo has real releases/tags, not just a default branch.
4. **Passing validation** — the catalog validation GitHub Action is green on
the PR (schema, SHA format, reachability).
5. **Pinned to settled code** — the pinned SHA is at least **2 weeks old**, so
the catalog never points at code pushed moments before review.
5. **Not self-updating** — the catalog build must not download and replace
its own files; the pinned SHA is the only update path (a SHA-bump PR plus
`hermes plugins update <name>`).
Pin updates (bumping `sha` to a newer commit) follow the same PR + review
process.