Back to skill

Security audit

Code Quality Guardian

Security checks for vulnerabilities and agentic risk

Overview

This is mostly a normal code-quality tool, but its HTML reports can embed untrusted scan output without escaping, which needs review before use on untrusted projects.

Install and run this only in an isolated, minimally privileged environment when analyzing untrusted repositories. Prefer console or JSON output until the HTML reporter escapes issue fields, and use a reviewed lockfile or pinned requirements before putting it in CI.

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

Warning
Location
src/code_quality_guardian/reports/html_reporter.py:274
Finding

Stored HTML Injection in Generated Reports

Content
View full analysis

Vulnerability Details

File Location: src/code_quality_guardian/reports/html_reporter.py:274-283
Vulnerability Type: Stored HTML injection
Risk Level: Medium

Vulnerable Code

python
for issue in sorted_issues:
    sev_class = severity_class.get(issue.severity, "info")
    rows.append(f"""
        <tr>
            <td class="{sev_class}">{issue.severity.name}</td>
            <td><code>{issue.code}</code></td>
            <td>{issue.file}</td>
            <td>{issue.line}</td>
            <td>{issue.message}</td>
        </tr>
    """)

Technical Analysis

The HTML reporter interpolates issue.code, issue.file, and issue.message directly into an HTML document without context-appropriate escaping. These values originate from external analyzer output and can be influenced by the contents and filenames of the repository being scanned.

Python permits filenames containing HTML metacharacters on common operating systems, and analyzer diagnostics may incorporate attacker-controlled identifiers, strings, or source fragments. When such values are inserted into the report, a browser interprets them as markup rather than plain text.

For example, a malicious filename or diagnostic containing an element with an event handler can introduce active content into the generated report. The payload is stored in the report file and activates when a user opens that file in a browser.

Attack Path

  1. An attacker prepares a repository containing a Python file whose filename or analyzer-triggered diagnostic contains malicious HTML.
  2. A victim or CI workflow scans the untrusted repository using the HTML format:
    bash
    quality-guardian analyze --path ./untrusted-project --format html --output report.html
    
  3. Flake8, Pylint, or Bandit returns the attacker-influenced filename or message as part of ...[truncated 824 chars]
Remediation
View remediation

Remediation Suggestions

Escape every untrusted value before inserting it into HTML. For example:

python
from html import escape

code = escape(str(issue.code), quote=True)
file_name = escape(str(issue.file), quote=True)
message = escape(str(issue.message), quote=True)
severity_name = escape(str(issue.severity.name), quote=True)

Insert only these escaped values into the template. Preferably, replace manual string interpolation with Jinja2 configured using an HTML-aware environment and automatic escaping:

python
from jinja2 import Environment, select_autoescape

env = Environment(autoescape=select_autoescape(["html", "xml"]))

Additional hardening should include:

  • Validate sev_class against a fixed allowlist before using it in an attribute.
  • Add a restrictive Content Security Policy to generated reports, such as disabling scripts entirely.
  • Add regression tests using malicious filenames and messages such as an image element with an onerror handler.
  • Verify that the generated document contains escaped entities and does not create executable DOM elements.
  • Treat all output from external analysis tools as untrusted, even when the tool itself is trusted.

T08 · Insecure Dependencies

Note
Location
requirements.txt:6
Finding

Unpinned Executable Dependencies Create Supply-Chain Exposure

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:6-52
Vulnerability Type: Unlocked third-party dependency installation
Risk Level: Low

Vulnerable Code

text
click>=8.0.0
pyyaml>=6.0
colorama>=0.4.6
tabulate>=0.9.0
jinja2>=3.1.0

flake8>=6.0.0
pylint>=2.17.0
bandit[toml]>=1.7.0
radon>=6.0.0
xenon>=0.9.0

mypy>=1.0.0
safety>=2.3.0
markdown>=3.4.0

pytest>=7.0.0
pytest-cov>=4.0.0
black>=23.0.0
isort>=5.12.0

pathspec>=0.11.0
tomli>=2.0.0;python_version<"3.11"

The documented installation command is:

bash
pip install -r requirements.txt

Technical Analysis

