fix(security): headingLevel prüfen, überschreibende Tools kennzeichnen, Meta-Tools auf lit/ beschränken

- Divi-Vollformat: headingLevel nur h1 bis h6 (ValueCleaner, StoredNodeGuard, ShortformWriter);
  sonst ließ sich für Konten ohne unfiltered_html ein Skript-Element erzeugen.
- content-update, divi-update und wp-settings-update sind destructive, damit MCP-Clients nachfragen.
- mcp-adapter/execute-ability und get-ability-info nehmen auf dem OAuth-Server nur lit/-Abilities an.
- release-publish.sh übergibt den Gitea-Token per Konfigurationsdatei statt als curl-Argument.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-11-05 16:36:16 +01:00
co-authored by Claude Sonnet 5.5
parent 194fd9e183
commit 165e61d7fe
14 changed files with 221 additions and 11 deletions
+9 -7
View File
@@ -33,27 +33,29 @@ step "ZIP prüfen"
[[ "$(bsdtar -xOf "$zip" wp-lit-mcp/wp-lit-mcp.php | sed -n 's/^ \* Version: //p')" == "$version" ]] \
|| fail "Das ZIP enthält nicht Version $version"
auth=(-H "Authorization: token $GITEA_TOKEN")
json=(-H 'Content-Type: application/json')
api_get() { curl -fsS "${auth[@]}" "$api/$1"; }
# The token reaches curl as a config file on a pipe, never as an argument: argv is readable for every user (ps).
# printf is a builtin, so the token is not in any command line here either.
gcurl() { curl --config <(printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN") "$@"; }
api_get() { gcurl -fsS "$api/$1"; }
step "Entwurf v$version suchen oder anlegen"
release="$(api_get 'releases?per_page=50' | jq -c --arg t "v$version" '[.[] | select(.tag_name == $t)][0] // empty')"
if [[ -z "$release" ]]; then
notes="$(awk -v header="= $version =" '$0 == header { on = 1; next } /^= / { on = 0 } on' readme.txt)"
target="$(curl -sS "${auth[@]}" "$api/tags/v$version" | jq -r '.commit.sha // empty')"
target="$(gcurl -sS "$api/tags/v$version" | jq -r '.commit.sha // empty')"
[[ -n "$target" ]] || target="$(git rev-parse HEAD)"
request="$(jq -n --arg tag "v$version" --arg sha "$target" --arg body "$notes" \
'{tag_name: $tag, target_commitish: $sha, name: $tag, body: $body, draft: true}')"
release="$(curl -fsS "${auth[@]}" "${json[@]}" -d "$request" "$api/releases")" || fail "Release ließ sich nicht anlegen"
release="$(gcurl -fsS "${json[@]}" -d "$request" "$api/releases")" || fail "Release ließ sich nicht anlegen"
fi
[[ "$(jq -r .draft <<<"$release")" == "true" ]] || fail "v$version ist schon veröffentlicht"
id="$(jq -r .id <<<"$release")"
step "ZIP anhängen"
old="$(jq -r --arg n "$name" '.assets[]? | select(.name == $n) | .id' <<<"$release")"
[[ -z "$old" ]] || curl -fsS -X DELETE "${auth[@]}" "$api/releases/$id/assets/$old" >/dev/null
curl -fsS "${auth[@]}" -F "attachment=@$zip" "$api/releases/$id/assets?name=$name" >/dev/null \
[[ -z "$old" ]] || gcurl -fsS -X DELETE "$api/releases/$id/assets/$old" >/dev/null
gcurl -fsS -F "attachment=@$zip" "$api/releases/$id/assets?name=$name" >/dev/null \
|| fail "Upload von $name fehlgeschlagen"
# Read it back instead of trusting the upload: only a draft that really carries the ZIP goes public.
@@ -62,7 +64,7 @@ size="$(api_get "releases/$id" | jq -r --arg n "$name" '.assets[]? | select(.nam
[[ "$size" == "$(stat -c %s "$zip")" ]] || fail "$name hängt nicht oder mit falscher Größe am Entwurf (Gitea: '$size')"
step "Veröffentlichen"
curl -fsS -X PATCH "${auth[@]}" "${json[@]}" -d '{"draft": false}' "$api/releases/$id" >/dev/null \
gcurl -fsS -X PATCH "${json[@]}" -d '{"draft": false}' "$api/releases/$id" >/dev/null \
|| fail "Veröffentlichen fehlgeschlagen"
step "Ergebnis von außen prüfen"