Skip to content

feat(tasks): bundle local skills into sha256-verified zip artifacts#2923

Open
tatoalo wants to merge 1 commit into
local-skill-01-contractsfrom
local-skill-02-bundler
Open

feat(tasks): bundle local skills into sha256-verified zip artifacts#2923
tatoalo wants to merge 1 commit into
local-skill-01-contractsfrom
local-skill-02-bundler

Conversation

@tatoalo

@tatoalo tatoalo commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

for cloud tasks, local skill invocations only sent the slash command text. User-local and repo-local skills were available in the local editor but not in the cloud sandbox

Changes

  • let's bundle uploadable local skills into zip artifacts with SHA-256 metadata and send them through the existing cloud artifact upload flow.

  • install skill_bundle artifacts in the agent server before prompt delivery, inject the bundled skill instructions for the invoked turn, and suppress the raw slash command from the model-facing prompt so local skills behave like actual skills rather than unsupported commands

  • refresh slash command metadata when a follow-up command is submitted, so newly created local skills can be selected and invoked without starting a brand-new task.

closes #2260

tatoalo commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit e8dec75.

@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "feat(tasks): bundle local skills into sh..." | Re-trigger Greptile

Comment thread packages/workspace-server/src/services/skills/skill-bundler.ts Outdated
Comment thread packages/workspace-server/src/services/skills/skill-bundler.ts Outdated
Comment thread packages/workspace-server/src/services/skills/skill-bundler.ts
@tatoalo tatoalo force-pushed the local-skill-02-bundler branch from 259d373 to e8dec75 Compare June 25, 2026 09:48
@tatoalo tatoalo force-pushed the local-skill-01-contracts branch from bf42454 to b44c3b4 Compare June 25, 2026 09:48
@tatoalo tatoalo self-assigned this Jun 25, 2026
@tatoalo tatoalo requested a review from a team June 25, 2026 10:41
@tatoalo tatoalo marked this pull request as ready for review June 25, 2026 10:41
@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Security Review

  • Arbitrary filesystem read via unguarded skillPath (packages/workspace-server/src/services/skills/skills.ts): The new bundleLocalSkill method omits the resolveKnownSkillDir check that every other skill-path consumer in the file applies. This check is the documented defense against turning the endpoint into an arbitrary filesystem read. Any caller who can reach the tRPC port can provide any path that contains a SKILL.md and receive the full directory contents as a base64-encoded zip.

Reviews (2): Last reviewed commit: "feat(tasks): bundle local skills into sh..." | Re-trigger Greptile

Comment on lines +492 to +499
bundleLocalSkill(
input: BundleLocalSkillInput,
): Promise<BundleLocalSkillOutput> {
return bundleLocalSkill({
name: input.name,
source: input.source,
skillPath: input.path,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Missing resolveKnownSkillDir guard allows arbitrary filesystem bundling

Every other method that accepts a skillPathgetSkillContents, readSkillFile, saveSkillManifest, etc. — first passes it through resolveKnownSkillDir (or resolveWritableSkillDir), which validates that the path sits under a known skill root. That guard's own comment says "This keeps the contents/readFile endpoints from becoming arbitrary-filesystem reads." bundleLocalSkill skips that guard entirely, so any caller can provide an arbitrary path (e.g. ~/.ssh) containing a SKILL.md and receive the full directory base64-encoded in the response. The fix is to call resolveKnownSkillDir on input.path before forwarding it to the bundler.

Rule Used: When implementing new features, ensure that owners... (source)

Learned From
PostHog/posthog#31236

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant