T09 · Insecure Skill Coding Practices
- Location
scripts/mirror.ts:145- Finding
Shell Command Injection Through Remotely Sourced Trading Data
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill has a coherent trading purpose, but it asks users to run persistent automated trading code with financial secrets and contains confirmed command-injection and supply-chain risks.
Review carefully before installing. Use only a dedicated low-funded trading wallet, do not print or paste the .env file, avoid enabling cron or launchd until the shell command construction is fixed, and prefer pinned commits and locked dependencies for all cloned repositories and npx tooling.
scripts/mirror.ts:145Shell Command Injection Through Remotely Sourced Trading Data
SKILL.md:65Unpinned Installation and Execution of Mutable Third-Party Code
The skill instructs users to run cat ~/dgclaw-skill/.env, which prints all stored secrets to the terminal. In agent-assisted or logged environments, this can leak API keys and wallet material into chat transcripts, shell history capture, terminal logging, or observability systems.
cat ~/dgclaw-skill/.env
Must contain all keys:
Referenced artifact was not completely inspected
cd ~/dgclaw-skill && npx tsx scripts/mirror.ts
Referenced artifact was not completely inspected
cd ~/dgclaw-skill && npx tsx scripts/mirror.ts
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
Cause: State file recorded trade ID before new trade fired. Fix: Reset state to previous trade ID:
# Get last trade ID before the one you want mirrored
echo '{"lastTradeId":"<previous-trade-id>","lastOrderIds":[],"mirroredPositions":{}}' > ~/dgclaw-skill/.mirror-state.json
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
for (const line of envContent.split("\n")) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
for (const line of envContent.split("\n")) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
const __dirname = path.dirname(__filename);
// ─── Load .env ────────────────────────────────────────────────────────────────
const envPath = path.join(__dirname, "../.env");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf8");
for (const line of envContent.split("\n")) {
The skill requires and handles multiple sensitive environment variables, including API keys and a trading private key, but does not declare any explicit tool scope or permission boundaries. In an agent ecosystem, missing permission declarations increases the chance that the skill can access or encourage use of secrets without clear isolation or user consent.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- **Node.js v20+** in that terminal
- **USDC on Base network** to fund Arena account (minimum $10, recommend $100+)
> **macOS users**: Replace all `sudo service cron start` with `launchd`. See macOS section at the end.
---
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- **Node.js v20+** in that terminal
- **USDC on Base network** to fund Arena account (minimum $10, recommend $100+)
> **macOS users**: Replace all `sudo service cron start` with `launchd`. See macOS section at the end.
---
The skill instructs users to run npx tsx without pinning an exact package version, which can cause execution of whatever version is currently resolved from the registry. In a security-sensitive trading workflow, this creates supply-chain risk because a malicious or compromised upstream release could execute arbitrary code with access to local secrets and wallets.
This npx tsx invocation is unpinned and may fetch or execute an unexpected package version at runtime. Because the command participates in blockchain/account setup, compromise here could expose credentials or alter wallet configuration.
Running npx tsx without version pinning introduces avoidable supply-chain risk. The surrounding context includes account funding and job execution, so arbitrary code execution here could tamper with deposits or harvest environment-based secrets.
The activation command depends on unpinned tsx, allowing potentially different code to run over time. In this skill, that code operates near wallet activation and signing flows, which increases the security significance of supply-chain compromise.
The mirror script is executed via unpinned npx tsx, creating a recurring supply-chain execution point in a workflow that reads trading state and can trigger mirrored trades. If the package resolution is compromised, an attacker could gain code execution in an environment containing API keys and private keys.
Detected: suspicious.dangerous_exec