Back to skill

Security audit

goverment bidding email

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly aligned with sending government-procurement email reports, but it sends real email using stored SMTP credentials and relies on an unbundled runtime component that was not available for review.

Install only if you know the trusted source of govb_fetcher, can verify the SMTP recipients before each send, and run it from a trusted working directory. Prefer a fixed config path, pinned dependencies, and a safer user-private lock file before production use.

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
govb_email/fetcher.py:300
Finding

Predictable Shared Lock File Allows Symlink-Based File Truncation

Content
View full analysis

Vulnerability Details

File Location: govb_email/fetcher.py, lines 300-304
Vulnerability Type: Unsafe temporary file handling
Risk Level: Medium

Vulnerable Code:

python
LOCK_FILE = '/tmp/govb_bidding_email.lock'

try:
    lock_fd = open(LOCK_FILE, 'w')
    fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)

Technical Analysis

The application uses a predictable lock-file path in the globally writable /tmp directory. Opening this path with mode w follows symbolic links and truncates the resolved target before the advisory lock is acquired.

A local attacker who can create files in /tmp can place a symbolic link at /tmp/govb_bidding_email.lock pointing to another file writable by the account running govb-email. When the victim invokes the command, open(..., 'w') follows that link and truncates the target.

The subsequent flock does not prevent this attack because pathname resolution and truncation occur before the lock is applied.

Attack Path

  1. A local attacker determines which user is expected to run govb-email.
  2. The attacker identifies a valuable file writable by that user, such as an application configuration or user data file.
  3. The attacker creates /tmp/govb_bidding_email.lock as a symbolic link to that target.
  4. The victim runs govb-email.
  5. The application follows the symbolic link while opening the lock file in write mode.
  6. The target file is truncated before fcntl.flock is executed.
  7. The affected application or user loses data or operates with a corrupted configuration.

Impact Assessment

Exploitation does not grant arbitrary code execution or access beyond the victim's existing filesystem privileges. It can, however, truncate any file writable by the account running the Skill. This may cause data loss, configuration corruption, denial of service, or secondary security consequences if a security-relevant writable file is targeted.

Remediation
View remediation

Remediation Suggestions

  • Store the lock in a user-private runtime directory, such as $XDG_RUNTIME_DIR, after verifying that the directory is owned by the current user and is not accessible to other users.
  • Create the lock securely with os.open and restrictive flags and permissions:
    python
    flags = os.O_WRONLY | os.O_CREAT
    flags |= getattr(os, "O_NOFOLLOW", 0)
    fd = os.open(lock_path, flags, 0o600)
    lock_fd = os.fdopen(fd, "w")
    fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
    
  • Validate the opened file with os.fstat and reject non-regular files or files not owned by the current user.
  • Avoid deleting a shared-path lock without verifying its inode and ownership.
  • Consider using a maintained lock-file library that protects against symlink and ownership attacks.

T08 · Insecure Dependencies

Note
Location
pyproject.toml:7
Finding

Unpinned and Undeclared Runtime Dependencies Create Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Locations: pyproject.toml, lines 7-9; govb_email/fetcher.py, lines 27-31
Vulnerability Type: Incomplete and non-reproducible dependency declaration
Risk Level: Low

Vulnerable Code:

toml
dependencies = [
    "requests",
]
python
def _import_fetcher():
    """延迟导入避免循环依赖"""
    from govb_fetcher.fetcher import fetch_all_bidding, save_to_excel
    from govb_fetcher.config import get_output_dir
    return fetch_all_bidding, save_to_excel, get_output_dir

Technical Analysis

The declared requests dependency has no version constraints or integrity lock. More importantly, the application imports the essential govb_fetcher component at runtime, but that component is neither included in the audited project nor declared as an installable dependency in pyproject.toml.

Consequently, pip install -e . does not produce a complete or reproducible runtime. A user may attempt to resolve the missing import by installing a similarly named package from an unverified source. Any installed govb_fetcher module executes in the same Python process and inherits the application's filesystem, environment, and network access.

The missing component also prevents this audit from verifying the actual procurement network requests, Excel generation behavior, and output-directory handling.

Attack Path

  1. A user installs the project using the documented editable-install command.
  2. The installation succeeds without installing govb_fetcher.
  3. The user runs govb-email, causing an import failure when _import_fetcher() executes.
  4. To resolve the failure, the user obtains or installs a package that provides govb_fetcher from an unverified package index, repository, or local source.
  5. The untrusted package is imported directly into the govb-email process.
  6. Malicious import-time or function-level code executes with the invoking user's privileges and ca ...[truncated 697 chars]
Remediation
View remediation

Remediation Suggestions

  • Declare the exact trusted distribution that provides govb_fetcher in pyproject.toml, including an appropriate supported version range.
  • If govb_fetcher is an internal component, bundle it in the project or publish it through an authenticated private package index.
  • Generate and enforce a dependency lock file with hashes for deployment.
  • Apply compatible version bounds to direct dependencies and routinely review resolved transitive dependencies.
  • Document the authoritative source, package name, version, and integrity verification process for govb_fetcher.
  • Remove requests if this package does not use it directly and it is not required as an explicitly declared runtime dependency.
  • Audit the complete govb_fetcher implementation before deployment because its network and file behavior is outside the supplied project.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 38)May include surrounding context.

md
"""
配置加载模块 (govb-email)

从 .env 文件读取配置,所有配置项必填,缺失时直接报错
只加载 EMAIL_* 前缀的配置
"""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · govb_email/config.py (reported line 6)May include surrounding context.

python
"""
配置加载模块 (govb-email)

从 .env 文件读取配置,所有配置项必填,缺失时直接报错
只加载 EMAIL_* 前缀的配置
"""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · govb_email/config.py (reported line 28)May include surrounding context.

python
"""
配置加载模块 (govb-email)

从 .env 文件读取配置,所有配置项必填,缺失时直接报错
只加载 EMAIL_* 前缀的配置
"""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · govb_email/config.py (reported line 65)May include surrounding context.

python
"""
配置加载模块 (govb-email)

从 .env 文件读取配置,所有配置项必填,缺失时直接报错
只加载 EMAIL_* 前缀的配置
"""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · govb_email/config.py (reported line 70)May include surrounding context.

python
"""
配置加载模块 (govb-email)

从 .env 文件读取配置,所有配置项必填,缺失时直接报错
只加载 EMAIL_* 前缀的配置
"""

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

Searching the current working directory first for .env introduces a configuration-hijacking risk: if the skill is launched from an untrusted or attacker-influenced directory, it may load attacker-supplied SMTP settings and recipients. In the context of an automated government procurement email tool, that could redirect sensitive business reports or cause mail to be sent through attacker-controlled infrastructure.

Content

Scanner excerpt · govb_email/config.py (reported line 35)May include surrounding context.

python
"""
    # 按优先级查找:当前工作目录 → ~/.config/govb-email/
    candidates = [
        Path.cwd() / '.env',
        Path.home() / '.config' / 'govb-email' / '.env',
    ]
    env_path = next((p for p in candidates if p.exists()), None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · govb_email/config.py (reported line 36)May include surrounding context.

python
# 按优先级查找:当前工作目录 → ~/.config/govb-email/
    candidates = [
        Path.cwd() / '.env',
        Path.home() / '.config' / 'govb-email' / '.env',
    ]
    env_path = next((p for p in candidates if p.exists()), None)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares operational capabilities that imply reading configuration and writing generated Excel output, but it does not define any explicit tool scope or permissions boundaries. In an agent setting, this increases the chance of unintended file access or broader-than-necessary execution because the runtime cannot clearly constrain what files the skill may read or write.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The usage section explains how to run the skill but does not prominently warn that it will send outbound email through configured SMTP credentials to configured recipients. Users may trigger it without realizing it performs an external side effect, which is risky in an agent environment where actions should be transparent and consented to.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases include very generic terms like '发送邮件', '推送报告', and '邮件通知', which overlap with ordinary user requests unrelated to this specific government-procurement workflow. That makes accidental invocation more likely, potentially causing unsolicited outbound email or execution of business logic when the user intended something else.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This file contains natural-language descriptions and runtime output exclusively in Chinese, including the module docstring and printed messages. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module docstring says all configuration items are mandatory, yet REQUIRED_CONFIG_KEYS at L15-L23 excludes EMAIL_RECIPIENT_NAME, EMAIL_SENDER_NAME, EMAIL_SUBJECT_PREFIX, and EMAIL_BODY_INTRO. get_email_config() still calls get_config() for those values at L92-L95, so the documented validation behavior does not match the actual required-key check.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This file contains user-facing descriptions, usage text, help text, and log/output strings entirely in Chinese. Under the policy criteria, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The natural-language description and invocation guidance are entirely in Chinese and do not indicate that users may choose another language or that the locale restriction is required for a documented regional-compliance reason. Under the policy, forcing a specific language without opt-in can be a natural-language policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The only natural-language description in the file is written in Chinese and presents the skill as a government procurement email tool without any indication that language selection is optional. Under the policy, forcing a specific language or locale without user opt-in can be a natural-language policy violation unless clearly documented as region-specific and justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module documentation states '只加载 EMAIL_* 前缀的配置', implying non-email keys are ignored. In implementation, load_config() parses every key=value line without filtering by prefix at L47-L49, so the documented intent contradicts actual behavior.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The project declares a dependency on requests without pinning or constraining its version, making it impossible to verify at review time whether deployments will pull a patched or vulnerable release. In a tool that fetches data and sends government procurement emails, an affected requests version could expose credentials, mishandle TLS or redirects, or otherwise increase supply-chain and runtime risk depending on the environment.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.