Skip to content

chore(security): move artifact filename path-safety to schema layer (consistency) #97

@mgoldsborough

Description

@mgoldsborough

Observation

`apps/registry/src/routes/v1/bundles.ts:133` defines `validateArtifactFilename` as an ad-hoc per-route check. The equivalent skill filename in `SkillArtifactSchema` (`packages/schemas/src/skill.ts:100`) only enforces `.skill` extension via regex — no path-traversal guard.

Current state:

  • Bundle artifact filename: route-level validation, schema only requires non-empty string
  • Skill artifact filename: no path-safety validation; only the extension regex

Inconsistent and out of step with the post-PR-#94 pattern (which moved `entry_point` validation to the schema layer).

Risk

Currently non-exploitable for skills:

  • Filename is matched against `release.assets[*].name` (GitHub doesn't put path separators in asset names)
  • File is downloaded to a `randomUUID()`-named temp path, so traversal can't write outside the temp dir

But:

Proposed approach

Define `SafeFilenameSchema` in `packages/schemas` (similar to but stricter than `SafeRelativePathSchema` — also forbids `/` and `\` since a filename has no path separators). Apply to both bundle announce artifacts and `SkillArtifactSchema.filename`.

Remove the ad-hoc `validateArtifactFilename` in `bundles.ts:133`.

Acceptance criteria

  • New `SafeFilenameSchema` exported from `@nimblebrain/mpak-schemas`
  • `SkillArtifactSchema.filename` uses it
  • Bundle announce artifact filename uses it (route-level helper removed or trivial wrapper)
  • Tests cover the standard rejection cases

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions