Back to skill

Security audit

Hacker新闻数据服务

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to provide Hacker News lookups through a third-party API, but it requires and persists an API key in a local plaintext .env file with inconsistent copied project references.

Review this before installing. It will ask for a XiaoBenYang API key, send requests to that service, and save the key in a local .env file as plaintext. Install only if you trust that third-party service and are comfortable managing or deleting the persisted key yourself; avoid using a key with broad privileges or reuse across services.

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
scripts/config.py:43
Finding

API Key Persisted in a Plaintext File Without Explicit Permission Hardening

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:43-64
Vulnerability Type: Plaintext sensitive-data storage with insufficient file-permission controls
Risk Level: Medium

Vulnerable Code

python
def save_api_key_to_env(api_key: str) -> bool:
    """将API key保存到.env文件"""
    try:
        env_path = Path(".env")
        lines = []
        if env_path.exists():
            lines = env_path.read_text(encoding="utf-8").splitlines()
        found = False
        new_lines = []
        for line in lines:
            if line.startswith("XBY_APIKEY="):
                new_lines.append(f"XBY_APIKEY={api_key}")
                found = True
            else:
                new_lines.append(line)
        if not found:
            new_lines.append(f"XBY_APIKEY={api_key}")
        env_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8")
        os.environ["XBY_APIKEY"] = api_key
        return True
    except Exception as e:
        print(f"保存API key失败: {e}")
        return False

Technical Analysis

The supplied API key is written directly to .env in the process's current working directory. The implementation does not use a platform secret manager, encrypt the credential, select a dedicated protected configuration directory, or explicitly restrict the file to owner-only access.

Path.write_text() creates files using permissions derived from the ambient process umask. Consequently, deployments with a permissive umask may create a file readable by other local users or processes. If .env already exists with unsafe permissions, updating it does not correct those permissions. Storing the file in the working directory also increases the possibility of accidental inclusion in source-control commits, build artifacts, backups, or shared workspace snapshots.

The Skill documentation explicitly directs the agent to request and persist the user's API key, so this storag ...[truncated 1429 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer a platform-provided secret manager, operating-system credential store, or runtime-only environment variable instead of filesystem persistence.
  2. If persistence is essential, store the credential in a dedicated per-user configuration directory rather than the current working directory.
  3. Create the secret file atomically with mode 0600, and explicitly verify and repair permissions on existing files before reading or updating them.
  4. Avoid following symbolic links when opening the destination, and use an atomic temporary-file-plus-rename procedure to prevent link and partial-write attacks.
  5. Add .env to .gitignore and exclude it from packaging, logging, diagnostics, backups, and workspace synchronization.
  6. Do not print, return, or interpolate the API key into exceptions or logs.
  7. Document credential rotation and revocation procedures, and advise users to rotate any key that may already have been stored in an exposed workspace.
  8. Consider making persistence opt-in and clearly disclose the storage location before writing the credential.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unbounded Dependency Constraints Permit Unreviewed Future Releases

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-4
Vulnerability Type: Non-reproducible and insufficiently constrained third-party dependencies
Risk Level: Low

Vulnerable Code

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Technical Analysis

Every dependency uses a minimum-only version constraint. An installation can therefore resolve to any later version accepted by the package resolver, including major releases that were not present during this audit. No lock file or package hashes are included to guarantee that installations receive the same reviewed artifacts.

This does not establish that any currently named dependency is malicious. The risk is that future compromised, unexpectedly incompatible, or otherwise unsafe releases may be installed automatically without a corresponding project change or security review. The absence of hashes also prevents installers from verifying dependencies against project-approved artifacts.

Attack Path

  1. A maintainer or deployment system installs the project dependencies at a later date.
  2. The package resolver selects the newest versions satisfying the minimum-only constraints.
  3. A selected release contains a compromised package artifact, malicious maintainer update, exploitable regression, or incompatible behavior.
  4. The package is installed and its code executes during installation, import, or normal Skill operation.
  5. The resulting privileges are those of the user or service account running the installation or Skill.

This path is contingent on a future compromised or vulnerable upstream release; no malicious dependency was confirmed in the audited files.

