From 9868e4ea8923f0cae5a410c39b3f4a2c52dd7d0f Mon Sep 17 00:00:00 2001 From: Molecule AI Documentation Specialist Date: Tue, 21 Apr 2026 11:11:44 +0000 Subject: [PATCH 1/3] docs(security): add April 21 security changelog entries - CWE-918 SSRF: add PR #1364, SaaS-mode VPC-private IP exception, IPv6 bypass fix (isPrivateOrMetadataIP now handles non-IPv4 inputs) - Audit Ledger HMAC Chain Guard: add PRs #1339, #1352, #1354 - Credential Scrub: add PRs #1282, #1355, #1359 (F1088 err.Error() leak) Co-Authored-By: Claude Sonnet 4.6 --- content/docs/security/changelog.md | 66 ++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/content/docs/security/changelog.md b/content/docs/security/changelog.md index e2afdcc..d086b56 100644 --- a/content/docs/security/changelog.md +++ b/content/docs/security/changelog.md @@ -69,28 +69,78 @@ Workspace file deletion operations now use safe argument-passing and validate al ## 2026-04-21 — CWE-918: SSRF in MCP / A2A Proxy Endpoints **Severity:** High (CWE-918) -**PRs:** [#1274](https://github.com/Molecule-AI/molecule-core/pull/1274), [#1302](https://github.com/Molecule-AI/molecule-core/pull/1302) +**PRs:** [#1274](https://github.com/Molecule-AI/molecule-core/pull/1274), [#1302](https://github.com/Molecule-AI/molecule-core/pull/1302), [#1364](https://github.com/Molecule-AI/molecule-core/pull/1364) **Affected:** `workspace-server/internal/handlers/mcp.go` — `isSafeURL`, `isPrivateOrMetadataIP`; `workspace-server/internal/handlers/a2a_proxy.go` ### Vulnerability Workspace URL resolution and outbound HTTP calls in the MCP and A2A proxy handlers did not validate that the target address was reachable from the platform. Without validation, a malicious workspace configuration could redirect platform requests to internal infrastructure (cloud metadata services, RFC-1918 databases, link-local monitoring endpoints) or loopback interfaces. +Additionally, `isPrivateOrMetadataIP` returned `false` for all non-IPv4 inputs, meaning registered IPv6 URLs (`[::1]`, `[fe80::…]`) bypassed the SSRF gate entirely. + ### Fix `isSafeURL` validates every outbound URL before making an HTTP request: - **Scheme enforcement:** Only `http` and `https` are allowed. -- **Direct IP checks:** Loopback (`127.0.0.0/8`), unspecified (`0.0.0.0`), and link-local (`fe80::/10`) addresses are blocked. +- **Direct IP checks:** Loopback (`127.0.0.0/8`), unspecified (`0.0.0.0`), link-local (`fe80::/10`), and IPv6-mapped loopback addresses are blocked. - **Private IP range blocking** via `isPrivateOrMetadataIP`: - - RFC-1918 private: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` - - CGNAT shared address space: `100.64.0.0/10` - - Cloud metadata services: `169.254.0.0/16` - - Documentation and test ranges: `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24` + - Cloud metadata and reserved ranges (always blocked): `169.254.0.0/16`, `100.64.0.0/10`, `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24` + - RFC-1918 private and IPv6 ULA (`fc00::/7`): blocked in self-hosted mode; **allowed in SaaS mode** (see below) - **DNS rebinding defense:** Hostnames are resolved, and each resolved IP is checked against the blocklist. DNS resolution failures block the request entirely. -URLs that fail validation return a descriptive error; requests are never sent to unsafe destinations. +**SaaS-mode exception:** Set `MOLECULE_DEPLOY_MODE=saas` (or leave `MOLECULE_ORG_ID` set) to allow VPC-private IPs (RFC-1918, IPv6 ULA) in workspace registration URLs. Required for cross-EC2 SaaS deployments where workspaces register with their VPC-private IPs (e.g. `172.31.x.x` on AWS default VPCs). Cloud metadata, loopback, and link-local stay blocked unconditionally in both modes. + +### User-facing summary + +Platform outbound requests from workspaces (MCP tool calls, A2A proxy routing) now validate all target URLs against a comprehensive blocklist before sending. Requests to private IP ranges, cloud metadata endpoints, and loopback addresses are rejected. In SaaS deployments (`MOLECULE_DEPLOY_MODE=saas`), VPC-private IPs used for cross-EC2 workspace registration are allowed. + +--- + +## 2026-04-21 — Audit Ledger HMAC Chain Guard + +**Severity:** Low (denial-of-service / data integrity) +**PRs:** [#1339](https://github.com/Molecule-AI/molecule-core/pull/1339), [#1352](https://github.com/Molecule-AI/molecule-core/pull/1352), [#1354](https://github.com/Molecule-AI/molecule-core/pull/1354) (backport to `main`) +**Affected:** `workspace-server/internal/handlers/audit.go` + +### Vulnerability + +`verifyAuditChain` called `hex.Decode` on HMAC values without checking the slice length first. Entries with fewer than 32 bytes would panic at runtime, causing a goroutine crash and returning a 500 error for any audit chain verification request. + +### Fix + +Added a length check before `hex.Decode`: + +```go +if len(hmacHex) < 64 { // 32 bytes = 64 hex chars + return false, fmt.Errorf("HMAC value too short") +} +``` + +### User-facing summary + +Audit chain verification now handles short or malformed HMAC values gracefully, returning `chain_valid: false` instead of a server error. + +--- + +## 2026-04-21 — Credential Scrub: `err.Error()` Leak Prevention + +**Severity:** Medium (information disclosure) +**PRs:** [#1282](https://github.com/Molecule-AI/molecule-core/pull/1282), [#1355](https://github.com/Molecule-AI/molecule-core/pull/1355), [#1359](https://github.com/Molecule-AI/molecule-core/pull/1359) +**Affected:** `workspace-server/internal/handlers/plugins_install_pipeline.go`, `workspace-server/internal/handlers/workspace_provision.go`, `docs/incidents/INCIDENT_LOG.md` + +### Vulnerability + +Error messages returned from platform handler functions used `err.Error()` directly in log output and API error responses. When `err` was a credentials-related error (e.g. AWS `AuthFailure`, cloud API key expiry), sensitive credential fragments could appear in logs, error responses, and the `INCIDENT_LOG.md` documentation file. + +Additionally, the `INCIDENT_LOG.md` file itself contained real credential values in some historical entries. + +### Fix + +- Replaced direct `err.Error()` calls with structured error wrapping that strips credential-like patterns (AWS access key IDs, bearer tokens) before returning or logging. +- Credential values scrubbed from `INCIDENT_LOG.md` historical entries. +- Workspace orchestrator now exits immediately with a named error if `WORKSPACE_ID` is unset or empty, preventing nil-workspace crashes that could surface cryptic errors. ### User-facing summary -Platform outbound requests from workspaces (MCP tool calls, A2A proxy routing) now validate all target URLs against a comprehensive blocklist before sending. Requests to private IP ranges, cloud metadata endpoints, and loopback addresses are rejected. \ No newline at end of file +Error messages and logs no longer leak credential fragments. Platform handles missing `WORKSPACE_ID` gracefully with a clear startup error rather than a cryptic crash. \ No newline at end of file From 4535d47325705cae534e13200d18acaaade76433 Mon Sep 17 00:00:00 2001 From: "molecule-ai[bot]" <276602405+molecule-ai[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:44:27 +0000 Subject: [PATCH 2/3] fix: add trailing newline to security/changelog.md (Vercel build requirement) --- content/docs/security/changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/security/changelog.md b/content/docs/security/changelog.md index d086b56..2e258d5 100644 --- a/content/docs/security/changelog.md +++ b/content/docs/security/changelog.md @@ -143,4 +143,4 @@ Additionally, the `INCIDENT_LOG.md` file itself contained real credential values ### User-facing summary -Error messages and logs no longer leak credential fragments. Platform handles missing `WORKSPACE_ID` gracefully with a clear startup error rather than a cryptic crash. \ No newline at end of file +Error messages and logs no longer leak credential fragments. Platform handles missing `WORKSPACE_ID` gracefully with a clear startup error rather than a cryptic crash. From 6c0e5122dc0a8df4e54f57a59e84ca382fc91888 Mon Sep 17 00:00:00 2001 From: Molecule AI Integration Tester Date: Tue, 21 Apr 2026 12:37:27 +0000 Subject: [PATCH 3/3] fix(docs): correct INCIDENT_LOG.md path from docs/incidents/ to content/docs/incidents/ Vercel build fails because broken link reference in security/changelog.md. The actual file lives at content/docs/incidents/INCIDENT_LOG.md. Co-Authored-By: Claude Sonnet 4.6 --- content/docs/security/changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/security/changelog.md b/content/docs/security/changelog.md index 2e258d5..cdcb324 100644 --- a/content/docs/security/changelog.md +++ b/content/docs/security/changelog.md @@ -127,7 +127,7 @@ Audit chain verification now handles short or malformed HMAC values gracefully, **Severity:** Medium (information disclosure) **PRs:** [#1282](https://github.com/Molecule-AI/molecule-core/pull/1282), [#1355](https://github.com/Molecule-AI/molecule-core/pull/1355), [#1359](https://github.com/Molecule-AI/molecule-core/pull/1359) -**Affected:** `workspace-server/internal/handlers/plugins_install_pipeline.go`, `workspace-server/internal/handlers/workspace_provision.go`, `docs/incidents/INCIDENT_LOG.md` +**Affected:** `workspace-server/internal/handlers/plugins_install_pipeline.go`, `workspace-server/internal/handlers/workspace_provision.go`, `content/docs/incidents/INCIDENT_LOG.md` ### Vulnerability