@gotgenes/pi-permission-system 33.0.7 → 33.0.8

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/CHANGELOG.md CHANGED
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [33.0.8](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v33.0.7...pi-permission-system-v33.0.8) (2026-09-23)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **pi-permission-system:** stop reading a git revision range as a parent-directory path ([2656b8d](https://github.com/gotgenes/pi-packages/commit/2656b8d8867404a623534004a7edab41a0de93b1)), closes [#859](https://github.com/gotgenes/pi-packages/issues/859)
14
+
8
15
  ## [33.0.7](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v33.0.6...pi-permission-system-v33.0.7) (2026-09-22)
9
16
 
10
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-permission-system",
3
- "version": "33.0.7",
3
+ "version": "33.0.8",
4
4
  "description": "Permission enforcement extension for the Pi coding agent.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -52,7 +52,7 @@ import type { PathFlavor } from "#src/path/path-flavor";
52
52
  * Accepts tokens that unambiguously look like filesystem paths:
53
53
  * - Absolute paths (starting with `/`)
54
54
  * - Home-relative paths (starting with `~/`)
55
- * - Parent-traversal paths (containing `..`)
55
+ * - Parent-traversal paths (carrying a whole `..` segment)
56
56
  * - Windows drive-letter absolute paths (`C:/…` or `C:\…`)
57
57
  *
58
58
  * Returns the raw token string if it qualifies, or `null` to skip.
@@ -62,7 +62,7 @@ export function classifyTokenAsPathCandidate(token: string): string | null {
62
62
 
63
63
  if (token.startsWith("/")) return token;
64
64
  if (token.startsWith("~/")) return token;
65
- if (token.includes("..")) return token;
65
+ if (hasParentTraversal(token)) return token;
66
66
  if (WINDOWS_DRIVE_PATH_PATTERN.test(token)) return token;
67
67
 
68
68
  return null;
@@ -85,7 +85,8 @@ export function classifyTokenAsPathCandidate(token: string): string | null {
85
85
  * and order-independent, and covers the backslash-only form (`D:\…`) which the POSIX
86
86
  * flavor's `hasPathSeparator` cannot reach.
87
87
  *
88
- * Does NOT require the strict "must start with `/` or `~/` or contain `..`"
88
+ * Does NOT require the strict "must start with `/` or `~/` or carry a whole
89
+ * `..` segment"
89
90
  * gate that the external-directory classifier uses.
90
91
  *
91
92
  * Returns the raw token string if it qualifies, or `null` to skip.
@@ -98,7 +99,7 @@ export function classifyTokenAsRuleCandidate(
98
99
 
99
100
  if (token.startsWith(".")) return token;
100
101
  if (flavor.hasPathSeparator(token)) return token; // ~/ paths, relative paths with /, and win32 dir\file
101
- if (token.includes("..")) return token; // bare ".." (no slash)
102
+ if (hasParentTraversal(token)) return token; // a backslash `..` segment on POSIX
102
103
  if (WINDOWS_DRIVE_PATH_PATTERN.test(token)) return token; // backslash-only drive form
103
104
 
104
105
  return null;
@@ -131,6 +132,23 @@ export function classifyBareTokenCandidate(token: string): string | null {
131
132
 
132
133
  // ── Private rejection predicate ────────────────────────────────────────────
133
134
 
135
+ /**
136
+ * A `..` standing as a whole path segment: exactly `..`, or a `..` bounded by
137
+ * a separator (`/` or `\`) or a token edge on both sides. A `..` inside a
138
+ * segment is not a traversal: a git revision range (`HEAD..origin/main`,
139
+ * `v1..v2`, `a...b`) never names a parent directory, so it must not reach the
140
+ * external-directory guard. A real file whose name carries `..` is still
141
+ * reached through the resolver's existence probe (#645).
142
+ *
143
+ * The backslash counts on every flavor: the strict classifier takes no flavor,
144
+ * and Git Bash hands a `\` to Windows file APIs as a separator.
145
+ */
146
+ const PARENT_TRAVERSAL_SEGMENT_PATTERN = /(^|[/\\])\.\.($|[/\\])/;
147
+
148
+ function hasParentTraversal(token: string): boolean {
149
+ return PARENT_TRAVERSAL_SEGMENT_PATTERN.test(token);
150
+ }
151
+
134
152
  /**
135
153
  * Windows drive-letter absolute path: a single ASCII letter, a colon, then a
136
154
  * separator (`/` or `\`). Matches `C:/…` and `C:\…` but not drive-relative