Add @walletconnect/staking-cli package and CLI SDK improvements#2
Conversation
New package: @walletconnect/staking-cli - CLI for WCT staking on Optimism (chain ID 10) - Commands: stake, unstake, claim, status, balance - Smart stake flow: reads on-chain position first, picks correct contract call (createLock/updateLock/increaseLockAmount) - Gas estimation with 20% buffer, tx receipt polling after approve - Foundation API integration for position/rewards/APY data - 20 unit tests covering contracts and formatting CLI SDK enhancements: - Global config: walletconnect config set/get project-id (persisted to ~/.walletconnect-cli/config.json) - Transaction decode: runs cast 4byte-decode on calldata when cast CLI is available, shows decoded function + args - Wallet name: logs which wallet is being prompted on every request - Process exit: both CLIs call process.exit(0) on success to avoid hanging from SignClient internal timers - Relay cleanup: destroy() closes WebSocket transport, disconnect() absorbs relay errors to always clean up local state Skills: - walletconnect skill for wallet connection/signing operations - walletconnect-staking skill for staking operations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| const data = params[0]?.data; | ||
| if (data && data !== "0x") { | ||
| try { | ||
| const decoded = execSync(`cast 4d ${data}`, { |
Check warning
Code scanning / CodeQL
Unsafe shell command constructed from library input Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 27 days ago
In general, to fix this kind of issue you should avoid constructing shell commands by concatenating untrusted strings and passing them to an API that invokes a shell (exec/execSync with a single string). Instead, either (1) pass arguments as an array to a non-shell-spawning API such as execFile/execFileSync, or (2) if you must invoke a shell, properly escape any untrusted values using a library like shell-quote before embedding them in the command string.
The best fix here, without changing functionality, is to keep calling the cast CLI but pass it as a program with separate arguments, so that the untrusted data value is not interpreted by the shell. We can do this by importing execFileSync from child_process alongside execSync (leaving execSync untouched if used elsewhere) and replacing the unsafe execSync("cast 4d " + data, ...) call with execFileSync("cast", ["4d", data], ...). execFileSync does not invoke a shell and treats data as a literal argument to cast, eliminating command injection while preserving behavior (same program, same args, same options).
Concretely:
- Update the import on line 2 in
packages/cli-sdk/src/client.tsto also importexecFileSync. - In
logRequestDetails, replace theexecSyncinvocation on lines 234–238 with anexecFileSynccall that passes"cast"as the command and["4d", data]as the arguments, using the same options (encoding,timeout,stdio).
No additional helper methods are needed; only this import and call-site replacement are required.
| @@ -1,5 +1,5 @@ | ||
| import { EventEmitter } from "events"; | ||
| import { execSync } from "child_process"; | ||
| import { execSync, execFileSync } from "child_process"; | ||
| import { homedir } from "os"; | ||
| import { join } from "path"; | ||
| import { KeyValueStorage } from "@walletconnect/keyvaluestorage"; | ||
| @@ -231,7 +231,7 @@ | ||
| const data = params[0]?.data; | ||
| if (data && data !== "0x") { | ||
| try { | ||
| const decoded = execSync(`cast 4d ${data}`, { | ||
| const decoded = execFileSync("cast", ["4d", data], { | ||
| encoding: "utf-8", | ||
| timeout: 5000, | ||
| stdio: ["pipe", "pipe", "pipe"], |
Resolves CodeQL alert #2 (actions/missing-workflow-permissions) by setting contents: read — the minimum permission needed for checkout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolves CodeQL alert #2 (actions/missing-workflow-permissions) by setting contents: read — the minimum permission needed for checkout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolves CodeQL alert #2 (actions/missing-workflow-permissions) by setting contents: read — the minimum permission needed for checkout. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
New package: @walletconnect/staking-cli
CLI SDK enhancements:
Skills: