A valid skill archive named skill.zip is unpacked, but renaming that same archive to skill.ZIP or skill.ZiP makes SkillSpector treat it as an ordinary file. The contained SKILL.md is therefore not exposed for scanning.
This occurs for local inputs and for supported file URLs when the server supplies a generic content type, such as application/octet-stream.
Reproduction
On main at 4a5506276795397c62ed4f0111c08f41c2b9f1b1, run this from an environment with SkillSpector installed:
import tempfile
import zipfile
from pathlib import Path
from skillspector.input_handler import InputHandler
with tempfile.TemporaryDirectory() as directory:
for extension in (".zip", ".ZIP", ".ZiP"):
archive = Path(directory) / f"skill{extension}"
with zipfile.ZipFile(archive, "w") as zf:
zf.writestr("SKILL.md", "# Skill")
handler = InputHandler()
try:
resolved, source_type = handler.resolve(str(archive))
print(extension, source_type, (resolved / "SKILL.md").is_file())
finally:
handler.cleanup()
Expected: all three inputs resolve as zip and contain an extracted SKILL.md.
Actual:
.zip zip True
.ZIP file False
.ZiP file False
InputHandler.resolve, _download_file, and _download_transitive_file each use a case-sensitive .endswith(".zip") check. Making those extension checks case-insensitive would allow the same archive to be processed consistently regardless of extension capitalization.
A valid skill archive named
skill.zipis unpacked, but renaming that same archive toskill.ZIPorskill.ZiPmakes SkillSpector treat it as an ordinary file. The containedSKILL.mdis therefore not exposed for scanning.This occurs for local inputs and for supported file URLs when the server supplies a generic content type, such as
application/octet-stream.Reproduction
On main at
4a5506276795397c62ed4f0111c08f41c2b9f1b1, run this from an environment with SkillSpector installed:Expected: all three inputs resolve as
zipand contain an extractedSKILL.md.Actual:
InputHandler.resolve,_download_file, and_download_transitive_fileeach use a case-sensitive.endswith(".zip")check. Making those extension checks case-insensitive would allow the same archive to be processed consistently regardless of extension capitalization.