mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Preserve filesystem authority when loading skills (#59279)
## Why Skill discovery and metadata loading used raw filesystem handles with unrestricted reads, and cache keys distinguished filesystems without accounting for captured permissions. ## What changed - Pass borrowed `EnvironmentAccess` accessors through skill root resolution, discovery, canonicalization, and metadata reads. - Include captured permissions in skill snapshot and empty remote root cache keys. - Add fixed-path watches to `EnvironmentAccess`, falling back to live discovery when read restrictions prevent using unsandboxed executor watches. - Keep user and plugin roots under host filesystem authority independently of the selected repository executor. ## Testing Extend remote root cache coverage to verify that changing captured permissions triggers a fresh scan and that restricted accessors decline unsandboxed watches. GitOrigin-RevId: 97d4bfdfcba78a93fc8845773c6397d4364494e3
This commit is contained in:
committed by
copyberry
parent
afefd0ba95
commit
526f6099f6
@@ -27,11 +27,21 @@ use std::sync::Weak;
|
||||
/// Filesystem operations authorized by the environment that supplied this borrowed accessor.
|
||||
///
|
||||
/// Callers cannot extract the underlying filesystem or choose another sandbox. They may retain
|
||||
/// returned data, cache keys, and already-opened read streams after the accessor is gone.
|
||||
/// returned data, cache keys, opened read streams, and fixed-path watches after the accessor is gone.
|
||||
pub trait EnvironmentAccess: Send + Sync {
|
||||
/// Identifies the filesystem and captured permissions without granting access to either.
|
||||
fn cache_key(&self) -> EnvironmentAccessKey;
|
||||
|
||||
/// Registers an owned watch for these fixed paths, or returns `None` when unsupported.
|
||||
/// Implementations must preserve captured read permissions when checking the observation.
|
||||
fn watch_missing(
|
||||
&self,
|
||||
_missing: Vec<PathUri>,
|
||||
_present: Option<PathUri>,
|
||||
) -> ExecutorFileSystemFuture<'static, Option<tokio::sync::oneshot::Receiver<()>>> {
|
||||
Box::pin(async { Ok(None) })
|
||||
}
|
||||
|
||||
fn canonicalize<'a>(&'a self, path: &'a PathUri) -> ExecutorFileSystemFuture<'a, PathUri>;
|
||||
|
||||
fn read_file<'a>(
|
||||
@@ -201,6 +211,26 @@ impl<'environment> FileSystemEnvironmentAccessor<'environment> {
|
||||
}
|
||||
|
||||
impl EnvironmentAccess for FileSystemEnvironmentAccessor<'_> {
|
||||
fn watch_missing(
|
||||
&self,
|
||||
missing: Vec<PathUri>,
|
||||
present: Option<PathUri>,
|
||||
) -> ExecutorFileSystemFuture<'static, Option<tokio::sync::oneshot::Receiver<()>>> {
|
||||
// Executor watches make unsandboxed observations, so restricted reads use live discovery.
|
||||
if self
|
||||
.key
|
||||
.sandbox
|
||||
.as_ref()
|
||||
.is_some_and(|sandbox| sandbox.should_read_from_sandbox())
|
||||
{
|
||||
return Box::pin(async { Ok(None) });
|
||||
}
|
||||
let Some(file_system) = self.key.file_system.upgrade() else {
|
||||
return Box::pin(async { Ok(None) });
|
||||
};
|
||||
Box::pin(async move { file_system.watch_missing(missing, present).await })
|
||||
}
|
||||
|
||||
fn cache_key(&self) -> EnvironmentAccessKey {
|
||||
self.key.clone()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user