Back to skill

Security audit

Code QC

Security checks for vulnerabilities and agentic risk

Overview

This code-quality audit skill is useful, but it can execute project code and unpinned external tools during audits without clear sandboxing or approval boundaries.

Install only if you will run it on trusted repositories or inside a disposable, network-restricted environment with no secrets. Treat test, import, build, smoke-test, npx, pip install, and --fix steps as active code execution or mutation, and require an explicit review before allowing those steps.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/import_check.py:179
Finding
Audited Python Modules Execute In-Process Without Isolation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/import_check.py:179-200` **Vulnerability Type**: Unsafe execution of untrusted project code **Risk Level**: High ### Vulnerable Code ```python # Try to import the base package first try: importlib.import_module(package_name) except ImportError as e: results.failed.append( ImportFailure( module=package_name, error=str(e), error_type=type(e).__name__, is_critical=True, ) ) return results for modname, _ispkg in walk_package_modules(package_name, exclude): # Check if excluded if any( f"{package_name}.{ex}." in modname or modname == f"{package_name}.{ex}" for ex in exclude ): results.skipped.append(modname) continue results.total += 1 try: importlib.import_module(modname) ``` The package is also imported while discovering modules: ```python def walk_package_modules( package_name: str, exclude: list[str] ) -> Iterator[tuple[str, bool]]: """Yield (module_name, is_pkg) for all modules in a package.""" try: pkg = importlib.import_module(package_name) except ImportError as e: logger.error(f"Cannot import base package {package_name}: {e}") return ``` ### Technical Analysis `importlib.import_module()` does not merely validate import declarations. It executes all module-level Python code, including package initializers, decorators, registration hooks, and other import-time behavior. The checker imports the audited package and every discovered submodule directly inside the auditor process. It applies no process isolation, filesystem restriction, network restriction, environment-variable filtering, timeout, or privilege reduction. Exception handling only catches failures after module code has already executed and does not prevent side effects. Consequently, an untrusted repository can use ordinary import-time code to execute arb ...[truncated 1648 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Do not import untrusted project modules in the main Agent process.** Prefer static analysis of Python source and import declarations whenever runtime initialization is not essential. 2. When runtime import verification is required, run it in a disposable sandbox or container with: - No inherited secrets or credential-related environment variables. - Outbound network access disabled by default. - A read-only project mount. - A separate temporary writable directory. - No access to the host home directory or sensitive sockets. - A low-privilege, non-root user. - CPU, memory, process, and execution-time limits. 3. Import each module in a separate subprocess so a timeout, crash, or process-state modification cannot compromise the main auditor. 4. Require explicit user approval before executing code from an untrusted repository and clearly disclose that Python imports execute initialization code. 5. Record and report blocked filesystem, process, and network activity as audit findings rather than permitting those operations. 6. Avoid importing the base package twice during discovery and checking. ]]>

T08 · Insecure Dependencies

