@integrity-labs/agt-cli 0.28.914 → 0.28.916

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.
package/dist/bin/agt.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-3WTA477Y.js";
43
+ } from "../chunk-OJK2OMY7.js";
44
44
  import {
45
45
  getProjectDir,
46
46
  isSessionResumeDisabled,
@@ -5467,7 +5467,7 @@ import { execFileSync, execSync } from "child_process";
5467
5467
  import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
5468
5468
  import chalk18 from "chalk";
5469
5469
  import ora16 from "ora";
5470
- var cliVersion = true ? "0.28.914" : "dev";
5470
+ var cliVersion = true ? "0.28.916" : "dev";
5471
5471
  async function fetchLatestVersion() {
5472
5472
  const host2 = getHost();
5473
5473
  if (!host2) return null;
@@ -6682,7 +6682,7 @@ function handleError(err) {
6682
6682
  }
6683
6683
 
6684
6684
  // src/bin/agt.ts
6685
- var cliVersion2 = true ? "0.28.914" : "dev";
6685
+ var cliVersion2 = true ? "0.28.916" : "dev";
6686
6686
  var program = new Command();
6687
6687
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
6688
6688
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -3339,9 +3339,13 @@ function provisionIsolationHook(codeName, agentId) {
3339
3339
  if (hasAgentId)
3340
3340
  assertValidAgentId(agentId);
3341
3341
  const augmentedBaseRe = augmentedBase.replace(/[.[\]()*+?{}|^$]/g, "\\$&");
3342
+ const claudeProjectsBase = join4(homeDir, ".claude", "projects");
3343
+ const claudeProjectsBaseRe = claudeProjectsBase.replace(/[.[\]()*+?{}|^$]/g, "\\$&");
3344
+ const mangledBase = augmentedBase.replace(/[^a-zA-Z0-9]/g, "-");
3342
3345
  const ownAgentDir = getAgentDir(codeName);
3343
3346
  const logFile = join4(ownAgentDir, "isolation.log");
3344
3347
  const idAllowClause = hasAgentId ? ` && [ "$AGENT_DIR" != "${agentId}" ]` : "";
3348
+ const idAllowClause2 = hasAgentId ? ` || [ "$OWNER" = "${agentId}" ]` : "";
3345
3349
  const hookScriptPath = join4(claudeDir, "agt-isolation-hook.sh");
3346
3350
  const hookScript = [
3347
3351
  "#!/bin/bash",
@@ -3408,6 +3412,25 @@ function provisionIsolationHook(codeName, agentId) {
3408
3412
  `AUGMENTED_BASE="${augmentedBase}"`,
3409
3413
  `AUGMENTED_BASE_RE='${augmentedBaseRe}'`,
3410
3414
  `LOG_FILE="${logFile}"`,
3415
+ // ENG-10378: the hook guarded ~/.augmented and nothing else, while Claude
3416
+ // Code writes every transcript and tool result to ~/.claude/projects. Ada
3417
+ // measured it on 2026-09-12 by piping synthetic payloads and reading exit
3418
+ // codes: reads under ~/.augmented/<other> blocked (exit 2), reads under
3419
+ // ~/.claude/projects/<other> allowed (exit 0). So on a bare host this was
3420
+ // not a partial mitigation for transcripts - it was none at all.
3421
+ //
3422
+ // Claude Code names a project directory by replacing every non-alphanumeric
3423
+ // character of the project path with '-', so /root/.augmented/<name>/project
3424
+ // becomes -root--augmented-<name>-project. Verified against a live host.
3425
+ // Matching on the '-augmented-<name>-' TOKEN rather than an exact directory
3426
+ // name keeps this correct for scratch and any other subpath.
3427
+ //
3428
+ // SCOPE, deliberately narrow: a directory is only judged when it carries an
3429
+ // agent token at all. A project dir for anything else (a bare repo checkout,
3430
+ // '-root') is untouched, so this cannot lock an agent out of its own work.
3431
+ `CLAUDE_PROJECTS_BASE="${claudeProjectsBase}"`,
3432
+ `CLAUDE_PROJECTS_BASE_RE='${claudeProjectsBaseRe}'`,
3433
+ `MANGLED_BASE="${mangledBase}"`,
3411
3434
  "# The directory this agent's codename actually resolves to. Under the",
3412
3435
  "# id-keyed layout the codename is a symlink to the agent_id, and a legacy-",
3413
3436
  "# provisioned hook has no agent_id baked in to recognise it by. Unlike the",
@@ -3422,6 +3445,51 @@ function provisionIsolationHook(codeName, agentId) {
3422
3445
  " exit 2",
3423
3446
  "}",
3424
3447
  "",
3448
+ "# ENG-10378: is this Claude Code project directory another agent's?",
3449
+ "#",
3450
+ "# CodeRabbit (#5994): a raw token SUBSTRING test is a prefix-collision",
3451
+ "# bypass. Agent `ada` owns the token `-augmented-ada-`, which is a prefix of",
3452
+ "# `-root--augmented-ada-two-project` - so ada could read ada-two's",
3453
+ "# transcripts. Matching the shape of a name instead of its path segments is",
3454
+ "# the same defect this hook exists to prevent.",
3455
+ "#",
3456
+ '# The mangling is lossy (every non-alphanumeric becomes "-"), so the name',
3457
+ "# cannot be inverted: `-augmented-ada-two-project` is ambiguous between",
3458
+ '# agent "ada-two" and an agent "ada" with a subdir "two-project". Ground',
3459
+ "# truth resolves it - the REAL entries under AUGMENTED_BASE say which agents",
3460
+ "# exist, and the LONGEST matching prefix is the owner. That makes ada-two win",
3461
+ "# over ada for its own directory, which is the whole point.",
3462
+ "own_mangled() {",
3463
+ ` printf '%s' "$1" | tr -c '[:alnum:]' '-'`,
3464
+ "}",
3465
+ "project_owner() {",
3466
+ " local D=$1 BEST= BESTLEN=0 E EN PFX",
3467
+ ' for E in "$AUGMENTED_BASE"/*; do',
3468
+ ' [ -e "$E" ] || continue',
3469
+ ' E=$(basename -- "$E")',
3470
+ ' EN=$(own_mangled "$E")',
3471
+ ' PFX="${MANGLED_BASE}-${EN}-"',
3472
+ ' case "$D" in',
3473
+ ' "$PFX"*) if [ ${#PFX} -gt $BESTLEN ]; then BEST=$E; BESTLEN=${#PFX}; fi ;;',
3474
+ " esac",
3475
+ " done",
3476
+ ` printf '%s' "$BEST"`,
3477
+ "}",
3478
+ "other_agent_project() {",
3479
+ " local D=$1",
3480
+ " local OWNER",
3481
+ ' OWNER=$(project_owner "$D")',
3482
+ " # No real agent directory claims it: not an agent project, not judged.",
3483
+ " # LIMITATION, stated: a DEPROVISIONED agent whose transcripts remain has no",
3484
+ " # directory to claim them, so they are not judged. This is an accident-guard",
3485
+ " # for live agents, not a retention control (ENG-10378).",
3486
+ ' [ -z "$OWNER" ] && return 1',
3487
+ ` if [ "$OWNER" = "${codeName}" ]${idAllowClause2} || [ "$OWNER" = "$OWN_REAL" ]; then`,
3488
+ " return 1",
3489
+ " fi",
3490
+ " return 0",
3491
+ "}",
3492
+ "",
3425
3493
  "# An agent segment that will be expanded later: nothing here can know where",
3426
3494
  "# it points, so it is treated as another agent.",
3427
3495
  "has_expansion() {",
@@ -3469,11 +3537,25 @@ function provisionIsolationHook(codeName, agentId) {
3469
3537
  " fi",
3470
3538
  " fi",
3471
3539
  ' done <<< "$OCCURRENCES"',
3540
+ " # ENG-10378: the same pass over ~/.claude/projects. A bash command naming",
3541
+ " # another agent's transcript directory is the case that was wide open.",
3542
+ ' POCC_RE="${CLAUDE_PROJECTS_BASE_RE}/[^/[:space:];&|<>()]+/?"',
3543
+ ` POCCURRENCES=$(printf '%s\\n' "$NORM" | grep -oE "$POCC_RE" || true)`,
3544
+ " while IFS= read -r POCC; do",
3545
+ ' [ -z "$POCC" ] && continue',
3546
+ ' PREST=${POCC#"$CLAUDE_PROJECTS_BASE"/}',
3547
+ " PROJ_DIR=${PREST%/}",
3548
+ ' case "$PROJ_DIR" in .|..) continue ;; esac',
3549
+ ' if other_agent_project "$PROJ_DIR" || has_expansion "$PROJ_DIR"; then',
3550
+ ' deny "bash targeting $CLAUDE_PROJECTS_BASE/$PROJ_DIR"',
3551
+ " fi",
3552
+ ' done <<< "$POCCURRENCES"',
3472
3553
  " exit 0",
3473
3554
  "fi",
3474
3555
  "",
3475
3556
  `CWD=$(echo "$INPUT" | jq -r '.cwd // empty')`,
3476
3557
  `CANON_BASE=$(realpath -m -- "$AUGMENTED_BASE" 2>/dev/null || printf '%s' "$AUGMENTED_BASE")`,
3558
+ `CANON_PROJECTS=$(realpath -m -- "$CLAUDE_PROJECTS_BASE" 2>/dev/null || printf '%s' "$CLAUDE_PROJECTS_BASE")`,
3477
3559
  "",
3478
3560
  "# check_path PATH [RELATIVE_TO]: canonicalise one tool path, then judge it.",
3479
3561
  "check_path() {",
@@ -3495,6 +3577,12 @@ function provisionIsolationHook(codeName, agentId) {
3495
3577
  ' deny "$TOOL on $P"',
3496
3578
  " fi",
3497
3579
  " fi ;;",
3580
+ ` "$CANON_PROJECTS"/?*)`,
3581
+ ' local PREST=${P#"$CANON_PROJECTS"/}',
3582
+ " local PROJ_DIR=${PREST%%/*}",
3583
+ ' if other_agent_project "$PROJ_DIR" || has_expansion "$PROJ_DIR"; then',
3584
+ ' deny "$TOOL on $P"',
3585
+ " fi ;;",
3498
3586
  " esac",
3499
3587
  " return 0",
3500
3588
  "}",
@@ -6841,7 +6929,7 @@ function exchangeFailureKind(err) {
6841
6929
  }
6842
6930
 
6843
6931
  // src/lib/api-client.ts
6844
- var agtCliVersion = true ? "0.28.914" : "dev";
6932
+ var agtCliVersion = true ? "0.28.916" : "dev";
6845
6933
  var lastConfigHash = null;
6846
6934
  function setConfigHash(hash) {
6847
6935
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -11451,4 +11539,4 @@ export {
11451
11539
  managerInstallSystemUnitCommand,
11452
11540
  managerUninstallSystemUnitCommand
11453
11541
  };
11454
- //# sourceMappingURL=chunk-3WTA477Y.js.map
11542
+ //# sourceMappingURL=chunk-OJK2OMY7.js.map