MCPcopy Index your code
hub / github.com/coder/mux / validateLocalSkillDirectory

Function validateLocalSkillDirectory

src/node/services/tools/skillFileUtils.ts:177–200  ·  view source on GitHub ↗
(
  containmentRoot: string,
  skillDir: string
)

Source from the content-addressed store, hash-verified

175 * Throws a descriptive error string on any violation.
176 */
177export async function validateLocalSkillDirectory(
178 containmentRoot: string,
179 skillDir: string
180): Promise<{ skillDirStat: Stats | null }> {
181 // 1) Reject symlinked skills root
182 const skillsRoot = path.dirname(skillDir);
183 const skillsRootStat = await lstatIfExists(skillsRoot);
184 if (skillsRootStat?.isSymbolicLink()) {
185 throw new Error(
186 "Skills root directory is a symbolic link and cannot be used for skill operations."
187 );
188 }
189
190 // 2) Reject symlinked skill directory
191 const skillDirStat = await lstatIfExists(skillDir);
192 if (skillDirStat?.isSymbolicLink()) {
193 throw new Error("Skill directory is a symlink (symbolic link) and cannot be modified.");
194 }
195
196 // 3) Verify realpath stays under containmentRoot (even for missing dirs via allow-missing resolution)
197 await ensurePathContained(containmentRoot, skillDir, { allowMissing: true });
198
199 return { skillDirStat };
200}
201
202/** Canonical filename for the skill definition file. */
203export const SKILL_FILENAME = "SKILL.md";

Callers 2

Calls 2

lstatIfExistsFunction · 0.85
ensurePathContainedFunction · 0.85

Tested by

no test coverage detected