T03 · Remote Payload Retrieval and Execution
Error
- Location
- README.md:123
- Finding
- Unauthenticated Mutable Remote Wrapper Is Downloaded and Executed## Vulnerability Details **File Location**: `README.md:123-138` and `references/standalone-verification.md:9-24` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: High ### Vulnerable Code `README.md:123-138`: ```shell If the plugin is not installed, use the repository's standalone wrapper. It checks the canonical validator against a pinned SHA-256 before running it, so the digest rather than a mutable version label controls execution. Literal ```shell curl -fsSLo /tmp/skill-provenance-verify.sh https://skillprovenance.dev/verify.sh sed -n '1,220p' /tmp/skill-provenance-verify.sh ``` Replace: TARGET_SKILL_DIRECTORY -> the local directory containing `SKILL.md` and `MANIFEST.yaml` Customize ```shell bash /tmp/skill-provenance-verify.sh TARGET_SKILL_DIRECTORY ``` ``` `references/standalone-verification.md:9-24`: ```shell Download and inspect the wrapper before running it. Literal ```shell curl -fsSLo /tmp/skill-provenance-verify.sh https://skillprovenance.dev/verify.sh sed -n '1,220p' /tmp/skill-provenance-verify.sh ``` Replace: TARGET_SKILL_DIRECTORY -> the local directory containing `SKILL.md` and `MANIFEST.yaml` Customize ```shell bash /tmp/skill-provenance-verify.sh TARGET_SKILL_DIRECTORY ``` Exit code `0` means every pinned file is present and matches. Exit code `1` means the manifest is invalid, a file is missing, or a hash mismatches. Exit code `2` means the target has no `MANIFEST.yaml`. ``` ### Technical Analysis The documented workflow downloads a shell script from the mutable URL `https://skillprovenance.dev/verify.sh` and subsequently executes that script with Bash. The downloaded wrapper itself is not authenticated using a locally trusted SHA-256 digest or a verified digital signature before execution. Although the documentation states that the wrapper verifies a downstream validator against a pinned digest, that protecti ...[truncated 2731 chars]
- Remediation
- ## Remediation Suggestions 1. **Authenticate the wrapper before execution.** Publish a SHA-256 digest through a separately trusted, immutable release channel and compare the downloaded wrapper against a hard-coded expected value before invoking Bash: ```shell wrapper="$(mktemp)" trap 'rm -f "$wrapper"' EXIT curl -fL --proto '=https' --tlsv1.2 \ -o "$wrapper" \ "https://example.invalid/releases/download/v6.3.0/skill-provenance-verify.sh" expected="REPLACE_WITH_REVIEWED_64_CHARACTER_SHA256" actual="$(sha256sum "$wrapper" | awk '{print $1}')" if [ "$actual" != "$expected" ]; then echo "Wrapper integrity verification failed" >&2 exit 1 fi bash "$wrapper" TARGET_SKILL_DIRECTORY ``` On macOS, use `shasum -a 256` or provide a portable verification procedure. 2. **Use an immutable source.** Fetch the wrapper from an exact release artifact or content-addressed object rather than an unversioned `verify.sh` endpoint. A versioned URL alone is insufficient unless its bytes are also authenticated. 3. **Prefer shipping the wrapper in the audited bundle.** Include the verifier as a manifest-listed file with a recorded SHA-256 digest so its contents are available during review and do not change after publication. 4. **Use signed releases where practical.** Sign release artifacts with a documented verification key or use a transparent signing system such as Sigstore. Verification must occur locally before execution. 5. **Fail closed.** Do not invoke the wrapper if downloading, digest verification, or signature verification fails. Do not fall back to a mutable remote copy. 6. **Avoid predictable temporary paths.** Use `mktemp`, quote every path, apply restrictive permissions where needed, and remove the temporary file with a cleanup trap. 7. **Retain manual inspection only as defense in depth.** If ...[truncated 385 chars]
