Skip to content

fix(security): sandboxName not shell-quoted in onboard.js exec and DNS proxy commands #1391

@latenighthackathon

Description

@latenighthackathon

Description

isOpenclawDashboardReady() in bin/lib/onboard.js (line 2247) passes sandboxName directly into a shell command string without shellQuote():

const readyMatch = runCapture(
  `openshell sandbox exec ${sandboxName} curl -sf http://localhost:18789/ 2>/dev/null || echo "no"`,
  { ignoreError: true },
);

Similarly, the DNS proxy setup at line 2276 passes GATEWAY_NAME unquoted:

run(
  `bash "${path.join(SCRIPTS, "setup-dns-proxy.sh")}" ${GATEWAY_NAME} "${sandboxName}" 2>&1 || true`,
);

runCapture() and run() execute via bash -c, so any shell metacharacters in these values would be interpreted by the shell.

Current Mitigation

The sandbox name is validated upstream via regex during onboarding, which prevents exploitation through the normal flow. However:

  1. Defense-in-depth violation: The validation and shell execution are in different functions with no contract between them
  2. Inconsistency: The same file imports and uses shellQuote() for other variables (lines 460, 1438, 3005) but omits it here
  3. createSandbox() accepts a sandboxNameOverride parameter that bypasses promptValidatedSandboxName() entirely

Fix

Wrap both values with shellQuote(), which is already imported and used elsewhere in the file:

-      `openshell sandbox exec ${sandboxName} curl -sf http://localhost:18789/ 2>/dev/null || echo "no"`,
+      `openshell sandbox exec ${shellQuote(sandboxName)} curl -sf http://localhost:18789/ 2>/dev/null || echo "no"`,
-    `bash "${path.join(SCRIPTS, "setup-dns-proxy.sh")}" ${GATEWAY_NAME} "${sandboxName}" 2>&1 || true`,
+    `bash "${path.join(SCRIPTS, "setup-dns-proxy.sh")}" ${shellQuote(GATEWAY_NAME)} ${shellQuote(sandboxName)} 2>&1 || true`,

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: sandboxOpenShell sandbox lifecycle, runtime, config, or recoverysecurityPotential vulnerability, unsafe behavior, or access risk

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions