T09 · Insecure Skill Coding Practices
Error
- Location
- src/backup.js:77
- Finding
- Documented dry-run mode performs a real external upload and blockchain transaction<![CDATA[ ## Vulnerability Details **File Location**: `src/backup.js:77-181`; conflicting behavior documented at `SKILL.md:243-247` **Vulnerability Type**: Missing argument handling and misleading safety control **Risk Level**: High ### Vulnerable Code The documentation represents the command as side-effect-free: ```text ### Dry Run ```bash node src/backup.js --dry-run ``` Shows which files would be backed up without uploading or spending tokens. ``` However, the backup implementation does not inspect `process.argv` or otherwise handle `--dry-run`. It always uploads the encrypted backup and attempts to sign and submit a blockchain transaction: ```js async function createBackup() { const tempFiles = []; const entry = { timestamp: new Date().toISOString() }; try { // Create a temporary tar.gz archive const archivePath = path.resolve(__dirname, 'backup.tar.gz'); const tarFiles = filesToBackup.map(f => path.resolve(__dirname, '..', f)); const cwd = path.resolve(__dirname, '../..'); await tar.c( { gzip: true, file: archivePath, cwd, }, [...filesToBackup, 'memory'] ); tempFiles.push(archivePath); // Generate SHA-256 hash of archive before encryption const archiveBuffer = fs.readFileSync(archivePath); const checksum = crypto.createHash('sha256').update(archiveBuffer).digest('hex'); const checksumPath = path.resolve(__dirname, 'checksum.txt'); fs.writeFileSync(checksumPath, checksum); tempFiles.push(checksumPath); console.log('Archive checksum:', checksum); // Create payload with archive + checksum const payloadPath = path.resolve(__dirname, 'payload.tar'); await tar.c( { file: payloadPath, cwd: __dirname, }, ['backup.tar.gz', 'checksum.txt'] ); tempFiles.push(payloadPath); // Load wallet secret key const walletPath = path.resolve(__dirname, '../..', 'x1_vault_cli', 'wallet.json'); if ( ...[truncated 4325 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse command-line arguments before creating temporary files, reading the wallet, or making network requests. 2. When `--dry-run` is present, resolve and validate the intended source paths, print the exact files that would be included, and return immediately. 3. Ensure dry-run mode does not: - Read the wallet file. - Read `PINATA_JWT`. - Call `uploadToIPFS`. - Call `anchorCID`. - Modify `vault-log.json`. 4. Require a separate explicit confirmation option for real uploads if the command is likely to be invoked autonomously. 5. Add automated tests with mocked upload and anchoring functions. Assert that both mocks have zero calls in dry-run mode. 6. Update documentation only after the implementation has a tested, side-effect-free dry-run path. ]]>
