Skip to content

fix(signal): report malformed release metadata cleanly#110824

Merged
steipete merged 3 commits into
openclaw:mainfrom
Alix-007:alix/t2-signal-release-schema
Jul 20, 2026
Merged

fix(signal): report malformed release metadata cleanly#110824
steipete merged 3 commits into
openclaw:mainfrom
Alix-007:alix/t2-signal-release-schema

Conversation

@Alix-007

@Alix-007 Alix-007 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where users installing Signal CLI could receive a generic setup failure when GitHub returned a successful but malformed latest-release payload.

Why This Change Was Made

Validates the GitHub release response at the Signal plugin boundary before using its tag or assets. Missing optional fields keep the existing fallback behavior, invalid field shapes return the existing stable parse error, and malformed asset rows are skipped while valid release assets remain usable. HTTP errors, request deadlines, archive selection, and install fallback policy are unchanged.

User Impact

P1 reliability impact: Signal setup now fails predictably on malformed 2xx release metadata instead of escaping the provider parse boundary with a TypeError. A malformed row can no longer discard a valid download asset from the same response.

Evidence

Immutable production-entry runtime proof

Secretless GitHub-hosted proof run: https://github.com/Alix-007/openclaw/actions/runs/29664913232

Runtime job: https://github.com/Alix-007/openclaw/actions/runs/29664913232/job/88133601660

The fork-only workflow has permissions: {}, uses no secrets, and is not part of this PR diff. It checked out and verified immutable refs:

  • current main control: 837db49ebb2446ab62be27741d1ffabcad93189a
  • PR head: 6413ec041534f436a2ad6a2671f58e1d63a28a27

At each ref, the runner loaded that ref's production extensions/signal/src/install-signal-cli.ts, replaced only its SSRF transport import with an observable response stub, and called the exported production installSignalCli entry on Ubuntu x64. The production installer function body and response parser were unchanged.

Current-main malformed 2xx control:

BEFORE_RESULT error_name=TypeError release_calls=1 url="https://api.github.com/repos/AsamK/signal-cli/releases/latest"

PR-head malformed 2xx result:

AFTER_MALFORMED result={"ok":false,"error":"Failed to parse signal-cli release info."} release_calls=1

PR-head mixed-assets control (null/wrong-name/wrong-URL rows followed by one valid Linux asset):

RUNTIME_LOG Downloading signal-cli 0.14.6 (signal-cli-0.14.6-Linux-native.tar.gz)…
AFTER_MIXED selected_url="https://downloads.example.test/signal-cli-Linux-native.tar.gz" release_calls=1 boundary=DOWNLOAD_BOUNDARY_SENTINEL

This shows the valid asset reached the production download boundary while the metadata response was released.

Live public endpoint control from the same job:

LIVE_GITHUB status=200 tag="v0.14.6" assets=8

GitHub documents the latest-release response and release asset schema: https://docs.github.com/en/rest/releases/releases#get-the-latest-release

Regression and CI controls

  • Focused regression cases cover valid JSON null, a top-level array, non-string tag_name, and non-array assets; each returns Failed to parse signal-cli release info. and releases the guarded response.
  • The mixed-assets regression supplies null, non-string name/URL rows, and one valid Linux asset; the valid URL is retained and used.
  • Existing controls retain valid release installation, missing assets, malformed/oversized JSON, HTTP 503 cancellation, explicit request timeout, download cleanup, and Homebrew fallback behavior.
  • Exact-head upstream CI is green, including openclaw/ci-gate, lint, production/test types, build artifacts, channel contracts, security checks, and CodeQL.
  • Independent adversarial Codex review found no actionable issue after the full response-boundary guard was added.
  • Targeted formatter proof and git diff --check passed on head 6413ec041534f436a2ad6a2671f58e1d63a28a27.
  • Repository tests were not executed locally under the external-contributor trust policy; secretless PR CI and the linked runtime job are the executable proof paths.

AI-assisted.

Exact-head proof refresh (2026-07-20)

Redacted console proof:

BEFORE_RESULT error_name=TypeError release_calls=1 url="https://api.github.com/repos/AsamK/signal-cli/releases/latest"
AFTER_MALFORMED result={"ok":false,"error":"Failed to parse signal-cli release info."} release_calls=1
AFTER_MIXED selected_url="https://downloads.example.test/signal-cli-Linux-native.tar.gz" release_calls=1 boundary=DOWNLOAD_BOUNDARY_SENTINEL
LIVE_GITHUB status=200 tag="v0.14.6" assets=8

The run covers the current PR head, malformed and mixed release metadata, and a live GitHub release response without exposing credentials.

@openclaw-barnacle openclaw-barnacle Bot added channel: signal Channel integration: signal size: S labels Jul 18, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jul 18, 2026
@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 20, 2026, 2:25 AM ET / 06:25 UTC.

Summary
The PR validates malformed Signal CLI GitHub release metadata and filters malformed asset rows before selecting an installer archive.

PR surface: Source +22, Tests +27. Total +49 across 2 files.

Reproducibility: yes. from source and the supplied immutable runtime control: current main can parse a successful but shape-invalid release payload into values used as ReleaseResponse, producing the reported TypeError path. The contributor also supplied exact-head production-entry output showing the corrected error result.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: extensions/signal/src/install-signal-cli.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Refresh the current three-way merge result against main and rerun the focused Signal installer checks before merge.

Risk before merge

  • [P1] GitHub reports this branch as behind current main. Before merge, review the current three-way merge result and rerun the focused Signal installer coverage on the resulting head; this is a review-refresh concern, not evidence that the branch deletes current-main behavior.

Maintainer options:

  1. Decide the mitigation before merge
    Land the bounded Signal-plugin boundary validation after confirming the current merge result preserves the guarded response-release and existing HTTP, timeout, download-cleanup, and Homebrew fallback behavior.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] No mechanical repair remains; a Signal-area reviewer should confirm the refreshed merge result and normal landing checks for the current head.

Security
Cleared: The patch adds input-shape validation at an existing GitHub API boundary and does not add dependencies, permissions, workflow changes, secrets access, or new executable supply-chain paths.

Review details

Best possible solution:

Land the bounded Signal-plugin boundary validation after confirming the current merge result preserves the guarded response-release and existing HTTP, timeout, download-cleanup, and Homebrew fallback behavior.

Do we have a high-confidence way to reproduce the issue?

Yes from source and the supplied immutable runtime control: current main can parse a successful but shape-invalid release payload into values used as ReleaseResponse, producing the reported TypeError path. The contributor also supplied exact-head production-entry output showing the corrected error result.

Is this the best way to solve the issue?

Yes. Validating the untrusted GitHub response at the Signal plugin boundary with the existing object-reader helper is narrower and more maintainable than adding a core-specific parser or changing installer fallback policy.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against fef846a3f0e2.

Label changes

Label justifications:

  • P2: The patch addresses a bounded Signal setup reliability failure without evidence of broader runtime, security, or delivery impact.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR includes an exact-head, secretless production-entry run with redacted live output for malformed metadata, mixed assets, and a public GitHub endpoint control; no private data is exposed.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR includes an exact-head, secretless production-entry run with redacted live output for malformed metadata, mixed assets, and a public GitHub endpoint control; no private data is exposed.
Evidence reviewed

PR surface:

Source +22, Tests +27. Total +49 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 25 3 +22
Tests 1 28 1 +27
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 53 4 +49

What I checked:

  • Current-main gap: Current main still reads the GitHub release response through readProviderJsonResponse<ReleaseResponse>, so a valid-JSON non-object or malformed asset row can escape the declared TypeScript shape at runtime rather than receiving the installer parse error. (extensions/signal/src/install-signal-cli.ts:328, fef846a3f0e2)
  • Proposed boundary validation: The PR switches this external response boundary to readProviderJsonObjectResponse, validates tag_name and assets, and discards asset rows whose name or download URL is not a string before archive selection. (extensions/signal/src/install-signal-cli.ts:328, e949737527b9)
  • Regression coverage: The tests cover top-level null and array payloads, invalid top-level field shapes, and mixed malformed/valid asset rows while preserving the existing valid-download path. (extensions/signal/src/install-signal-cli.test.ts:393, e949737527b9)
  • Existing SDK contract: The plugin SDK already exposes the object-only JSON response helper used by this patch, so the change keeps release-schema ownership in the Signal plugin rather than adding a parallel parser or core seam. (src/agents/provider-http-errors.ts:1634, fef846a3f0e2)
  • After-fix runtime proof: The PR body supplies an exact-head, secretless production-entry run showing current-main TypeError, the patched stable parse error for malformed metadata, preservation of a valid mixed-assets download URL, and a live public GitHub latest-release control. (e949737527b9)

Likely related people:

  • steipete: The affected surface is the bundled Signal plugin; no stronger file-level history attribution was available from the read-only review environment, so this is a low-confidence routing candidate rather than ownership attribution. (role: likely Signal plugin follow-up owner; confidence: low; files: extensions/signal/src/install-signal-cli.ts, extensions/signal/src/install-signal-cli.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (8 earlier review cycles)
  • reviewed 2026-07-18T16:55:41.809Z sha 6413ec0 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-18T23:21:58.551Z sha 6413ec0 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-20T03:08:19.955Z sha d4dc7f0 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-20T03:32:30.285Z sha afa2360 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-20T03:52:29.154Z sha 8657513 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-20T04:14:54.146Z sha e949737 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-20T04:57:30.827Z sha e949737 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-20T05:42:10.489Z sha e949737 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 18, 2026
@Alix-007
Alix-007 force-pushed the alix/t2-signal-release-schema branch from 6413ec0 to ecb0dd6 Compare July 20, 2026 02:57
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jul 20, 2026
@Alix-007
Alix-007 force-pushed the alix/t2-signal-release-schema branch from ecb0dd6 to d4dc7f0 Compare July 20, 2026 03:04
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 20, 2026
@Alix-007
Alix-007 force-pushed the alix/t2-signal-release-schema branch 2 times, most recently from afa2360 to 8657513 Compare July 20, 2026 03:49
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jul 20, 2026
@Alix-007
Alix-007 force-pushed the alix/t2-signal-release-schema branch from 8657513 to e949737 Compare July 20, 2026 04:10
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 20, 2026
@Alix-007

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jul 20, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 20, 2026
@steipete
steipete force-pushed the alix/t2-signal-release-schema branch from e949737 to 3c15220 Compare July 20, 2026 12:10
@steipete
steipete merged commit 756de70 into openclaw:main Jul 20, 2026
84 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 21, 2026
* fix(signal): validate release metadata before install

* refactor(signal): normalize release metadata once

Co-authored-by: Alix-007 <[email protected]>

* test(signal): prove normalized install version

Co-authored-by: Alix-007 <[email protected]>

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: signal Channel integration: signal P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants