@blogic-cz/agent-tools 1.5.11 → 1.6.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.
package/README.md CHANGED
@@ -648,7 +648,9 @@ That's it. The hook reads tool input from stdin, runs the guard, and exits with
648
648
 
649
649
  The guard permits static `printenv` reads and simple `echo`/`printf` expansions only for exact names in `credentialGuard.allowedEnvironmentVariables`. The default list is empty. Multiple names are allowed only when each name is approved. Approved environment values may be displayed, but redirecting their pipeline or passing them to an executor stays blocked.
650
650
 
651
- Literal assignments such as `F=README.md; cat "$F"` work in supported static commands. Bounded proofs also support a literal `for` loop over a fixed list, the adjacent `cd PATH && T=LITERAL && git add -- "$T/file"` form, and `rg -n PATTERN src/{a,b}` with a single literal path-brace component. Loop binders are a single lowercase letter or `T`, and their uses must occupy supported data operands. Every body command and expanded path is checked; unsupported control flow, mutations such as `printf -v`, and unknown command roles cannot establish the proof. Other variable assignments and brace expansions retain conservative refusal. Fully quoted literal braces remain usable in static searches.
651
+ Python inline programs and quoted stdin heredocs can also display approved values through `os.getenv("NAME")`, `os.environ.get("NAME", "default")`, or `os.environ["NAME"]`. The complete program must be `import os` followed by `print(...)` statements using these reads and plain string labels or defaults. Dynamic names, aliases, escaped or interpolated strings, additional statements, and whole-environment output remain unsupported. The same redirection and pipeline restrictions apply.
652
+
653
+ Literal assignments such as `F=README.md; cat "$F"` work in supported static commands. Bounded proofs also support a literal `for` loop over a fixed list, a single ASCII-letter path binding such as `cd PATH && A=docs/report.md && shasum -a 256 "$A"` or `F=README.md; cat "$F"`, including the existing `git add -- "$T/file"` form, and literal path braces such as `rg -n -i PATTERN src/{a,b} docs/{guide,api}.md`. Path braces work with supported passive text commands and `cat`, and support one unquoted comma list per path, at most 16 members per list and 32 generated paths per command, within 64 KiB. Nested braces, ranges, empty members, mixed quoting, command positions, and compound commands remain unsupported. Path bindings accept literal values and `;`, newline, or `&&` sequencing; a binding conditional on successful `cd` is proved only for uses in that same `&&` list. Their uses must be supported read-only file operands or explicit `git add --` paths. Rebinding, executable operands, startup-variable names, and uncertain scopes cannot establish this proof. Loop binders are a single lowercase letter or `T`, and their uses must occupy supported data operands. Every body command and expanded path is checked; unsupported control flow, mutations such as `printf -v`, and unknown command roles cannot establish the proof. Other variable assignments and brace expansions retain conservative refusal. Fully quoted literal braces remain usable in static searches.
652
654
 
653
655
  Ordinary navigation operands such as `cd "$HOME"` and `git -C "$WORKTREE_ROOT" status --short` do not need display permission. This does not authorize printing those values, using them as code/options, or reading unknown file paths. In `printf`, approved values belong in data arguments after a fixed nonmutating format, for example `printf -- '%s' "$WORKSPACE_LABEL"`.
654
656
 
@@ -656,6 +658,8 @@ The guard recognizes `rtk`, `rtk proxy`, `command`, and supported `env` prefixes
656
658
 
657
659
  Paths are checked against sensitive filename patterns and configured path rules. Supported proofs apply those checks to their expanded operands. Ordinary parent-directory and absolute paths may be allowed; the guard does not resolve filesystem paths or symlinks, or enforce repository confinement.
658
660
 
661
+ Recognized Linux process-environment paths such as `/proc/self/environ`, `/proc/thread-self/environ`, and PID/task variants are blocked before configured path exceptions.
662
+
659
663
  Single literal `echo`/`printf` writes with output redirection and single `cat`/`tee` heredoc writes are allowed. Heredoc braces are data. Use a quoted delimiter for literal code; unquoted heredocs containing `$`, backticks, or backslashes do not receive the literal-write exception. The exception permits only supported combinations with navigation or selected inspections; unsupported following commands remain outside it. Supported complete Python stdin heredocs are checked as inline programs, with the normal runtime-argument, path, execution, and environment checks.
660
664
 
661
665
  Python JSON parsing, dictionary iteration, and printing are not themselves evidence of credential access. They follow the same access and execution rules as other supported inline programs. This intentionally permits ordinary JSON output that older versions refused. Unknown secrets in ordinary files can therefore reach arbitrary shell output; wrapper content checks do not protect that output. A refusal caused by unsupported syntax means the guard could not establish its policy conditions, not that it observed a secret being read.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/credential-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAmB,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAI5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAM/D,8CAA8C;AAC9C,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,+CAA+C;AAC/C,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAQF,+CAA+C;AAC/C,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxE,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3E,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACrD,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjF,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACxD,CAAC;AAg7DF,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAErE;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,eAAe,CAiTrF;AAQD,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,UA3wED,SAAS,UAAU,UAAU,KAAK,IA2wEM,CAAC;AAE5E,oDAAoD;AACpD,eAAO,MAAM,aAAa,YA7wEC,MAAM,KAAK;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IA6wEjB,CAAC;AAExD,yEAAyE;AACzE,eAAO,MAAM,aAAa,aA/wEE,MAAM,KAAK,OA+wEgB,CAAC;AAExD,yDAAyD;AACzD,eAAO,MAAM,aAAa,aAjxEE,MAAM,KAAK,OAixEgB,CAAC;AAExD,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,YAnxEC,MAAM,KAAK,OAmxE0B,CAAC;AAE1E,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,YArxEC,MAAM,KAAK;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAqxEf,CAAC;AAEhE,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,YAvxEC,MAAM,KAAK,OAuxEsB,CAAC;AAElE,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,YAzxEC,MAAM,KAAK,MAAM,GAAG,IAyxEa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/credential-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAmB,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAK5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAM/D,8CAA8C;AAC9C,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,+CAA+C;AAC/C,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAQF,+CAA+C;AAC/C,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxE,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3E,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACrD,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjF,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACxD,CAAC;AA6qEF,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAErE;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,eAAe,CA4TrF;AAQD,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,UAnhFD,SAAS,UAAU,UAAU,KAAK,IAmhFM,CAAC;AAE5E,oDAAoD;AACpD,eAAO,MAAM,aAAa,YArhFC,MAAM,KAAK;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAqhFjB,CAAC;AAExD,yEAAyE;AACzE,eAAO,MAAM,aAAa,aAvhFE,MAAM,KAAK,OAuhFgB,CAAC;AAExD,yDAAyD;AACzD,eAAO,MAAM,aAAa,aAzhFE,MAAM,KAAK,OAyhFgB,CAAC;AAExD,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,YA3hFC,MAAM,KAAK,OA2hF0B,CAAC;AAE1E,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,YA7hFC,MAAM,KAAK;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IA6hFf,CAAC;AAEhE,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,YA/hFC,MAAM,KAAK,OA+hFsB,CAAC;AAElE,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,YAjiFC,MAAM,KAAK,MAAM,GAAG,IAiiFa,CAAC"}
@@ -228,6 +228,11 @@ export declare const prReadyCommand: Command.Command<"ready", {
228
228
  readonly pr: Option.Option<number>;
229
229
  readonly repo: Option.Option<string>;
230
230
  }, {}, import("#gh/service").GhError, GitHubService>;
231
+ export declare const prDraftCommand: Command.Command<"draft", {
232
+ readonly format: "json" | "toon";
233
+ readonly pr: Option.Option<number>;
234
+ readonly repo: Option.Option<string>;
235
+ }, {}, import("#gh/service").GhError, GitHubService>;
231
236
  export declare const prChecksCommand: Command.Command<"checks", {
232
237
  readonly failFast: boolean;
233
238
  readonly format: "json" | "toon";
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/commands.ts"],"names":[],"mappings":"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"}
@@ -149,6 +149,29 @@ export declare const readyPR: (opts: {
149
149
  baseSha: string | null;
150
150
  wasAlreadyReady: boolean;
151
151
  }, import("#gh/service").GhError, GitHubService>;
152
+ export declare const draftPR: (opts: {
153
+ pr: number | null;
154
+ }) => Effect.Effect<{
155
+ number: number;
156
+ url: string;
157
+ title: string;
158
+ headRefName: string;
159
+ baseRefName: string;
160
+ state: string;
161
+ isDraft: boolean;
162
+ mergeable: "MERGEABLE" | "CONFLICTING" | "UNKNOWN";
163
+ body: string;
164
+ author: {
165
+ login: string;
166
+ is_bot: boolean;
167
+ };
168
+ reviewDecision: "APPROVED" | "CHANGES_REQUESTED" | "REVIEW_REQUIRED" | "";
169
+ reviewRequests: import("#gh/types").ReviewRequest[];
170
+ headRefOid?: string;
171
+ headSha: string | null;
172
+ baseSha: string | null;
173
+ wasAlreadyDraft: boolean;
174
+ }, import("#gh/service").GhError, GitHubService>;
152
175
  export declare const editPR: (opts: {
153
176
  pr: number;
154
177
  title: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/core.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { prChecksCommand, prChecksFailedCommand, prCloseCommand, prCommentCommand, prCommentsCommand, prCreateCommand, prDiscussionSummaryCommand, prEditCommand, prFeedbackCommand, prIssueCommentsCommand, prIssueCommentsLatestCommand, prLastHumanReviewerCommand, prListCommand, prMergeCommand, prReadyCommand, prStackCommand, prRequestReviewCommand, prReplyCommand, prRerunChecksCommand, prReplyAndResolveCommand, prResolveCommand, prReviewCommand, prReviewsCommand, prStatusCommand, prSubmitReviewCommand, prThreadsCommand, prTriggerChecksCommand, prWaitMergeableCommand, prReviewTriageCommand, prReviewTriageBatchCommand, prViewCommand, prWatchCommand, } from "./commands";
1
+ export { prChecksCommand, prChecksFailedCommand, prCloseCommand, prCommentCommand, prCommentsCommand, prCreateCommand, prDiscussionSummaryCommand, prDraftCommand, prEditCommand, prFeedbackCommand, prIssueCommentsCommand, prIssueCommentsLatestCommand, prLastHumanReviewerCommand, prListCommand, prMergeCommand, prReadyCommand, prStackCommand, prRequestReviewCommand, prReplyCommand, prRerunChecksCommand, prReplyAndResolveCommand, prResolveCommand, prReviewCommand, prReviewsCommand, prStatusCommand, prSubmitReviewCommand, prThreadsCommand, prTriggerChecksCommand, prWaitMergeableCommand, prReviewTriageCommand, prReviewTriageBatchCommand, prViewCommand, prWatchCommand, } from "./commands";
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,aAAa,EACb,cAAc,EACd,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,aAAa,EACb,cAAc,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,aAAa,EACb,cAAc,EACd,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,aAAa,EACb,cAAc,GACf,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blogic-cz/agent-tools",
3
- "version": "1.5.11",
3
+ "version": "1.6.1",
4
4
  "description": "CLI tools for AI coding agent workflows — GitHub, database, Kubernetes, Azure platform, Azure DevOps, logs, sessions, and audit",
5
5
  "keywords": [
6
6
  "agent",
@@ -17,6 +17,7 @@
17
17
  import type { CliToolOverride, CredentialGuardConfig } from "#config/types";
18
18
  import { redactSensitiveText } from "#shared/content-security";
19
19
  import { SECRET_PATTERNS } from "#shared/credential-patterns";
20
+ import { posix } from "node:path";
20
21
 
21
22
  export { findSecretMatches } from "#shared/credential-patterns";
22
23
  export { redactSensitiveText } from "#shared/content-security";
@@ -89,6 +90,9 @@ const DEFAULT_ALLOWED_PATH_PATTERNS: RegExp[] = [
89
90
  /\.env\.sample$/,
90
91
  ];
91
92
 
93
+ const PROCESS_ENVIRONMENT_PATH =
94
+ /^(?:\/|(?:\.\.\/)*)proc\/(?:self|thread-self|[0-9]+|\$\$|\$\{\$\})(?:\/task\/(?:[0-9]+|\$\$|\$\{\$\}))?\/environ$/;
95
+
92
96
  /**
93
97
  * CLI tools that must use wrapper tools for security and audit.
94
98
  */
@@ -186,11 +190,11 @@ function getLeadingLiteralAssignments(
186
190
  const assignments = new Map<string, { value: string; end: number }>();
187
191
  let offset = 0;
188
192
  while (offset === 0 || command[offset - 1] === ";" || command[offset - 1] === "\n") {
189
- while (/\s/.test(command[offset] ?? "")) offset++;
193
+ while (/[ \t\n]/.test(command[offset] ?? "")) offset++;
190
194
  const assignment = /^([A-Za-z_][A-Za-z0-9_]*)=([A-Za-z0-9_./-]+)/.exec(command.slice(offset));
191
195
  if (!assignment) break;
192
196
  const end = offset + assignment[0].length;
193
- const next = command.slice(end).match(/^\s*/)?.[0].length ?? 0;
197
+ const next = command.slice(end).match(/^[ \t]*/)?.[0].length ?? 0;
194
198
  const separator = command[end + next];
195
199
  if (separator !== ";" && separator !== "\n") break;
196
200
  assignments.set(assignment[1] ?? "", { value: assignment[2] ?? "", end });
@@ -235,39 +239,45 @@ function hasSafeLocalAssignmentCommands(
235
239
  assignments.get(assignment[1] ?? "")?.value === assignment[2]
236
240
  );
237
241
  }
238
- const argv = unwrapStaticCommand(words);
239
- if (isSafeHerdrTabCreate(argv)) return true;
240
- const name = argv[0]?.split("/").at(-1) ?? "";
241
- if (name === "cd") return isNavigationOperand(argv, "LOCALVALUE");
242
- if (name === "git") {
243
- let index = 1;
244
- while (argv[index] === "-C" && argv[index + 1]) index += 2;
245
- return (
246
- ["branch", "diff", "log", "rev-parse", "rev-list", "show", "status"].includes(
247
- argv[index] ?? "",
248
- ) && !hasExecutionOption(argv.slice(index + 1), ["exec", "ext-diff", "textconv"])
249
- );
250
- }
251
- if (name === "find") {
252
- return !argv.slice(1).some((arg) => /^-(?:exec|ok|delete|fprint|fprintf)/.test(arg));
253
- }
254
- if (name === "bun") return argv[1] === "run" && ["db-tool", "gh-tool"].includes(argv[2] ?? "");
242
+ return isSafeLocalAssignmentCommand(words);
243
+ });
244
+ }
245
+
246
+ function isSafeLocalAssignmentCommand(words: string[]): boolean {
247
+ const argv = unwrapStaticCommand(words);
248
+ if (isSafeHerdrTabCreate(argv)) return true;
249
+ const name = argv[0]?.split("/").at(-1) ?? "";
250
+ if (name === "wc" && hasExecutionOption(argv.slice(1), ["files0-from"])) return false;
251
+ if (name === "cd") return isNavigationOperand(argv, "LOCALVALUE");
252
+ if (name === "git") {
253
+ let index = 1;
254
+ while (argv[index] === "-C" && argv[index + 1]) index += 2;
255
255
  return (
256
- isPassiveTextCommand(argv) ||
257
- ["ls", "cat", "tail", "wc", "uniq", "cut", "mv"].includes(name) ||
258
- (name === "sort" && !hasExecutionOption(argv.slice(1), ["compress-program"])) ||
259
- (name === "sed" &&
260
- argv
261
- .slice(1)
262
- .every(
263
- (arg) =>
264
- /^-[En]+$/.test(arg) ||
265
- /^s([/|]).*\1[^/|]*\1[gp]*$/.test(arg) ||
266
- /^[A-Za-z0-9_./-]+$/.test(arg),
267
- ) &&
268
- !argv.includes("-f"))
256
+ ["branch", "diff", "log", "rev-parse", "rev-list", "show", "status"].includes(
257
+ argv[index] ?? "",
258
+ ) && !hasExecutionOption(argv.slice(index + 1), ["exec", "ext-diff", "textconv"])
269
259
  );
270
- });
260
+ }
261
+ if (name === "find") {
262
+ return !argv.slice(1).some((arg) => /^-(?:exec|ok|delete|fprint|fprintf)/.test(arg));
263
+ }
264
+ if (name === "bun") return argv[1] === "run" && ["db-tool", "gh-tool"].includes(argv[2] ?? "");
265
+ return (
266
+ isPassiveTextCommand(argv) ||
267
+ ["ls", "cat", "tail", "wc", "uniq", "cut", "mv"].includes(name) ||
268
+ (name === "sort" &&
269
+ !hasExecutionOption(argv.slice(1), ["compress-program", "files0-from", "output"], "o")) ||
270
+ (name === "sed" &&
271
+ argv
272
+ .slice(1)
273
+ .every(
274
+ (arg) =>
275
+ /^-[En]+$/.test(arg) ||
276
+ /^s([/|]).*\1[^/|]*\1[gp]*$/.test(arg) ||
277
+ /^[A-Za-z0-9_./-]+$/.test(arg),
278
+ ) &&
279
+ !argv.includes("-f"))
280
+ );
271
281
  }
272
282
 
273
283
  function hasSensitivePathRedirect(
@@ -425,6 +435,7 @@ function literalBindingText(
425
435
  let quote: "'" | '"' | undefined;
426
436
  for (let i = 0; i < command.length; i++) {
427
437
  const char = command[i] ?? "";
438
+ if (!quote && /[^\S \t\n]/.test(char)) return undefined;
428
439
  if (char === "\\" && quote !== "'") {
429
440
  const next = command[++i];
430
441
  if (next === undefined || /[\r\n]/.test(next)) return undefined;
@@ -520,7 +531,7 @@ function materializeLiteralShell(command: string): LiteralShellProof | undefined
520
531
  if (new TextEncoder().encode(command).byteLength > 65_536) return undefined;
521
532
  const marker = "GUARDLITERALBINDING";
522
533
  if (command.includes(marker)) return undefined;
523
- let script = command.trim();
534
+ let script = command.replace(/^[ \t\n]+|[ \t\n]+$/g, "");
524
535
  const wrapped = parseStaticShellCommands(script);
525
536
  if (
526
537
  wrapped &&
@@ -530,7 +541,10 @@ function materializeLiteralShell(command: string): LiteralShellProof | undefined
530
541
  wrapped.redirects.length === 0
531
542
  ) {
532
543
  const argv = unwrapProofCommand(wrapped.pipelines[0]?.[0] ?? [], marker);
533
- if (argv?.[0] === "sh" && argv[1] === "-c" && argv.length === 3) script = argv[2] ?? "";
544
+ if (argv?.[0] === "sh" && argv[1] === "-c" && argv.length === 3) {
545
+ if (!literalBindingText(script, "", "")) return undefined;
546
+ script = argv[2] ?? "";
547
+ }
534
548
  }
535
549
  const loop =
536
550
  /^for[ \t]+([A-Za-z_]\w*)[ \t]+in[ \t]+([^;\n]+);[ \t\r\n]*do[ \t\r\n]+([\s\S]*);[ \t\r\n]*done[ \t\r\n]*$/.exec(
@@ -583,64 +597,135 @@ function materializeLiteralShell(command: string): LiteralShellProof | undefined
583
597
  paths: [],
584
598
  };
585
599
  }
600
+ // Single ASCII-letter names avoid shell startup/special variables such as PATH and IFS.
586
601
  const assignment =
587
- /^cd[ \t]+(~?\/?[A-Za-z0-9_./-]+)[ \t]+&&[ \t]+([A-Za-z_]\w*)=([A-Za-z0-9_./][A-Za-z0-9_./-]*)[ \t]+&&[ \t]+/.exec(
588
- command,
602
+ /^(?:cd[ \t]+(~?\/?[A-Za-z0-9_./-]+)[ \t]*(;|\n|&&)[ \t]*)?([A-Za-z])=([A-Za-z0-9_./][A-Za-z0-9_./-]*)[ \t]*(;|\n|&&)[ \t]*/.exec(
603
+ script,
589
604
  );
590
- if (assignment && isLiteralBinder(assignment[2] ?? "")) {
605
+ if (assignment) {
591
606
  const rest = literalBindingText(
592
- command.slice(assignment[0].length),
593
- assignment[2] ?? "",
607
+ script.slice(assignment[0].length),
608
+ assignment[3] ?? "",
594
609
  marker,
595
610
  );
596
- if (!rest) return undefined;
597
- const end = rest.syntax.search(/[;&|\r\n]/);
598
- const use = rest.text.slice(0, end < 0 ? undefined : end);
599
- const suffix = end < 0 ? "" : rest.text.slice(end);
600
- if (suffix.includes(marker)) return undefined;
601
- const parsed = parseStaticShellCommands(use);
602
- const argv =
603
- parsed &&
604
- typeof parsed !== "string" &&
605
- parsed.pipelines.length === 1 &&
606
- parsed.pipelines[0]?.length === 1 &&
607
- parsed.redirects.length === 0
608
- ? parsed.pipelines[0]?.[0]
609
- : undefined;
611
+ if (!rest || !rest.text.includes(marker)) return undefined;
612
+ // No branches, background jobs or pipeline-local state. FD duplication stays inert.
613
+ const syntax = rest.syntax.replace(/[<>]&[0-9-]+/g, "");
614
+ if (/\|\||(^|[^&])&(?!&)|[^\S \t\n]/.test(syntax)) return undefined;
615
+ if (assignment[2] === "&&") {
616
+ if (assignment[5] !== "&&") return undefined;
617
+ const boundary = rest.syntax.search(/[;\r\n]/);
618
+ if (boundary >= 0 && rest.text.slice(boundary).includes(marker)) return undefined;
619
+ }
620
+ const parsed = parseStaticShellCommands(rest.text);
610
621
  if (
611
- !argv ||
612
- argv.length < 4 ||
613
- argv.slice(0, 3).join(" ") !== "git add --" ||
614
- argv.slice(3).some((word) => !/^[A-Za-z0-9_./-]+$/.test(word))
622
+ !parsed ||
623
+ typeof parsed === "string" ||
624
+ parsed.redirects.some(({ target }) => target.includes(marker)) ||
625
+ !parsed.pipelines.flat().length ||
626
+ parsed.pipelines.flat().length > 32
615
627
  )
616
628
  return undefined;
617
- const value = assignment[3] ?? "";
629
+ const value = assignment[4] ?? "";
630
+ const paths: string[] = [];
631
+ for (const words of parsed.pipelines.flat()) {
632
+ const marked = unwrapProofCommand(words, marker);
633
+ if (!marked) return undefined;
634
+ const argv = marked.map((word) => word.replaceAll(marker, () => value));
635
+ const name = argv[0]?.split("/").at(-1) ?? "";
636
+ const uses = marked.flatMap((word, index) => (word.includes(marker) ? [index] : []));
637
+ const checksum =
638
+ ["shasum", "sha1sum", "sha256sum", "sha512sum", "md5sum", "cksum"].includes(name) &&
639
+ !hasExecutionOption(argv.slice(1), ["check"], "c");
640
+ if (!uses.length) {
641
+ if (
642
+ !isSafeLocalAssignmentCommand(argv) &&
643
+ inlineProgramIndex(argv) === undefined &&
644
+ !(argv[0] === "git" && argv[1] === "commit") &&
645
+ !checksum
646
+ )
647
+ return undefined;
648
+ continue;
649
+ }
650
+ if (
651
+ uses.some(
652
+ (index) => index === 0 || !/^[A-Za-z0-9_./][A-Za-z0-9_./-]*$/.test(argv[index] ?? ""),
653
+ )
654
+ )
655
+ return undefined;
656
+ const gitAdd =
657
+ argv.slice(0, 3).join(" ") === "git add --" && uses.every((index) => index >= 3);
658
+ const reader =
659
+ ["cat", "ls", "head", "tail", "wc", "uniq", "cut", "sort", "grep", "rg"].includes(name) &&
660
+ isSafeLocalAssignmentCommand(argv);
661
+ if (!gitAdd && !reader && !checksum) return undefined;
662
+ paths.push(...uses.map((index) => argv[index] ?? ""));
663
+ }
664
+ const prefix = assignment[1] ? `cd ${assignment[1]}${assignment[2]} ` : "";
618
665
  const size =
619
- new TextEncoder().encode(rest.text).byteLength +
620
- (use.split(marker).length - 1) * (value.length - marker.length) +
621
- (assignment[1]?.length ?? 0) +
622
- 7;
623
- if (size > 65_536) return undefined;
624
- const paths = argv.slice(3).map((word) => word.replaceAll(marker, () => value));
625
- return {
626
- command: `cd ${assignment[1]} && ${use.replaceAll(marker, () => value)}${suffix}`,
627
- paths,
628
- };
666
+ new TextEncoder().encode(prefix + rest.text).byteLength +
667
+ (rest.text.split(marker).length - 1) * (value.length - marker.length);
668
+ if (paths.length > 32 || size > 65_536) return undefined;
669
+ return { command: prefix + rest.text.replaceAll(marker, () => value), paths };
629
670
  }
630
- // Only the observed rg -n PATTERN PATH form; marker position proves a real file operand.
631
- const brace =
632
- /(?:^|\s)([A-Za-z0-9_./-]*\/[A-Za-z0-9_./-]*\{[A-Za-z_]\w*(?:,[A-Za-z_]\w*){1,7}\}[A-Za-z0-9_./-]*)$/.exec(
633
- command,
634
- );
635
- if (!brace) return undefined;
636
- const path = brace[1] ?? "";
637
- const start = command.length - path.length;
638
- const marked = command.slice(0, start) + marker;
639
- const lexical = literalBindingText(marked, "", "");
671
+ // Expand only complete, unquoted path words. Keep all other source text intact.
672
+ const paths: string[] = [];
673
+ let expanded = "";
674
+ let marked = "";
675
+ let start = 0;
676
+ let quote: "'" | '"' | undefined;
677
+ let braces = false;
678
+ const finishWord = (end: number): boolean => {
679
+ const word = command.slice(start, end);
680
+ if (!braces) {
681
+ expanded += word;
682
+ marked += word;
683
+ return true;
684
+ }
685
+ // ponytail: one comma-list per path, no nesting; extend only with a bounded shell parser.
686
+ const match =
687
+ /^([A-Za-z0-9_./-]*\/[A-Za-z0-9_./-]*)\{([A-Za-z0-9_./-]+(?:,[A-Za-z0-9_./-]+)+)\}([A-Za-z0-9_./-]*)$/.exec(
688
+ word,
689
+ );
690
+ if (!match) return false;
691
+ const members = (match[2] ?? "").split(",");
692
+ if (members.length > 16 || paths.length + members.length > 32) return false;
693
+ const values = members.map((member) => (match[1] ?? "") + member + (match[3] ?? ""));
694
+ const text = values.join(" ");
695
+ if (expanded.length + text.length + command.length - end > 65_536) return false;
696
+ paths.push(...values);
697
+ expanded += text;
698
+ marked += marker;
699
+ return true;
700
+ };
701
+ for (let i = 0; i <= command.length; i++) {
702
+ const char = command[i];
703
+ if (quote === "'") {
704
+ if (char === quote) quote = undefined;
705
+ } else if (char === "\\") {
706
+ if (command[i + 1] === undefined || /[\r\n]/.test(command[i + 1] ?? "")) return undefined;
707
+ i++;
708
+ } else if (quote === '"') {
709
+ if (char === quote) quote = undefined;
710
+ } else if (char === "'" || char === '"') {
711
+ quote = char;
712
+ } else if (char === "{" || char === "}") {
713
+ braces = true;
714
+ } else if (char === undefined || /[ \t\n]/.test(char)) {
715
+ if (!finishWord(i)) return undefined;
716
+ expanded += char ?? "";
717
+ marked += char ?? "";
718
+ start = i + 1;
719
+ braces = false;
720
+ } else if (/[\s;&|<>#]/.test(char)) {
721
+ // Other JS whitespace is a literal shell word character, not a token boundary.
722
+ return undefined;
723
+ }
724
+ }
725
+ if (quote || !paths.length || new TextEncoder().encode(expanded).byteLength > 65_536)
726
+ return undefined;
640
727
  const parsed = parseStaticShellCommands(marked);
641
728
  if (
642
- !lexical ||
643
- /[;&|<>\r\n]/.test(lexical.syntax) ||
644
729
  !parsed ||
645
730
  typeof parsed === "string" ||
646
731
  parsed.redirects.length ||
@@ -649,24 +734,19 @@ function materializeLiteralShell(command: string): LiteralShellProof | undefined
649
734
  )
650
735
  return undefined;
651
736
  const argv = unwrapProofCommand(parsed.pipelines[0]?.[0] ?? [], marker);
737
+ const expandedCommands = parseStaticShellCommands(expanded);
738
+ const expandedArgv =
739
+ expandedCommands && typeof expandedCommands !== "string"
740
+ ? unwrapProofCommand(expandedCommands.pipelines[0]?.[0] ?? [], marker)
741
+ : undefined;
742
+ // Classify actual options too: a marked path can hide an executor such as git grep -O/path.
652
743
  if (
653
744
  !argv ||
654
- argv.length !== 4 ||
655
- argv[0] !== "rg" ||
656
- argv[1] !== "-n" ||
657
- argv[2]?.startsWith("-") ||
658
- argv[3] !== marker
745
+ !expandedArgv ||
746
+ (!isPassiveTextCommand(expandedArgv) && expandedArgv[0]?.split("/").at(-1) !== "cat")
659
747
  )
660
748
  return undefined;
661
- const members = /\{([^{}]+)\}/.exec(path);
662
- if (!members) return undefined;
663
- const values = (members[1] ?? "").split(",");
664
- const size =
665
- new TextEncoder().encode(command.slice(0, start)).byteLength +
666
- values.reduce((total, value) => total + path.length - members[0].length + value.length + 1, -1);
667
- if (size > 65_536) return undefined;
668
- const paths = values.map((member) => path.replace(members[0], () => member));
669
- return { command: command.slice(0, start) + paths.join(" "), paths };
749
+ return { command: expanded, paths };
670
750
  }
671
751
 
672
752
  /** Complete package metadata loops: no prelude, loader shadowing, mutation or arbitrary suffix. */
@@ -1263,12 +1343,144 @@ function unwrapStaticCommand(words: string[]): string[] {
1263
1343
  }
1264
1344
 
1265
1345
  function isAllowedEnvironmentRead(argv: string[], allowedNames: Set<string>): boolean {
1346
+ if (isAllowedPythonEnvironmentRead(argv, allowedNames)) return true;
1266
1347
  if (argv[0]?.split("/").at(-1) !== "printenv") return false;
1267
1348
  const args = argv.slice(1);
1268
1349
  if (args[0] === "--") args.shift();
1269
1350
  return args.length > 0 && args.every((name) => allowedNames.has(name));
1270
1351
  }
1271
1352
 
1353
+ /** Prove the complete, print-only Python program before treating its reads as approved. */
1354
+ function isAllowedPythonEnvironmentRead(argv: string[], allowedNames: Set<string>): boolean {
1355
+ const index = inlineProgramIndex(argv);
1356
+ if (inlineRuntimeKind(argv[0]) !== "python" || index === undefined || argv.length !== index + 1)
1357
+ return false;
1358
+
1359
+ const program = argv[index] ?? "";
1360
+ let position = 0;
1361
+ let foundRead = false;
1362
+ const skipInlineWhitespace = () => {
1363
+ while (/[\t ]/.test(program[position] ?? "")) position++;
1364
+ };
1365
+ const take = (value: string): boolean => {
1366
+ if (!program.startsWith(value, position)) return false;
1367
+ position += value.length;
1368
+ return true;
1369
+ };
1370
+ const takeIdentifier = (value: string): boolean => {
1371
+ if (!take(value) || /[A-Za-z0-9_]/.test(program[position] ?? "")) return false;
1372
+ return true;
1373
+ };
1374
+ const takeString = (): string | undefined => {
1375
+ skipInlineWhitespace();
1376
+ const quote = program[position];
1377
+ if ((quote !== "'" && quote !== '"') || program.startsWith(quote.repeat(3), position))
1378
+ return undefined;
1379
+ position++;
1380
+ const start = position;
1381
+ while (position < program.length && program[position] !== quote) {
1382
+ if (/[\\\r\n]/.test(program[position] ?? "")) return undefined;
1383
+ position++;
1384
+ }
1385
+ if (program[position] !== quote) return undefined;
1386
+ const value = program.slice(start, position);
1387
+ position++;
1388
+ return value;
1389
+ };
1390
+ const takeEnvironmentRead = (): boolean => {
1391
+ skipInlineWhitespace();
1392
+ const start = position;
1393
+ if (!takeIdentifier("os")) return false;
1394
+ if (!take(".")) {
1395
+ position = start;
1396
+ return false;
1397
+ }
1398
+ if (takeIdentifier("getenv")) {
1399
+ if (!take("(")) return false;
1400
+ const name = takeString();
1401
+ if (name === undefined || !allowedNames.has(name)) return false;
1402
+ skipInlineWhitespace();
1403
+ if (take(",")) {
1404
+ if (takeString() === undefined) return false;
1405
+ skipInlineWhitespace();
1406
+ }
1407
+ if (!take(")")) return false;
1408
+ foundRead = true;
1409
+ return true;
1410
+ }
1411
+ if (!takeIdentifier("environ")) return false;
1412
+ if (take(".")) {
1413
+ if (!takeIdentifier("get") || !take("(")) return false;
1414
+ const name = takeString();
1415
+ if (name === undefined || !allowedNames.has(name)) return false;
1416
+ skipInlineWhitespace();
1417
+ if (take(",")) {
1418
+ if (takeString() === undefined) return false;
1419
+ skipInlineWhitespace();
1420
+ }
1421
+ if (!take(")")) return false;
1422
+ foundRead = true;
1423
+ return true;
1424
+ }
1425
+ if (!take("[")) return false;
1426
+ const name = takeString();
1427
+ if (name === undefined || !allowedNames.has(name)) return false;
1428
+ skipInlineWhitespace();
1429
+ if (!take("]")) return false;
1430
+ foundRead = true;
1431
+ return true;
1432
+ };
1433
+ const takeExpression = (): boolean => {
1434
+ const takeTerm = (): boolean => takeString() !== undefined || takeEnvironmentRead();
1435
+ if (!takeTerm()) return false;
1436
+ skipInlineWhitespace();
1437
+ while (take("+")) {
1438
+ if (!takeTerm()) return false;
1439
+ skipInlineWhitespace();
1440
+ }
1441
+ return true;
1442
+ };
1443
+ const takePrint = (): boolean => {
1444
+ skipInlineWhitespace();
1445
+ if (!takeIdentifier("print")) return false;
1446
+ skipInlineWhitespace();
1447
+ if (!take("(")) return false;
1448
+ skipInlineWhitespace();
1449
+ if (take(")")) return true;
1450
+ while (true) {
1451
+ if (!takeExpression()) return false;
1452
+ skipInlineWhitespace();
1453
+ if (take(")")) return true;
1454
+ if (!take(",")) return false;
1455
+ skipInlineWhitespace();
1456
+ if (take(")")) return true;
1457
+ }
1458
+ };
1459
+ const skipSeparators = (): void => {
1460
+ while (true) {
1461
+ skipInlineWhitespace();
1462
+ if (take(";") || take("\n") || take("\r\n")) continue;
1463
+ break;
1464
+ }
1465
+ };
1466
+
1467
+ skipInlineWhitespace();
1468
+ if (!takeIdentifier("import")) return false;
1469
+ skipInlineWhitespace();
1470
+ if (!takeIdentifier("os")) return false;
1471
+ skipInlineWhitespace();
1472
+ if (!(take(";") || take("\n") || take("\r\n"))) return false;
1473
+ skipSeparators();
1474
+ while (position < program.length) {
1475
+ if (!takePrint()) return false;
1476
+ skipInlineWhitespace();
1477
+ if (position === program.length) break;
1478
+ if (!(take(";") || take("\n") || take("\r\n"))) return false;
1479
+ skipSeparators();
1480
+ }
1481
+ return foundRead;
1482
+ }
1483
+
1272
1484
  function hasExecutionOption(args: string[], longOptions: string[], shortOption?: string): boolean {
1273
1485
  return args.some((arg) => {
1274
1486
  const flag = arg.split("=", 1)[0] ?? "";
@@ -1431,13 +1643,13 @@ function hasEnvironmentRead(
1431
1643
  const pipelines = parsed.pipelines.map((commands) => commands.map(unwrapStaticCommand));
1432
1644
  const unwrapped = pipelines.flat();
1433
1645
  if (
1434
- command.includes(">") &&
1646
+ parsed.redirects.length > 0 &&
1435
1647
  unwrapped.some((argv) => isAllowedEnvironmentRead(argv, allowedNames))
1436
1648
  ) {
1437
1649
  return true;
1438
1650
  }
1439
1651
  if (
1440
- command.includes(">") &&
1652
+ parsed.redirects.length > 0 &&
1441
1653
  pipelines.some((pipeline) =>
1442
1654
  pipeline.some(
1443
1655
  (argv) => isLiteralTextProducer(argv) && mentionsEnvironmentRead(argv.join(" ")),
@@ -1574,7 +1786,7 @@ function hasSensitiveFileRead(command: string, isPathBlocked: (path: string) =>
1574
1786
  if (/\bcat\b[^;&|]*<<-?\s*\S+[\s\S]*\b(?:secret|credential)\b/i.test(command)) return true;
1575
1787
  const parsed = parseStaticShellCommands(command);
1576
1788
  const readers =
1577
- /\b(?:cat|cp|grep|rg|sed|awk|jq|head|tail|less|more|source|ls|sort|uniq|cut|wc|mv|find)\b/i;
1789
+ /\b(?:cat|cp|grep|rg|sed|awk|jq|head|tail|less|more|source|ls|sort|uniq|cut|wc|mv|find|shasum|sha1sum|sha256sum|sha512sum|md5sum|cksum)\b/i;
1578
1790
  if (parsed && parsed !== "brace-expansion") {
1579
1791
  return parsed.pipelines.flat().some((words) => {
1580
1792
  const argv = unwrapStaticCommand(words);
@@ -1963,6 +2175,28 @@ function isLiteralInlineWriter(argv: string[]): boolean {
1963
2175
  return take(/^\s*\)\s*;?\s*$/) && position === program.length;
1964
2176
  }
1965
2177
 
2178
+ /** Literal inline output can accompany a proved environment display; file writers cannot. */
2179
+ function isLiteralInlineDisplay(argv: string[]): boolean {
2180
+ const index = inlineProgramIndex(argv);
2181
+ if (index === undefined || !isLiteralInlineWriter(argv)) return false;
2182
+ const kind = inlineRuntimeKind(argv[0]);
2183
+ const program = argv[index] ?? "";
2184
+ return (
2185
+ (kind === "python" && /^\s*print\s*\(/.test(program)) ||
2186
+ (kind === "node" && /^\s*console\s*\.\s*log\s*\(/.test(program))
2187
+ );
2188
+ }
2189
+
2190
+ /** Parse approved Python readers from the original shell shape, including quoted stdin heredocs. */
2191
+ function hasApprovedPythonEnvironmentRead(command: string, allowedNames: Set<string>): boolean {
2192
+ const normalized = normalizeProgramHeredocs(command);
2193
+ const parsed = parseStaticShellCommands(normalized);
2194
+ if (!parsed || typeof parsed === "string") return false;
2195
+ return parsed.pipelines
2196
+ .flat()
2197
+ .some((words) => isAllowedPythonEnvironmentRead(unwrapStaticCommand(words), allowedNames));
2198
+ }
2199
+
1966
2200
  /** Inert command identity is unproved after an explicit environment mutation. */
1967
2201
  function hasEnvironmentMutationPrefix(command: string): boolean {
1968
2202
  const heredoc = boundedHeredoc(command);
@@ -1991,10 +2225,27 @@ function hasEnvironmentMutationPrefix(command: string): boolean {
1991
2225
  });
1992
2226
  }
1993
2227
 
1994
- function hasEnvironmentSourceAccess(command: string, rawTrigger: boolean): boolean {
2228
+ function hasEnvironmentSourceAccess(
2229
+ command: string,
2230
+ rawTrigger: boolean,
2231
+ allowedNames: Set<string>,
2232
+ ): boolean {
1995
2233
  if (rawTrigger && hasEnvironmentMutationPrefix(command)) return true;
1996
- if (isLiteralTextWrite(command) || isStaticHerdrPrompt(command)) return false;
1997
2234
  const parsed = parseStaticShellCommands(command);
2235
+ if (parsed && typeof parsed !== "string") {
2236
+ const commands = parsed.pipelines.flat().map(unwrapStaticCommand);
2237
+ if (commands.some((argv) => isAllowedPythonEnvironmentRead(argv, allowedNames))) {
2238
+ if (hasEnvironmentMutationPrefix(command)) return true;
2239
+ return !commands.every(
2240
+ (argv) =>
2241
+ argv[0]?.split("/").at(-1) === "cat" ||
2242
+ isPassiveTextCommand(argv) ||
2243
+ isAllowedPythonEnvironmentRead(argv, allowedNames) ||
2244
+ isLiteralInlineDisplay(argv),
2245
+ );
2246
+ }
2247
+ }
2248
+ if (isLiteralTextWrite(command) || isStaticHerdrPrompt(command)) return false;
1998
2249
  if (!parsed || typeof parsed === "string") return rawTrigger;
1999
2250
  const commands = parsed.pipelines.flat().map(unwrapStaticCommand);
2000
2251
  if (rawTrigger) {
@@ -2007,12 +2258,15 @@ function hasEnvironmentSourceAccess(command: string, rawTrigger: boolean): boole
2007
2258
  );
2008
2259
  }
2009
2260
  return commands.some((argv) => {
2261
+ if (isAllowedPythonEnvironmentRead(argv, allowedNames)) return false;
2010
2262
  const index = inlineProgramIndex(argv);
2011
2263
  if (index === undefined) return false;
2012
- const parts = programParts(argv[index] ?? "", inlineRuntimeKind(argv[0]) === "python");
2264
+ const python = inlineRuntimeKind(argv[0]) === "python";
2265
+ const parts = programParts(argv[index] ?? "", python);
2013
2266
  if (!parts) return true;
2014
2267
  return (
2015
2268
  mentionsEnvironmentSource(parts.code) ||
2269
+ (python && /\b(?:environ|getenv)\b/.test(parts.code)) ||
2016
2270
  (/\b(?:os|process)\s*\[/.test(parts.code) &&
2017
2271
  parts.literals.some((value) => /^(?:env|environ|getenv)$/.test(value)))
2018
2272
  );
@@ -2085,12 +2339,17 @@ export function createCredentialGuard(config?: CredentialGuardConfig): Credentia
2085
2339
 
2086
2340
  function isPathAllowed(filePath: string): boolean {
2087
2341
  const normalizedPath = filePath.replace(/\\/g, "/");
2088
- return allowedPathPatterns.some((pattern) => pattern.test(normalizedPath));
2342
+ return (
2343
+ !PROCESS_ENVIRONMENT_PATH.test(posix.normalize(normalizedPath)) &&
2344
+ allowedPathPatterns.some((pattern) => pattern.test(normalizedPath))
2345
+ );
2089
2346
  }
2090
2347
 
2091
2348
  function isPathBlocked(filePath: string): boolean {
2092
2349
  const normalizedPath = filePath.replace(/\\/g, "/");
2093
2350
 
2351
+ if (PROCESS_ENVIRONMENT_PATH.test(posix.normalize(normalizedPath))) return true;
2352
+
2094
2353
  for (const pattern of allowedPathPatterns) {
2095
2354
  if (pattern.test(normalizedPath)) {
2096
2355
  return false;
@@ -2126,6 +2385,12 @@ export function createCredentialGuard(config?: CredentialGuardConfig): Credentia
2126
2385
  const allowPackageInventory = hasProvedPackageInventoryInvocation(originalCommand);
2127
2386
  const rawEnvironmentSource =
2128
2387
  mentionsEnvironmentSource(command) && mentionsInlineRuntime(command);
2388
+ if (
2389
+ hasApprovedPythonEnvironmentRead(originalCommand, allowedEnvironmentVariables) &&
2390
+ hasEnvironmentMutationPrefix(normalizeProgramHeredocs(originalCommand))
2391
+ ) {
2392
+ return "blocked by the environment/execution policy after an unproved environment mutation";
2393
+ }
2129
2394
  if (rawEnvironmentSource && hasEnvironmentMutationPrefix(originalCommand))
2130
2395
  return "blocked by the environment/execution policy after an unproved environment mutation";
2131
2396
  command = normalizeProgramHeredocs(command);
@@ -2157,7 +2422,7 @@ export function createCredentialGuard(config?: CredentialGuardConfig): Credentia
2157
2422
  return "expands an unapproved or executable environment variable value";
2158
2423
  }
2159
2424
  if (
2160
- hasEnvironmentSourceAccess(command, rawEnvironmentSource) ||
2425
+ hasEnvironmentSourceAccess(command, rawEnvironmentSource, allowedEnvironmentVariables) ||
2161
2426
  hasEnvironmentRead(command, allowedEnvironmentVariables, allowPackageInventory)
2162
2427
  ) {
2163
2428
  return "blocked by the environment/execution policy; permitted access or non-execution could not be established for this command form";
@@ -28,6 +28,7 @@ import {
28
28
  prEditCommand,
29
29
  prMergeCommand,
30
30
  prReadyCommand,
31
+ prDraftCommand,
31
32
  prStackCommand,
32
33
  prRequestReviewCommand,
33
34
  prThreadsCommand,
@@ -95,6 +96,7 @@ const prCommand = Command.make("pr", {}).pipe(
95
96
  prEditCommand,
96
97
  prMergeCommand,
97
98
  prReadyCommand,
99
+ prDraftCommand,
98
100
  prStackCommand,
99
101
  prRequestReviewCommand,
100
102
  prWaitMergeableCommand,
@@ -34,6 +34,7 @@ import {
34
34
  closePR,
35
35
  collectWithStableState,
36
36
  createPR,
37
+ draftPR,
37
38
  detectPRStatus,
38
39
  editPR,
39
40
  fetchPRView,
@@ -784,6 +785,26 @@ export const prReadyCommand = Command.make(
784
785
  ),
785
786
  );
786
787
 
788
+ export const prDraftCommand = Command.make(
789
+ "draft",
790
+ {
791
+ format: formatOption,
792
+ pr: Flag.Int("pr").pipe(
793
+ Flag.withDescription("PR number (default: current branch PR)"),
794
+ Flag.optional,
795
+ ),
796
+ repo: repoOption,
797
+ },
798
+ ({ format, pr, repo }) =>
799
+ withRepo(
800
+ repo,
801
+ Effect.gen(function* () {
802
+ const result = yield* draftPR({ pr: Option.getOrNull(pr) });
803
+ yield* logFormatted(result, format);
804
+ }),
805
+ ),
806
+ ).pipe(Command.withDescription("Convert an open PR to draft (no-op if it's already a draft)"));
807
+
787
808
  export const prChecksCommand = Command.make(
788
809
  "checks",
789
810
  {
@@ -1220,6 +1220,21 @@ export const readyPR = Effect.fn("pr.readyPR")(function* (opts: { pr: number | n
1220
1220
  return { ...updated, wasAlreadyReady: false };
1221
1221
  });
1222
1222
 
1223
+ export const draftPR = Effect.fn("pr.draftPR")(function* (opts: { pr: number | null }) {
1224
+ const gh = yield* GitHubService;
1225
+
1226
+ const info = yield* viewPR(opts.pr);
1227
+
1228
+ if (info.isDraft) {
1229
+ return { ...info, wasAlreadyDraft: true };
1230
+ }
1231
+
1232
+ yield* gh.runGh(["pr", "ready", String(info.number), "--undo"]);
1233
+
1234
+ const updated = yield* viewPR(info.number);
1235
+ return { ...updated, wasAlreadyDraft: false };
1236
+ });
1237
+
1223
1238
  export const editPR = Effect.fn("pr.editPR")(function* (opts: {
1224
1239
  pr: number;
1225
1240
  title: string | null;
@@ -6,6 +6,7 @@ export {
6
6
  prCommentsCommand,
7
7
  prCreateCommand,
8
8
  prDiscussionSummaryCommand,
9
+ prDraftCommand,
9
10
  prEditCommand,
10
11
  prFeedbackCommand,
11
12
  prIssueCommentsCommand,