Skip to content

Add resource limits to skill packager#32

Merged
rdimitrov merged 1 commit intomainfrom
fix/packager-resource-limits
Feb 19, 2026
Merged

Add resource limits to skill packager#32
rdimitrov merged 1 commit intomainfrom
fix/packager-resource-limits

Conversation

@JAORMX
Copy link
Contributor

@JAORMX JAORMX commented Feb 19, 2026

Summary

The skill packager's collectSkillFiles() function walks a skill directory and reads all file contents into memory before building the OCI artifact. Without limits, a maliciously crafted or excessively large skill directory could exhaust memory during the Build operation exposed via the thv serve API.

The gap

toolhive-core already has comprehensive size limits on the extraction and registry paths:

Limit Value Location Protects
MaxDecompressedSize 100 MB gzip.go Decompression bombs
MaxTarFileSize 100 MB/file tar.go Oversized archive entries
MaxBlobSize 100 MB registry.go Registry push/pull
MaxManifestSize 1 MB registry.go Registry push/pull
maxFrontmatterSize 64 KB packager.go YAML parsing attacks

And toolhive adds extraction-side limits:

Limit Value Location
MaxTotalExtractSize 500 MB installer.go
MaxFileExtractSize 100 MB/file installer.go
MaxExtractFileCount 1,000 files installer.go

However, the packaging (build) side had no file count or aggregate size limit. This meant the memory exhaustion could happen before any of the downstream limits had a chance to trigger.

What this PR adds

Two limits to collectSkillFiles():

  • maxSkillFiles = 1,000 — caps the number of files collected. Aligned with MaxExtractFileCount in toolhive so that anything that can be packaged can also be extracted.
  • maxSkillTotalSize = 100 MB — caps the total aggregate size of all file contents read into memory. Aligned with MaxBlobSize and MaxDecompressedSize in this package.

Both limits are checked incrementally during the directory walk, so the function fails fast without reading the entire directory.

Test plan

  • TestCollectSkillFiles_ExceedsMaxFiles — creates 1,001 files (one over the limit), verifies the error
  • task test — all tests pass (including race detector)
  • task lint — 0 issues

🤖 Generated with Claude Code

The skill packager's collectSkillFiles() function walks a directory and
reads all files into memory. Without limits, a maliciously crafted or
excessively large skill directory could exhaust memory during packaging.

Add two limits to collectSkillFiles():
- maxSkillFiles (1,000): caps the number of files, aligned with the
  extraction-side MaxExtractFileCount in toolhive/pkg/skills/installer.go
- maxSkillTotalSize (100 MB): caps the aggregate size of all file
  contents, aligned with existing blob/decompression limits in this
  package (MaxBlobSize, MaxDecompressedSize)

These limits complement the existing per-file and per-blob limits that
already protect the extraction and registry paths, closing a gap on the
packaging (build) side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rdimitrov rdimitrov merged commit 43aaaf9 into main Feb 19, 2026
5 checks passed
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.

2 participants