Impact Assessment

A compromised dependency could potentially execute code with the privileges of the installing or running process, access API credentials available to that process, alter requests or responses, read access ...[truncated 366 chars]

Remediation
View remediation

Remediation Suggestions

  1. Generate and commit a lock file containing exact, reviewed transitive dependency versions.
  2. Use package hashes, such as pip's --require-hashes workflow, to restrict installations to approved artifacts.
  3. Apply compatible upper bounds where a lock file cannot be used, especially across major versions.
  4. Install only from trusted package indexes over authenticated TLS, and disable unapproved extra indexes.
  5. Automate dependency vulnerability and provenance scanning.
  6. Update dependencies through an explicit review and testing process rather than resolving unrestricted current releases during deployment.
  7. Rebuild the lock file periodically so security updates are adopted deliberately instead of leaving dependencies permanently stale.
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (30)

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented behavior centers on Hacker News data access, but the implementation behavior reportedly includes local .env persistence, xiaobenyang/gaokao-related configuration management, and API-key state handling unrelated to the declared feature set. This discrepancy increases the risk of credential collection under false pretenses and expands the attack surface through undocumented local state changes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented behavior centers on Hacker News data access, but the implementation behavior reportedly includes local .env persistence, xiaobenyang/gaokao-related configuration management, and API-key state handling unrelated to the declared feature set. This discrepancy increases the risk of credential collection under false pretenses and expands the attack surface through undocumented local state changes.

Content

No source excerpt is available for this finding.

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 · scripts/config.py (reported line 13)May include surrounding context.