All declared packages use open-ended lower-bound constraints. No lockfile, exact version constraints, or package hashes are supplied. Consequently, separate installations can resolve to different dependency versions, including releases published after the Skill was reviewed.

Python package installation may execute package build backends or other installation-time logic. The dependencies also include command-line analysis tools and development packages, increasing the number of executable third-party components installed into the environment.

This is a supply-chain hardening weakness rather than evidence that any currently declared package is malicious. The identified package names are established projects, and the audit found no unsafe custom package index or direct dependency URL.

Attack Path

  1. A permitted direct or transitive dependency publishes a compromised release that still satisfies the lower-bound constraint.
  2. A user or CI workflow runs:
    bash
    pip install -r requirements.txt
    
  3. The package resolver selects the compromised newer version because no upper bound, exact pin, lockfile, or hash prevents it.
  4. Malicious installation or runtime code executes with the privileges of the account running ` ...[truncated 718 chars]
Remediation
View remediation

Remediation Suggestions

Adopt reproducible, reviewed dependency management:

  1. Separate runtime dependencies from development and testing dependencies.
  2. Remove packages that are not required by implemented runtime features.
  3. Generate a lockfile containing exact direct and transitive versions.
  4. Record cryptographic hashes and install with hash verification:
    bash
    pip install --require-hashes -r requirements.lock
    
  5. Update dependencies through reviewed automated changes rather than allowing installations to select arbitrary future releases.
  6. Run dependency vulnerability and provenance checks in CI.
  7. Install and execute analyzers in an isolated, minimally privileged container without production credentials.
  8. Restrict CI network access and secret availability during dependency installation and untrusted repository analysis.
  9. Avoid running pip as root or an administrator.
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (51)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documents capabilities that imply shell, file read/write, and environment access, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization ambiguity where an agent may execute powerful operations without clear least-privilege boundaries, increasing the risk of unintended command execution, filesystem modification, or secret exposure when analyzing untrusted repositories.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This Python file's docstring and all user-facing console messages are written in Chinese, which imposes a specific language on users without any visible opt-in or alternative. The policy for natural-language violations applies to all file types, including code string literals and comments, so this is in scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains the title, class docstring, comments, exception text, and log messages in Chinese only, which imposes a specific language/locale on users and operators. The file does not provide an opt-in, alternative language, or a documented reason for a Chinese-only constraint, matching the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code defines multiple user-facing help strings and command descriptions exclusively in Chinese, such as option help text and command docstrings. That effectively forces a specific language for end users without offering a locale choice or documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The check command will execute any program name supplied by the user, not just known code-quality tools. In a developer-tool context this broadens the feature beyond its stated purpose and can enable unintended command execution, especially if the tool is run in automated pipelines, wrappers, or privileged environments where user-controlled input may reach this parameter.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/code_quality_guardian/cli.py (reported line 227)May include surrounding context.

python
# 尝试获取版本
        import subprocess
        try:
            result = subprocess.run(
                [tool_name, "--version"],
                capture_output=True,
                text=True,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code file embeds user-facing documentation and error messaging primarily in Chinese, including the module description, class docstrings, and raised error strings. That creates an implicit language/locale constraint without any visible opt-in or alternate language path, which matches the policy concern for forced language selection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code file contains natural-language descriptions in Chinese in the module docstring and class/docstring content, and the rest of the file continues that pattern for user-facing/reporting text descriptions. Under the policy, forcing a specific language without user opt-in is a locale/language policy violation unless the constraint is explicitly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The HTML template hard-codes lang="zh-CN", which imposes a specific language/locale on all generated reports. The file does not indicate that this locale is configurable, optional, or justified as region-specific behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The module docstrings and class/method descriptions are written in Chinese, which imposes a specific language context without any indication of user opt-in or a documented locale requirement. The policy explicitly calls for flagging language or locale constraints when the skill does not offer a choice or justification.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/code_quality_guardian/tools/bandit.py (reported line 54)May include surrounding context.

python
cmd.extend(["-s", ",".join(skips)])
        
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/code_quality_guardian/tools/flake8.py (reported line 69)May include surrounding context.

python
cmd.extend(["-s", ",".join(skips)])
        
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/code_quality_guardian/tools/pylint.py (reported line 78)May include surrounding context.

python
cmd.extend(["-s", ",".join(skips)])
        
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/code_quality_guardian/tools/radon.py (reported line 63)May include surrounding context.

python
cmd.extend(["-s", ",".join(skips)])
        
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/code_quality_guardian/tools/radon.py (reported line 89)May include surrounding context.

python
cmd.extend(["-s", ",".join(skips)])
        
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This Python test file contains module docstrings and usage text entirely in Chinese, including the title and run instructions. Because the file presents user-facing natural-language guidance in a single language without offering an alternative or documenting a locale-specific constraint, it may violate a language/locale policy requiring user choice or opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The document prominently presents Chinese-first content and continues primarily in Chinese throughout headings and descriptions, but does not state that language selection is optional or that the skill is intended only for a Chinese-speaking context. Per the policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The display name is given only in Chinese ("代码质量守护者"), while the rest of the document is bilingual. This creates a mild language/locale policy concern because the skill appears to prefer a specific language in a user-facing field without stating that users can choose their preferred locale.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens build reproducibility and can unintentionally introduce vulnerable or incompatible releases through the supply chain.

Content

Scanner excerpt · requirements.txt (reported line 6)May include surrounding context.

text
# Core dependencies
# 核心依赖
click>=8.0.0
pyyaml>=6.0
colorama>=0.4.6
tabulate>=0.9.0

Unverifiable Dependency: click has 1 known advisory(ies) (CVE-2026-7246 (Pallets Click, versions 8.3.2 and below, contain a command injection vulnerabili)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
89% confidence
Finding

Click is not pinned, and the scanner notes at least one known advisory affecting some versions. Because the manifest does not identify the exact installed version, you cannot verify whether deployments are exposed, which is a real security gap for a package that may handle CLI input.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

PyYAML is declared with a non-pinned minimum version, so deployments may pull different releases depending on install time and environment. Because this package has had multiple historical security issues, lack of pinning makes it harder to verify whether an installation is safe.

Content

Scanner excerpt · requirements.txt (reported line 7)May include surrounding context.

text
# Core dependencies
# 核心依赖
click>=8.0.0
pyyaml>=6.0
colorama>=0.4.6
tabulate>=0.9.0
jinja2>=3.1.0

Unverifiable Dependency: pyyaml has 8 known advisory(ies) (CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
97% confidence
Finding

PyYAML has a substantial history of deserialization and input-handling vulnerabilities, and the unpinned requirement prevents confirming whether the resolved version is safe. In a tool that may parse configuration files, this uncertainty is more dangerous than for a purely cosmetic library.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

An unpinned dependency permits non-deterministic builds and increases exposure to supply-chain risk if a later release becomes vulnerable or malicious. While colorama is lower risk than parser or templating libraries, the control weakness still exists.

Content

Scanner excerpt · requirements.txt (reported line 8)May include surrounding context.

text
# 核心依赖
click>=8.0.0
pyyaml>=6.0
colorama>=0.4.6
tabulate>=0.9.0
jinja2>=3.1.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

Using only a minimum version for tabulate means installed versions can drift over time, reducing reproducibility and making security posture difficult to audit. This is a real supply-chain hygiene issue even if direct exploitability is limited.

Content

Scanner excerpt · requirements.txt (reported line 9)May include surrounding context.

text
click>=8.0.0
pyyaml>=6.0
colorama>=0.4.6
tabulate>=0.9.0
jinja2>=3.1.0

# Python code quality tools

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

Jinja2 is a templating engine with a notable history of sandbox and injection-related issues, so leaving it unpinned increases the chance of resolving to an unsafe release. In a code-quality/reporting skill that may generate output from analyzed content, templating dependencies deserve extra scrutiny.

Content

Scanner excerpt · requirements.txt (reported line 10)May include surrounding context.

text
pyyaml>=6.0
colorama>=0.4.6
tabulate>=0.9.0
jinja2>=3.1.0

# Python code quality tools
# Python 代码质量工具

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/test_quality_checker.py:94