T09 · Insecure Skill Coding Practices
Error
- Location
- src/1password.js:43
- Finding
- Shell Command Injection in 1Password CLI Integration<![CDATA[ ## Vulnerability Details **File Location**: `src/1password.js:43-64`, with attacker-controlled command construction at `src/1password.js:112-188` and `src/1password.js:231-249` **Vulnerability Type**: OS command injection and secret disclosure through process arguments **Risk Level**: Critical ### Vulnerable Code ```javascript execOp(command, input = null) { const accountFlag = this.account ? ` --account ${this.account}` : ''; if (process.env.AGENTGUARD_USE_TMUX === 'true') { return this.execViaTmux(`op ${command}${accountFlag}`, input); } try { const options = { encoding: 'utf8', env: { ...process.env, OP_ACCOUNT: this.account } }; if (input) { options.input = input; } return execSync(`op ${command}${accountFlag}`, options); } catch (e) { throw new Error(`1Password CLI error: ${e.message}`); } } ``` Representative callers construct the command from externally supplied values: ```javascript let cmd = `item create --vault "${vault}" --category ${category} --title "${itemTitle}" "${field}=${value}"`; if (username) { cmd += ` --username "${username}"`; } if (url) { cmd += ` --url "${url}"`; } const result = this.execOp(cmd); ``` ### Technical Analysis `execSync()` executes the supplied string through a shell. The command incorporates account names, vault names, item titles, field names, usernames, URLs, references, agent IDs, credential keys, and secret values without shell-safe argument separation. Double quotes are not sufficient protection because shell substitutions such as `$(command)` and backticks remain active inside double-quoted strings. Some arguments, including `category` and `account`, are not consistently quoted at all. Credential values are also placed directly in process command lines, where they may be exposed through process inspection, shell diagnostics, or error messages. ### Attack Path 1. An attacker supplies a crafted agent ID, key, item title, account, vau ...[truncated 961 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Replace string-based `execSync()` calls with `execFileSync()` or `spawnSync()` using a fixed executable and an argument array. - Never invoke a shell for 1Password operations. - Pass credential values through stdin or another supported secret-input mechanism rather than command-line arguments. - Apply strict allowlist validation to account names, vault names, categories, agent IDs, and credential keys. - Do not include full child-process error messages if they could contain secrets. - Add tests using shell metacharacters, command substitutions, quotes, and newline characters to verify that inputs remain literal arguments. ]]>
