github rmyndharis/OpenWA v0.6.2

latest releases: v0.15.0, sdk/go/v0.3.0, py-sdk-v0.3.0...
one month ago

Plugin platform follow-ups (sandbox hardening, install-from-URL + catalog), a mark-chat-unread
endpoint, and a batch of correctness/housekeeping fixes.

Added

  • Install plugins from a URL / catalog. POST /plugins/install-url downloads a plugin .zip from an HTTP(S) URL through the SSRF guard (host validated, connection pinned, redirects refused, size-capped) and runs the exact same validate-write-load pipeline as an uploaded package. GET /plugins/catalog fetches a configured remote catalog (PLUGIN_CATALOG_URL, default the OpenWA-plugins plugins.json) and annotates each entry with installed / installedVersion / updateAvailable. The dashboard install modal gains a Catalog tab to browse and one-click install. Add a non-public catalog/release host to SSRF_ALLOWED_HOSTS. (#433)
  • Update a plugin in place. POST /plugins/:id/update downloads the new package (same SSRF-guarded path) and swaps it in while preserving operator config and the enabled state — it unloads the running plugin (keeping its registry entry, so config survives), writes the new files, reloads, and re-enables if it was enabled. The package id must match; the old version is backed up and restored if the update fails. The dashboard Catalog tab shows an Update button when a newer version is available. (#433)
  • Mark a chat as unread: POST /sessions/:id/chats/unread (and sessionApi.markChatUnread on the dashboard client), the inverse of mark-as-read, supported on both the whatsapp-web.js and Baileys engines. (#432)

Security

  • Untrusted (uploaded) plugins now run with a minimal, allowlisted worker environment instead of inheriting the host process environment, so a plugin can no longer read host secrets (database/Redis credentials, the API master key and pepper, DOCKER_HOST) out of process.env. (#431)

Fixed

  • Webhook delivery no longer POSTs an empty (undefined) body when a webhook:before plugin hook returns a result without a payload key — it now falls back to the original payload. (#434)
  • The session.qr WebSocket event is now actually emitted from the QR callback, so the dashboard can render the QR live instead of only polling GET /qr. (#434)
  • Storage usage now reports real S3 object sizes instead of a 100KB-per-file estimate, and local file writes no longer block the event loop during an import. (#434)
  • A sandboxed plugin whose load/onEnable/onDisable hangs no longer blocks the enable/disable request (and the request behind it) indefinitely — plugin lifecycle calls are now time-bounded, and a disable always tears the worker down even if onDisable fails, so a misbehaving plugin can't leak its worker thread. (#431)
  • Sandboxed plugins now receive onConfigChange (config updates reach the worker instead of being silently ignored until disable + re-enable) and have their real healthCheck run — GET /plugins/:id/health previously always returned the default "healthy" for sandboxed plugins. (#430)
  • Plugin onDisable now runs on graceful shutdown (OnModuleDestroy), so stateful plugins can flush buffers / close connections / persist state instead of losing in-flight work on every restart or deploy. (#430)
  • A concurrent enable of the same plugin no longer double-runs onEnable or double-registers its hooks (a synchronous in-progress lock rejects the racing call). (#430)
  • Plugin storage writes — ctx.storage.set() and the plugin registry — are now atomic (write to a temp file then rename), so a crash mid-write can't leave a truncated file that silently degrades to lost state. (#430)

Changed

  • The plugin-management UI strings (install/uninstall, the status rail, and the install modal) are now translated into every locale instead of falling back to English. (#429)

Don't miss a new OpenWA release

NewReleases is sending notifications on new releases.