@yagni-app/code-staging 0.3.0-staging.1091.1 → 0.3.0-staging.1093.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.
@@ -29,7 +29,7 @@
29
29
  */
30
30
  import { runStage as defaultRunStage } from "./pipeline/runner.js";
31
31
  export const DEFAULT_GUARDIAN_LIMITS = {
32
- maxReviews: 30,
32
+ maxReviews: 120,
33
33
  maxConsecutiveDenials: 3,
34
34
  timeoutMs: 15_000,
35
35
  };
package/dist/login.d.ts CHANGED
@@ -34,8 +34,10 @@ type OpenRunner = (cmd: string, args: string[]) => Promise<void>;
34
34
  *
35
35
  * macOS: open <url>
36
36
  * Linux: xdg-open <url>
37
- * Windows: cmd /c start "" <url> (the empty "" is start's window-title slot;
38
- * without it `start` swallows the URL as the title and opens nothing)
37
+ * Windows: rundll32 url.dll,FileProtocolHandler <url> (opens the default
38
+ * browser without going through cmd.exe `cmd /c start <url>`
39
+ * re-parses its arguments as a shell line, so a hostile URL with
40
+ * `&`/`^` metacharacters could execute commands)
39
41
  */
40
42
  export declare function resolveOpenCommand(url: string, platform?: NodeJS.Platform): {
41
43
  cmd: string;
package/dist/login.js CHANGED
@@ -31,14 +31,17 @@ function isTimeoutError(err) {
31
31
  *
32
32
  * macOS: open <url>
33
33
  * Linux: xdg-open <url>
34
- * Windows: cmd /c start "" <url> (the empty "" is start's window-title slot;
35
- * without it `start` swallows the URL as the title and opens nothing)
34
+ * Windows: rundll32 url.dll,FileProtocolHandler <url> (opens the default
35
+ * browser without going through cmd.exe `cmd /c start <url>`
36
+ * re-parses its arguments as a shell line, so a hostile URL with
37
+ * `&`/`^` metacharacters could execute commands)
36
38
  */
37
39
  export function resolveOpenCommand(url, platform = process.platform) {
38
40
  if (platform === "darwin")
39
41
  return { cmd: "open", args: [url] };
40
- if (platform === "win32")
41
- return { cmd: "cmd", args: ["/c", "start", "", url] };
42
+ if (platform === "win32") {
43
+ return { cmd: "rundll32", args: ["url.dll,FileProtocolHandler", url] };
44
+ }
42
45
  return { cmd: "xdg-open", args: [url] };
43
46
  }
44
47
  const spawnRunner = (cmd, args) => new Promise((resolve, reject) => {
@@ -50,6 +53,18 @@ const spawnRunner = (cmd, args) => new Promise((resolve, reject) => {
50
53
  * URL is still printed for manual copy. `runner` is injectable for tests.
51
54
  */
52
55
  export const realOpenUrl = (url, runner = spawnRunner) => {
56
+ // Only ever hand http(s) URLs to the OS opener — refuse file:, javascript:,
57
+ // or custom schemes a compromised server response could try to smuggle in.
58
+ let parsed;
59
+ try {
60
+ parsed = new URL(url);
61
+ }
62
+ catch {
63
+ return Promise.resolve();
64
+ }
65
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
66
+ return Promise.resolve();
67
+ }
53
68
  const { cmd, args } = resolveOpenCommand(url);
54
69
  return runner(cmd, args).catch(() => {
55
70
  // Silently fail — the user can still copy the URL manually.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yagni-app/code-staging",
3
- "version": "0.3.0-staging.1091.1",
3
+ "version": "0.3.0-staging.1093.1",
4
4
  "description": "YAGNI Code: a terminal coding agent that already knows your company. One YAGNI login routes the model and grounds the agent in your team's context.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "YAGNI, Inc. <jack@yagni.app> (https://yagni.app)",
@@ -38,5 +38,5 @@
38
38
  "@earendil-works/pi-tui": "0.84.1",
39
39
  "typebox": "^1.3.11"
40
40
  },
41
- "yagniSourceSha": "50ccbb69838d6ee20a0b0d7a7b7259105158f215"
41
+ "yagniSourceSha": "189159f08a0b5f7ab5cf10221f8238782ff7d1f7"
42
42
  }