python
model_config = SettingsConfigDict(
        env_prefix="XBY_GAOKAO_",
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

The model_post_init method explicitly reads .env and extracts a specific API key outside the normal settings mechanism, creating bespoke secret-handling logic. Custom parsing of local secret files expands attack surface, bypasses centralized controls, and is suspicious given the mismatch between the skill's stated purpose and its credential behavior.

Content

Scanner excerpt · scripts/config.py (reported line 31)May include surrounding context.

python
default_year: int = 2025

    def model_post_init(self, __context):
        # 强制从 .env 文件读取 XBY_APIKEY
        env_path = Path(".env")
        if env_path.exists():
            content = env_path.read_text(encoding="utf-8")

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

Checking for and reading a local .env file as part of custom logic contributes to unnecessary secret access behavior. In this skill context, direct local secret-file handling is more dangerous because Hacker News retrieval ordinarily should not require private credential collection or custom secret extraction.

Content

Scanner excerpt · scripts/config.py (reported line 32)May include surrounding context.

python
def model_post_init(self, __context):
        # 强制从 .env 文件读取 XBY_APIKEY
        env_path = Path(".env")
        if env_path.exists():
            content = env_path.read_text(encoding="utf-8")
            for line in content.splitlines():

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 · scripts/config.py (reported line 39)May include surrounding context.

python
if line.startswith("XBY_APIKEY="):
                    self.api_key = line.split("=", 1)[1].strip()
                    break
        # 如果环境变量有值,覆盖 .env 的值
        env_val = os.getenv("XBY_APIKEY", "")
        if env_val:
            self.api_key = env_val

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code adds credential persistence and mutation capabilities to a skill described as a Hacker News data service, which is a clear scope mismatch. Writing API keys into a local .env file and mutating process environment increases secret exposure risk and creates a persistence mechanism that is unnecessary for simple public-data retrieval.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The functions save_api_key_to_env and set_api_key store secrets locally and modify runtime environment state without a justified need for a Hacker News information tool. Such behavior can expose credentials to other local users, accidental check-in, backups, logs, or unrelated code running in the same environment.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This function is explicitly designed to persist an API key into a plaintext .env file, creating durable local secret storage. Plaintext storage of credentials is dangerous because it is easily exposed via source control mistakes, backups, local compromise, or unintended sharing, especially when unrelated to the tool's advertised public-data role.

Content

Scanner excerpt · scripts/config.py (reported line 48)May include surrounding context.

python
def save_api_key_to_env(api_key: str) -> bool:
    """将API key保存到.env文件"""
    try:
        env_path = Path(".env")
        lines = []
        if env_path.exists():
            lines = env_path.read_text(encoding="utf-8").splitlines()

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares no explicit tool scope or permission boundaries even though it appears to have environment access, file read/write, and network capabilities. In a skill that also instructs collecting and persisting an API key, the lack of scope constraints increases the chance of overbroad access, secret misuse, or unexpected data exfiltration through undocumented code paths.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill requires an API key and references an external service unrelated to the stated Hacker News purpose, creating a trust mismatch for users who may provide credentials expecting only public-data retrieval. This inconsistency makes social engineering and secret harvesting more plausible, especially because the skill frames the requirement as mandatory.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill instructs the model to solicit an API key from the user and persist it via local configuration without warning about sensitivity, retention, or storage behavior. This is dangerous because users may disclose secrets without informed consent, and persisted credentials can later be read, leaked, or misused by other components with file or env access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The raised error string is natural-language content that will be surfaced to users, but it is fixed to Chinese with no opt-in or alternative locale handling. This violates the language/locale policy unless the skill is explicitly documented as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The wrapper returns user-visible status messages such as Chinese failure text and English success text, but there is no locale selection or documented reason for the language behavior. This is a policy issue because the skill effectively imposes language choices on users.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The class docstring refers to a different domain than the declared skill, suggesting the file may have been repurposed from another project without adequate review. This kind of provenance mismatch is a supply-chain red flag because hidden assumptions, endpoints, or credential handling may not align with the advertised functionality.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill persists an API key to .env automatically, with no user-facing warning, confirmation, or explanation of storage location and lifetime. Silent persistence of secrets can lead to unintentional long-term storage, accidental disclosure through source control, and misuse by other local processes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

Nearly all instructional and descriptive text in the skill is presented only in Chinese, with no indication that users may choose another language or that the locale restriction is intentional and justified. This can constitute a language-policy issue when a skill imposes a specific language without offering user choice.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

文档声称应调用本技能的 scripts.tools 中函数,但示例却使用了 scripts.tools.search_schools(...),这是与 Hacker News 工具集无关的学校搜索函数。该示例会误导调用方对技能真实意图和可用能力的理解。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The project structure refers to a gaokao-related directory instead of a Hacker News skill, reinforcing that the package may be repurposed or mislabeled. In context with the API-key collection and behavior mismatches, this inconsistency raises the risk that the skill is routing data to an unrelated backend or performing undocumented operations.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency specification uses a lower-bound constraint (requests>=2.31.0) instead of pinning an exact version, which makes builds non-reproducible and can allow different environments to resolve to different releases. This increases supply-chain risk and makes it difficult to determine whether a deployed version includes known vulnerabilities or breaking changes.

Content

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

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

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

Requests has multiple known advisories, and because the manifest does not pin the installed version, it is impossible to verify from this file whether a vulnerable release could be selected. In a network-facing data retrieval skill, that uncertainty matters because requests is likely central to outbound HTTP handling and may process attacker-influenced URLs or responses.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency specification uses a lower-bound constraint (pydantic>=2.7.0) rather than an exact pinned version, so installations may resolve to different package versions over time. That weakens reproducibility and complicates vulnerability management because you cannot verify which version is actually deployed.

Content

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

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: pydantic has 4 known advisory(ies) (CVE-2021-29510 (Use of "infinity" as an input to datetime and date fields causes infinite loop i); CVE-2024-3772 (Pydantic regular expression denial of service); CVE-2021-29510 (Pydantic is a data validation and settings management using Python type hinting.) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
86% confidence
Finding

Pydantic has known advisories, but the unpinned requirement prevents verification of whether the resolved version is safe. If the skill validates untrusted external data from Hacker News APIs or search results, a vulnerable parser or regex path could be reachable and increase denial-of-service or parsing risk.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

Using pydantic-settings>=2.2.0 allows any later version to be installed, which can introduce unreviewed code changes or vulnerable releases into the environment. This is a supply-chain hygiene issue that reduces build determinism and auditability.

Content

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

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1