11import { mkdir , readFile , rename , writeFile } from "node:fs/promises" ;
22import { homedir } from "node:os" ;
3- import { dirname , join , resolve } from "node:path" ;
3+ import { dirname , isAbsolute , join , resolve } from "node:path" ;
44import { createHash } from "node:crypto" ;
55import { type } from "arktype" ;
66import { getLogger } from "@intx/log" ;
@@ -142,10 +142,22 @@ export async function readProjectTrustStore(
142142 logger . warn `project trust store repo mismatch at ${ path } : recorded ${ validated . repo } , expected ${ resolve ( cwd ) } ` ;
143143 return { state : "invalid" , store : emptyStore ( ) } ;
144144 }
145+ // Grants are recorded as absolute paths (see requireAbsolute below); a
146+ // relative entry has no fixed meaning on load — resolving it here would
147+ // bind to whatever process.cwd() happens to be, the same confused-cwd bug
148+ // path-trust.ts guards against on disk. Drop it instead of guessing.
149+ const absolutePluginPaths : string [ ] = [ ] ;
150+ for ( const p of trustedPluginPaths ) {
151+ if ( ! isAbsolute ( p ) ) {
152+ logger . warn `project trust store dropping non-absolute trustedPluginPaths entry at ${ path } : ${ p } ` ;
153+ continue ;
154+ }
155+ absolutePluginPaths . push ( resolve ( p ) ) ;
156+ }
145157 return {
146158 state : "valid" ,
147159 store : {
148- trustedPluginPaths : trustedPluginPaths . map ( ( p ) => resolve ( p ) ) ,
160+ trustedPluginPaths : absolutePluginPaths ,
149161 trustedMcpFingerprints : [ ...trustedMcpFingerprints ] ,
150162 } ,
151163 } ;
@@ -185,8 +197,19 @@ function enqueueMutation<T>(key: string, run: () => Promise<T>): Promise<T> {
185197 return next ;
186198}
187199
188- export function isPluginTrusted ( store : ProjectTrustStore , pluginPath : string ) : boolean {
189- const abs = resolve ( pluginPath ) ;
200+ // A relative pluginPath has no fixed meaning until resolved against some cwd;
201+ // resolving it against process.cwd() (path.resolve's default) would trust a
202+ // different directory than the caller's project, the confused-cwd bug
203+ // path-trust.ts avoids by requiring absolute paths outright. Project trust
204+ // callers pass relative paths in practice, so resolve against the given
205+ // project cwd instead of rejecting — path.resolve(cwd, pluginPath) leaves an
206+ // already-absolute pluginPath untouched.
207+ function resolveAgainstProjectCwd ( cwd : string , pluginPath : string ) : string {
208+ return resolve ( cwd , pluginPath ) ;
209+ }
210+
211+ export function isPluginTrusted ( store : ProjectTrustStore , pluginPath : string , cwd : string = process . cwd ( ) ) : boolean {
212+ const abs = resolveAgainstProjectCwd ( cwd , pluginPath ) ;
190213 return store . trustedPluginPaths . includes ( abs ) ;
191214}
192215
@@ -195,7 +218,7 @@ export async function trustPlugin(
195218 pluginPath : string ,
196219 home : string = homedir ( ) ,
197220) : Promise < ProjectTrustStore > {
198- const abs = resolve ( pluginPath ) ;
221+ const abs = resolveAgainstProjectCwd ( cwd , pluginPath ) ;
199222 return enqueueMutation ( projectTrustPath ( cwd , home ) , async ( ) => {
200223 const store = await loadProjectTrust ( cwd , home ) ;
201224 if ( ! store . trustedPluginPaths . includes ( abs ) ) {
0 commit comments