codegate-ai 0.14.2 → 0.14.4
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/cli.js +18 -1
- package/dist/scan-target/staging.js +2 -0
- package/dist/scan-target/types.d.ts +8 -0
- package/dist/scan.js +35 -7
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -296,7 +296,24 @@ function addScanCommand(program, version, deps) {
|
|
|
296
296
|
? true
|
|
297
297
|
: (baseConfig.workflow_audits?.enabled ?? false),
|
|
298
298
|
},
|
|
299
|
-
|
|
299
|
+
// When the raw input was a single local file (now staged into a
|
|
300
|
+
// temp dir), walking the full user-scope tree is off-target — the
|
|
301
|
+
// user asked to scan one file, not their whole home. Without
|
|
302
|
+
// this guard, sibling findings (e.g. `~/.agents/skills/*/SKILL.md`)
|
|
303
|
+
// leak into scans of files like `.claude/settings.json` or
|
|
304
|
+
// `.idea/workspace.xml`.
|
|
305
|
+
//
|
|
306
|
+
// Earlier we gated on `explicitCandidates.length > 0`, but that
|
|
307
|
+
// falsely passed for files whose extension is not in the
|
|
308
|
+
// text-like format list (XML, binary-ish configs, etc.) — those
|
|
309
|
+
// produce zero explicit candidates and the guard never fired.
|
|
310
|
+
// Using `stagedFromLocalFile` is the reliable signal.
|
|
311
|
+
// Explicit opt-in via `--include-user-scope` still forces it on.
|
|
312
|
+
scan_user_scope: options.includeUserScope === true
|
|
313
|
+
? true
|
|
314
|
+
: resolvedTarget.stagedFromLocalFile === true
|
|
315
|
+
? false
|
|
316
|
+
: (baseConfig.scan_user_scope ?? false),
|
|
300
317
|
};
|
|
301
318
|
if (options.resetState) {
|
|
302
319
|
const reset = deps.resetScanState ?? ((path) => resetScanState(path));
|
|
@@ -78,6 +78,7 @@ export function stageLocalFile(absolutePath) {
|
|
|
78
78
|
scanTarget: tempRoot,
|
|
79
79
|
displayTarget: absolutePath,
|
|
80
80
|
explicitCandidates: collectExplicitCandidates(tempRoot),
|
|
81
|
+
stagedFromLocalFile: true,
|
|
81
82
|
cleanup: () => cleanupTempDir(tempRoot),
|
|
82
83
|
};
|
|
83
84
|
}
|
|
@@ -89,6 +90,7 @@ export function stageLocalFile(absolutePath) {
|
|
|
89
90
|
scanTarget: tempRoot,
|
|
90
91
|
displayTarget: absolutePath,
|
|
91
92
|
explicitCandidates: collectExplicitCandidates(tempRoot),
|
|
93
|
+
stagedFromLocalFile: true,
|
|
92
94
|
cleanup: () => cleanupTempDir(tempRoot),
|
|
93
95
|
};
|
|
94
96
|
}
|
|
@@ -10,6 +10,14 @@ export interface ResolvedScanTarget {
|
|
|
10
10
|
scanTarget: string;
|
|
11
11
|
displayTarget: string;
|
|
12
12
|
explicitCandidates?: ExplicitScanCandidate[];
|
|
13
|
+
/**
|
|
14
|
+
* `true` when the raw input was a local file that got staged into a
|
|
15
|
+
* temp directory. This is the signal the CLI uses to disable the
|
|
16
|
+
* user-scope walk, regardless of whether `explicitCandidates` could be
|
|
17
|
+
* inferred for the file (an XML / binary / unrecognised extension
|
|
18
|
+
* would still benefit from the scope guard).
|
|
19
|
+
*/
|
|
20
|
+
stagedFromLocalFile?: boolean;
|
|
13
21
|
cleanup?: () => Promise<void> | void;
|
|
14
22
|
}
|
|
15
23
|
export interface ResolveScanTargetInput {
|
package/dist/scan.js
CHANGED
|
@@ -148,18 +148,46 @@ function isPathInside(root, candidatePath) {
|
|
|
148
148
|
* User-scope patterns (e.g. `~/.agents/skills/*/SKILL.md`) walk the whole
|
|
149
149
|
* home directory, so they can match files belonging to completely unrelated
|
|
150
150
|
* skills or agents. When the scan target is itself a specific location
|
|
151
|
-
* **inside** the user's home — e.g. scanning a single skill directory
|
|
152
|
-
*
|
|
153
|
-
*
|
|
151
|
+
* **inside** the user's home — e.g. scanning a single skill directory or a
|
|
152
|
+
* single config file like `~/.claude/settings.json` — any user-scope match
|
|
153
|
+
* that does not belong to that target is a cross-scan leak and must be
|
|
154
|
+
* dropped.
|
|
154
155
|
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
156
|
+
* Three cases:
|
|
157
|
+
* - `scanTarget` is a directory inside `homeDir`: only keep candidates inside
|
|
158
|
+
* that directory (existing PR #53 behavior).
|
|
159
|
+
* - `scanTarget` is a file inside `homeDir`: only keep candidates that resolve
|
|
160
|
+
* to that exact file. "Inside" semantics do not apply to files, so the
|
|
161
|
+
* previous check let every sibling through.
|
|
162
|
+
* - `scanTarget` lives outside the home directory (or cannot be stat'd,
|
|
163
|
+
* e.g. a URL or a staged path that has been cleaned up): user-scope
|
|
164
|
+
* matches are accepted as legitimate host-wide context.
|
|
158
165
|
*/
|
|
159
166
|
function shouldKeepUserScopeCandidate(scanTarget, homeDir, candidatePath) {
|
|
160
|
-
if (isPathInside(homeDir, scanTarget)) {
|
|
167
|
+
if (!isPathInside(homeDir, scanTarget)) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
// Follow symlinks the same way the rest of the scan code does (walker,
|
|
171
|
+
// wildcard-base check, `isRegularFile`): `statSync` resolves them. If the
|
|
172
|
+
// target cannot be stat'd (missing / permission denied / URL that was never
|
|
173
|
+
// a local path), fall through to the pre-PR-#53 outside-home behavior so
|
|
174
|
+
// we do not over-filter project-scope scans on unusual inputs.
|
|
175
|
+
let targetStat;
|
|
176
|
+
try {
|
|
177
|
+
targetStat = statSync(scanTarget);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
if (targetStat.isFile()) {
|
|
183
|
+
// Nothing is "inside" a file. The only user-scope candidate that can
|
|
184
|
+
// legitimately belong to a file-target scan is the file itself.
|
|
185
|
+
return resolve(candidatePath) === resolve(scanTarget);
|
|
186
|
+
}
|
|
187
|
+
if (targetStat.isDirectory()) {
|
|
161
188
|
return isPathInside(scanTarget, candidatePath);
|
|
162
189
|
}
|
|
190
|
+
// Sockets, devices, etc. — behave like the outside-home case.
|
|
163
191
|
return true;
|
|
164
192
|
}
|
|
165
193
|
function toUserReportPath(pattern) {
|