Skip to content

Latest commit

 

History

History
122 lines (98 loc) · 6.67 KB

NESTED_ARTIFACT_INSPECTION.md

File metadata and controls

122 lines (98 loc) · 6.67 KB

Nested Artifact Inspection

SkillSpector inventories hidden regular files and inspects ZIP-compatible content locally. The container is recognized from its bytes and internal structure rather than its filename extension. Supported document containers are DOCX, XLSX, and PPTX; generic ZIP and nested ZIP-compatible members use the same traversal policy.

Nested members use a stable virtual path that retains their full provenance:

outer-file!/nested.zip!/scripts/setup.sh

JSON component locations

JSON component rows preserve this virtual path in path, matching finding locations and inspection-ledger entries. Archive members also expose their existing inventory provenance:

{
  "path": "bundle.whl!/package/module.py",
  "type": "python",
  "executable": true,
  "outer_path": "bundle.whl",
  "nested_path": "package/module.py",
  "container_type": "zip",
  "container_ancestry": ["zip"],
  "container_depth": 1
}

outer_path names the physical container relative to that component's source root. nested_path retains the full member chain inside it, including any nested !/ boundaries. Each member keeps its own component row, executable flag, type, line count, and byte size. Ordinary files do not gain archive fields merely because their names contain !/.

Consumers must distinguish a virtual member from an on-disk file: executable: true describes the member's content, not the existence of its virtual path on disk. Use the source identity and full path to join components with findings; do not collapse members by outer_path. When validating a report, check archive provenance and containment within the corresponding source root, and retain incomplete-inspection failures. These additive fields do not change existing consumer validators automatically, prove that every member was inspected, or justify extracting or executing archive content.

Security invariants

  • Members are read in memory. SkillSpector never extracts, renders, imports, installs, or executes archive content.
  • Absolute paths, parent traversal, drive-qualified paths, and link members are not followed.
  • Hidden files, recognized containers, and all nested content are local-only and are never included in an external LLM request.
  • Deterministic HIGH findings survive optional LLM meta-analysis.
  • A zero-finding result does not make opaque or uninspected content complete.

Cumulative bounds

Archive inspection uses one shared budget for the whole skill bundle. Opening another outer container does not reset the member, expanded-byte, or time budget. The bundle scanner may pass a smaller remaining artifact or byte allowance, and its deadline always takes precedence.

Bound Limit Scope
Container depth 3 One outer-to-inner provenance chain
Members 1,000 All outer and recursively nested containers combined
Expanded member bytes 25 MiB All outer and recursively nested containers combined
Central directory 4 MiB Each container, checked before creating ZIP metadata objects
Materialized member 1,000,000 bytes Each member
Compression ratio 100:1 Each member
Inspection wall time 5 seconds All outer and recursively nested containers combined

The 1,000-member and 25 MiB ceilings are also reduced to the bundle scanner's remaining 10,000-artifact and 64 MiB canonical-byte budgets. Nested members therefore cannot obtain a fresh allowance after ordinary files have consumed part of the bundle budget.

Before Python's ZIP reader is invoked, SkillSpector validates the terminal EOCD or ZIP64 records, the declared central-directory count and byte size, and the actual sequence of central-directory headers. This preflight prevents a forged entry count from causing an unbounded metadata list. Already-bounded outer bytes are reused from the bundle cache instead of being read a second time.

These are resource-safety limits, not trust configuration. They are intentionally not user-managed allowlists. See Analysis Resource Bounds for the enclosing bundle, parser, ledger, and finding ceilings.

Failure and completeness behavior

Malformed, encrypted, truncated, unreadable, unsafe-path, link, unsupported, and over-budget members are recorded as inspection-ledger exceptions. Readable members retain their exact raw bytes and a local-only decoded view. Unreadable members retain an opaque inventory record with a partial or failed disposition; they are never represented as successfully analyzed.

The scan continues safely when possible, but any relevant omitted or partially inspected content makes the analysis incomplete. A result that would otherwise be SAFE is reported as at least CAUTION; the MCP verdict sets safe_to_install to false. CLI users can make incomplete analysis a failing gate with --fail-on-incomplete. Inspection exceptions and their affected outer or nested paths are surfaced in terminal, JSON, Markdown, and SARIF output.

If a real disk path containing !/ has the same identity as an archive member, the scan records artifact_path_collision, retains the disk bytes, and withholds the archive member. This fails the scan (CLI exit 2 and MCP safe_to_install=false). Rename the disk directory ending in ! to remove the ambiguity. Non-colliding directory names ending in ! remain valid. The colliding member file is withheld; distinct descendant members still receive analysis. Exceptions for that withheld file or a skipped duplicate descendant are reported against its archive container. Disk format and malformed-container errors stay on the disk file, and an analyzed disk descendant is not marked partial merely because the archive copy was skipped.

SC9: Concealed Executable Artifact

SC9 is a deterministic HIGH finding when executable content is concealed inside an Office document container or a hidden/disguised artifact. Executability is established from an executable suffix, a shebang, or archive mode bits. A benign document without executable members does not produce SC9.

SC9 reports evidence and risk; it does not execute the member or prescribe an installation decision.

At the scan root, visible source scripts beneath .agents/skills/<name>/ and .claude/skills/<name>/ are not treated as concealed when that skill directory contains a regular SKILL.md or skill.md manifest. These paths remain hidden and local-only: their contents are not sent to an external LLM. When LLM analysis is enabled, the inspection ledger records that LLM review was withheld, so the report does not imply that those scripts received semantic review. This narrow exception does not cover hidden skill names, hidden descendants, mismatched shebangs, unsupported script types, or nested client directories.