File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -14,8 +14,11 @@ export function listSkills(): string[] {
1414}
1515
1616export function loadSkill ( name : string ) : string {
17- const resolved = resolve ( SKILLS_DIR , `${ name } .txt` ) ;
18- if ( ! resolved . startsWith ( resolve ( SKILLS_DIR ) + "/" ) ) {
17+ const root = resolve ( SKILLS_DIR ) ;
18+ const resolved = resolve ( root , `${ name } .txt` ) ;
19+ // Compare directories rather than a "/" prefix so the check also holds
20+ // for the backslash paths that resolve() returns on Windows.
21+ if ( dirname ( resolved ) !== root ) {
1922 throw new Error ( `Invalid skill name: ${ name } ` ) ;
2023 }
2124 return readFileSync ( resolved , "utf-8" ) ;
Original file line number Diff line number Diff line change 11import { describe , it , expect } from "vitest" ;
2- import { listSkills } from "../src/skills" ;
2+ import { listSkills , loadSkill } from "../src/skills" ;
33
44describe ( "listSkills" , ( ) => {
55 it ( "returns an array containing the bundled skills" , ( ) => {
@@ -8,3 +8,16 @@ describe("listSkills", () => {
88 expect ( skills ) . toContain ( "master-agent-playbook" ) ;
99 } ) ;
1010} ) ;
11+
12+ describe ( "loadSkill" , ( ) => {
13+ it ( "loads a bundled skill by name" , ( ) => {
14+ expect ( loadSkill ( "master-agent-playbook" ) . length ) . toBeGreaterThan ( 0 ) ;
15+ } ) ;
16+
17+ it . each ( [ "../package" , "nested/skill" , "/etc/passwd" ] ) (
18+ "rejects names outside the skills directory: %s" ,
19+ ( name ) => {
20+ expect ( ( ) => loadSkill ( name ) ) . toThrow ( "Invalid skill name" ) ;
21+ }
22+ ) ;
23+ } ) ;
You can’t perform that action at this time.
0 commit comments