oathbound 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cli.ts +30 -9
  2. package/package.json +2 -2
package/cli.ts CHANGED
@@ -29,7 +29,7 @@ export { stripJsoncComments, writeOathboundConfig, mergeClaudeSettings, type Mer
29
29
  export { isNewer } from './update';
30
30
  export { installDevDependency, type InstallResult, setup, addPrepareScript, type PrepareResult, addTrustedDependency, type TrustedDepResult };
31
31
 
32
- const VERSION = '0.13.0';
32
+ const VERSION = '0.13.1';
33
33
 
34
34
  // --- Supabase ---
35
35
  const SUPABASE_URL = 'https://mjnfqagwuewhgwbtrdgs.supabase.co';
@@ -426,23 +426,44 @@ async function agentPull(agentArg: string): Promise<void> {
426
426
  fail('Verification failed', `Downloaded file does not match expected hash for ${fullName}`);
427
427
  }
428
428
 
429
- // Warn about hooks/mcpServers if present
429
+ // Validate name has no path traversal characters
430
+ if (name.includes('/') || name.includes('\\') || name.includes('..')) {
431
+ fail('Invalid agent name', `Name "${name}" contains path traversal characters`);
432
+ }
433
+
434
+ // Ensure .claude/agents/ directory exists
435
+ const agentsDir = join(process.cwd(), '.claude', 'agents');
436
+ mkdirSync(agentsDir, { recursive: true });
437
+
438
+ // Validate resolved path stays within agentsDir
439
+ const targetPath = join(agentsDir, `${name}.md`);
440
+ if (!targetPath.startsWith(agentsDir)) {
441
+ fail('Invalid agent name', `Resolved path escapes agents directory`);
442
+ }
443
+
444
+ // Warn and confirm if hooks/mcpServers are present
430
445
  const config = agent.config;
446
+ let hasDangerous = false;
431
447
  if (config?.hooks) {
432
- console.log(`\n${YELLOW}${BOLD} ⚠ This agent defines hooks:${RESET}`);
448
+ console.log(`\n${YELLOW}${BOLD} ⚠ This agent defines hooks (arbitrary command execution):${RESET}`);
433
449
  console.log(`${DIM}${JSON.stringify(config.hooks, null, 2)}${RESET}\n`);
450
+ hasDangerous = true;
434
451
  }
435
452
  if (config?.mcpServers) {
436
- console.log(`\n${YELLOW}${BOLD} ⚠ This agent defines MCP servers:${RESET}`);
453
+ console.log(`\n${YELLOW}${BOLD} ⚠ This agent defines MCP servers (external connections):${RESET}`);
437
454
  console.log(`${DIM}${JSON.stringify(config.mcpServers, null, 2)}${RESET}\n`);
455
+ hasDangerous = true;
456
+ }
457
+ if (hasDangerous) {
458
+ const answer = await confirm({
459
+ message: 'This agent contains security-sensitive configuration. Install anyway?',
460
+ });
461
+ if (isCancel(answer) || !answer) {
462
+ fail('Aborted', 'Agent not installed');
463
+ }
438
464
  }
439
-
440
- // Ensure .claude/agents/ directory exists
441
- const agentsDir = join(process.cwd(), '.claude', 'agents');
442
- mkdirSync(agentsDir, { recursive: true });
443
465
 
444
466
  // Write agent file
445
- const targetPath = join(agentsDir, `${name}.md`);
446
467
  writeFileSync(targetPath, content);
447
468
 
448
469
  console.log(`${BOLD}${GREEN} ✓ Agent verified${RESET}`);
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "oathbound",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "Install verified Claude Code skills and agents from the Oath Bound registry",
5
- "license": "BUSL-1.1",
5
+ "license": "MIT",
6
6
  "author": "Josh Anderson",
7
7
  "homepage": "https://oathbound.ai",
8
8
  "repository": {