T08 · Insecure Dependencies
Error
- Location
- SKILL.md:31
- Finding
- Unpinned Third-Party Mutation Tools Are Downloaded and Executed<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:31`, `SKILL.md:47`, and `SKILL.md:62` **Vulnerability Type**: Unpinned third-party dependency installation and execution **Risk Level**: High ### Vulnerable Code ```bash # SKILL.md:31 npx stryker init 2>/dev/null || npm install --save-dev @stryker-mutator/core ``` ```bash # SKILL.md:47 pip install mutmut 2>/dev/null ``` ```bash # SKILL.md:62 go install github.com/go-gremlins/gremlins/cmd/gremlins@latest ``` ### Technical Analysis The skill directs the agent to retrieve and execute mutation-testing packages without pinning reviewed versions or verifying package integrity: - `npx stryker` can resolve and execute a remotely obtained npm package. It does not specify a reviewed package version. - `npm install --save-dev @stryker-mutator/core` resolves the current package version permitted by the registry rather than a fixed, audited artifact. - `pip install mutmut` installs the currently resolved release and its transitive dependencies without a pinned version or hash. - `go install ...@latest` explicitly downloads and builds the latest available release. Because package contents and dependency resolution can change after the skill has been reviewed, execution of these commands crosses a mutable supply-chain trust boundary. Installation hooks, package entry points, build logic, or the invoked command-line tools can execute code with the permissions of the agent running the skill. Redirecting standard error to `/dev/null` in two commands also suppresses information that could alert the operator to package-resolution failures, warnings, or unexpected installation behavior. ### Attack Path 1. An attacker compromises an upstream package maintainer account, package registry entry, source repository, release process, or transitive dependency. 2. The attacker publishes a malicious version under a package name used by the skill or introduces malicious behavior into a newly resolved dependency. 3. A u ...[truncated 1537 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Pin every tool to a reviewed version** - Use an explicit version for npm packages, Python packages, and Go modules. - Replace `@latest` with a fixed Go module version. - Avoid an unversioned `npx` invocation. 2. **Use lockfiles and immutable installation modes** - Commit and review the relevant lockfile. - For npm-based projects, prefer a project-local dependency installed through `npm ci`. - For Python, use a fully pinned requirements file generated from a reviewed dependency set. - Ensure transitive dependencies are also locked. 3. **Verify package integrity** - Require package hashes where supported, such as `pip install --require-hashes`. - Verify Go module checksums and use trusted module infrastructure. - Retain npm lockfile integrity metadata and reject unexpected lockfile changes. 4. **Separate installation from execution** - Do not automatically install missing mutation tools during a normal skill run. - Detect whether an approved local tool is available and request explicit user confirmation before any network retrieval or installation. - Clearly display the package name, source, and exact version before installation. 5. **Run third-party tools in a restricted environment** - Use a disposable container, sandbox, or temporary worktree. - Provide only the repository access required for mutation testing. - Remove unnecessary credentials and sensitive environment variables. - Restrict outbound network access during tool execution where practical. 6. **Preserve diagnostic output** - Do not suppress package-manager errors with `2>/dev/null`. - Surface resolution warnings, integrity failures, and installation scripts to the operator. Example hardened patterns should use organization-approved fixed versions rather than `latest` or other floating constraints: ```bash # Use an approved, exact version and a committed lockfile. npm ci npx --no-install stryker run ...[truncated 314 chars]