Warning
Location
references/typescript-profile.md:34
Finding
Unpinned Registry Packages May Be Downloaded and Executed During Audits<![CDATA[ ## Vulnerability Details **File Location**: `references/typescript-profile.md:34-38` **Additional Locations**: `SKILL.md:80,128,143,164`; `references/python-profile.md:126`; `references/gdscript-profile.md:18`; `references/typescript-profile.md:54,68-69,81-92,104-153,223-287,299-302` **Vulnerability Type**: Unpinned dependency retrieval and execution **Risk Level**: Medium ### Vulnerable Code ```bash ### Nx if [ -f "nx.json" ]; then echo "Nx monorepo detected" # List projects npx nx show projects fi ``` Other representative instructions include: ```bash pip install ruff pip install gdtoolkit npx eslint . --format json npx tsc --noEmit ``` The CLI smoke-test example also delegates execution through `npx`: ```typescript import { execSync } from 'child_process'; function smokeTestCli() { const output = execSync('npx my-cli --help', { encoding: 'utf8' }); if (!output.includes('Usage:')) throw new Error('CLI help failed'); return 'PASS'; } ``` ### Technical Analysis The Skill repeatedly invokes `npx` without an offline-only policy, explicit package version, integrity constraint, or verification that the executable came from the audited project's lockfile. When a requested executable is absent locally, `npx` can resolve and download registry content before executing it. The Python and GDScript profiles similarly recommend direct `pip install` commands without pinned versions or hashes. Package installation and executable startup can run attacker-controlled package code, including lifecycle hooks and command entry points. This creates a supply-chain execution boundary in which the effective code may change after the Skill has been reviewed. The risk is increased by the generic `npx my-cli --help` example because a placeholder or mismatched package name could resolve to an unrelated public registry package. ### Attack Path 1. A tool requested by the audit is not installed in the local project, or local package resolution does n ...[truncated 1238 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use only dependencies already declared and locked by the audited project. 2. For Node.js tools: - Prefer direct local binaries under `node_modules/.bin`. - Use package-manager commands that prohibit downloads, such as an offline-only or equivalent policy. - Validate that the requested package appears in `package.json` and the lockfile before execution. - Use exact versions when a temporary tool is unavoidable. - Disable lifecycle scripts where compatible with the tool. 3. For Python tools: - Pin exact versions. - Install from a reviewed constraints or requirements file. - Require cryptographic hashes with `--require-hashes`. - Install into an isolated disposable environment rather than the user's active environment. 4. Remove or replace the generic `npx my-cli --help` example. Invoke a verified project-local CLI through the project's declared script instead. 5. Require user approval before downloading any dependency during an audit. 6. Run third-party tooling in the same network-restricted, secret-free sandbox recommended for target-project execution. 7. Record tool versions, package sources, and lockfile integrity in the generated audit report to make results reproducible. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (44)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is a clear description-behavior mismatch. The code chunk implements a specific documentation linting tool, not a comprehensive code quality audit system. Its primary purpose is to detect missing docstrings in Python modules/classes/functions using AST traversal. While docstring checking is loosely related to documentation quality, it represents only one small subset of the declared QC scope. The code does not inspect tests, imports, typing, static analysis results, or smoke tests; it does not support TypeScript or GDScript; it does not produce PASS/WARN/FAIL verdicts; and it does not compare results over time. No concerning undeclared sensitive capability is present, but the declared purpose materially overstates and misrepresents the actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The code chunk does only one limited task: checking whether Python package modules can be imported. While import checking is one component mentioned in the description, the declared purpose presents this skill as a comprehensive multi-language QC/audit tool with reporting across several categories and temporal comparison support. None of those broader audit capabilities appear in this code. The primary purpose of the supplied code is materially narrower than the declared description, so this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description describes a broad, structured code quality auditing tool for multiple languages and multiple QC dimensions. The supplied code only checks Python files for syntax errors using py_compile. While syntax checking could be one small component of a QC workflow, this implementation lacks nearly all of the claimed functionality and has a materially narrower primary purpose. There is no evidence of test execution, import validation, type checking, static analysis, smoke testing, documentation checks, multi-language support, or longitudinal comparison features. Therefore the description substantially overstates the behavior, making this a clear mismatch.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill describes file-reading and project-audit behavior but does not declare any explicit tool scope or permissions boundaries. In an agent environment, that increases the risk of over-broad file access and makes it harder to constrain what parts of a repository or host filesystem the skill may inspect.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The activation description uses broad phrases like QC, audit, review, or check code quality, which can cause the skill to trigger in situations the user did not intend. Because this skill includes code execution, file reads, and possible write behaviors, accidental activation expands the chance of unreviewed actions on sensitive repositories.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The skill is presented as an audit tool but includes mutation behaviors such as autofixing code and writing baseline/report files. That scope expansion is dangerous because users may invoke a seemingly read-only review skill and unknowingly allow source changes or filesystem writes.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill documents automatic fixes and baseline/report file writes without a clear upfront warning that project files may be modified. In practice, that can lead to integrity issues, unexpected diffs, or accidental persistence in repositories where the user expected analysis only.

Rp1

Medium
Category
MCP Rug Pull
Confidence
86% confidence
Finding
Invoking `npx vitest` without pinning a specific version makes execution dependent on the local or remotely resolved package version at runtime. This creates a supply-chain risk where behavior can change unexpectedly or a compromised package version could be executed during QC.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding
Using `npx eslint` without a pinned version allows execution of whatever version is locally installed or fetched at runtime. That introduces nondeterminism and a supply-chain execution path in a skill that may run automatically against arbitrary projects.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
Auto-fix mode rewrites source files as part of a skill whose primary purpose is QC review. This is dangerous because it changes repository state, may introduce unintended modifications, and could be abused if triggered in contexts where users expected a non-destructive audit.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding
The fix-mode command `npx eslint . --fix` combines unpinned dependency resolution with source-code rewriting. If the resolved package version is altered or malicious, the skill could both execute unexpected code and modify repository contents.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding
Running `npx tsc --noEmit` without version pinning exposes the audit flow to dependency-resolution drift and possible execution of an untrusted compiler version. Even without writing output, this still executes code from the JavaScript toolchain in the target environment.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The smoke-test phase instructs the agent to generate and execute project-specific code against application logic. In the context of auditing arbitrary repositories, dynamic execution materially increases risk because imports, constructors, and method calls can trigger untrusted code paths, side effects, network access, or destructive operations.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
The profile instructs users to run `npx eslint --version`, which can cause `npx` to fetch and execute an unpinned package from the registry when ESLint is not already installed locally. In a QC/audit skill, this is risky because the skill is likely to be run against arbitrary repositories and environments, increasing the chance of unintended network access or execution of a substituted package version.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
The profile instructs use of `npx nx` without pinning a version, which can resolve and execute whatever version is available from the project or registry at runtime. In a QC skill, this creates a supply-chain execution risk because the skill may run unreviewed tooling during analysis rather than using a fixed, trusted version.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
Using `npx lerna` without an exact version allows runtime resolution of an arbitrary package version, potentially fetching and executing code from the registry. Because this skill is meant for quality control, not package acquisition, the command expands the trust boundary and introduces supply-chain risk.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
The unpinned `npx nx` command may execute a version selected at runtime, which can differ across environments or be sourced from the network. This is risky in an agent skill because simply auditing a codebase can trigger execution of untrusted tooling.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
Another unpinned `npx nx` invocation appears in the profile and carries the same supply-chain and arbitrary-tooling risk. In monorepo QC, affected-target commands may also traverse large parts of the repository, increasing the blast radius of any malicious script or compromised package.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
`npx turbo run lint test` is unpinned and may download or execute an unexpected `turbo` version at runtime. This creates reproducibility and supply-chain concerns, especially because the command fans out across packages and can trigger arbitrary package scripts.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
`npx vitest` without version pinning can execute whatever version resolves at runtime, including one fetched from the network. In an auditing profile this is unsafe because test runners execute project code, so the skill can be induced to run attacker-controlled code paths during review.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
The unpinned `npx jest` command introduces the same runtime package resolution risk as other `npx` usages. Combined with the fact that Jest executes repository code and setup hooks, this can convert a passive QC task into arbitrary code execution.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
`npx vitest --coverage` is unpinned and executes tests plus coverage instrumentation, increasing both dependency execution and project code execution risk. The coverage step does not reduce the underlying trust issue and may further broaden code paths executed.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
`npx jest --coverage` is another unpinned command that may fetch and run an arbitrary tool version, while also executing repository tests. In hostile or unknown repositories, this creates meaningful code-execution and supply-chain exposure.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding
The profile recommends `npx eslint` without version pinning, allowing the linter package and plugins to be resolved dynamically. ESLint loads project configuration, plugins, and parsers, so running it on an untrusted repository can execute attacker-controlled JavaScript.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding
This fallback `npx eslint` invocation is also unpinned and may pull packages from the registry at runtime. Because it explicitly loads parser and plugin packages, it widens the supply-chain surface even when the repository has no ESLint config.

Static analysis

No suspicious patterns detected.