Back to skill

Security audit

HackerNews数据服务

Security checks for vulnerabilities and agentic risk

Overview

The skill may provide HackerNews lookup features, but it uses an under-explained third-party API key flow and stores the key locally in plaintext.

Review this before installing. Only provide an XBY_APIKEY if you trust xiaobenyang.com with the key and your query parameters, and be aware the skill stores that key in a local .env file in plaintext. Prefer a revised version that removes the gaokao leftovers, clearly documents the backend, avoids persistent plaintext secrets, and pins dependencies.

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:45
Finding

API Key Persisted in a Plaintext File Without Enforced Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:45-68
Vulnerability Type: Plaintext credential 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 function persists the supplied API key as plaintext in a .env file located relative to the process's current working directory. Path.write_text() does not explicitly enforce owner-only permissions such as mode 0600; the resulting permissions depend on the process umask and any pre-existing file permissions.

The use of a current-working-directory-relative path also creates uncertainty about where the secret is stored. The file could be created in a shared workspace, included in backups, or accidentally committed to source control. An existing .env file is overwritten without validating its ownership, permissions, or whether it is a symbolic link.

Persisting the credential is part of the documented workflow, but permanent plaintext storage is not the minimum privilege necessary to make authenticated API requests. Environment-only or secret-manager-backed storag ...[truncated 1080 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer obtaining the key from a process environment variable or operating-system secret manager without writing it to disk.
  2. If persistence is essential, use a dedicated user-specific configuration directory rather than the current working directory.
  3. Create the secret file atomically with owner-only mode 0600, and verify its ownership and permissions before reading or replacing it.
  4. Refuse to write through symbolic links and reject paths that are not regular files.
  5. Add .env to .gitignore and exclude it from archives, logs, diagnostics, and backups where practical.
  6. Avoid printing the key or including it in exception payloads.
  7. Document the storage location, retention behavior, third-party recipient, and a procedure for deleting or rotating the credential.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Dependencies Are Not Upper-Bounded or Locked to Reviewed Versions

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-4
Vulnerability Type: Non-reproducible dependency resolution and supply-chain exposure
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 specifies only a minimum version. A future installation can therefore resolve to package releases that did not exist and were not reviewed when the Skill was audited. The absence of a lock file or cryptographic hashes also prevents installers from verifying that they received the exact dependency artifacts tested by the developer.

This does not establish that any currently named package or version is malicious. It is a supply-chain hardening weakness: future compromised, vulnerable, or incompatible releases could enter deployments without a corresponding source-code change in this project.

Attack Path

  1. An attacker compromises the publication account or release process of one of the named dependencies, or a future allowed release contains exploitable behavior.
  2. The attacker publishes a version satisfying the declared minimum constraint.
  3. A user installs or rebuilds the Skill without a lock file, upper bound, or hash verification.
  4. The package resolver selects the unintended future release.
  5. Malicious or vulnerable dependency code executes during installation, import, or normal Skill operation with the privileges of the installing or running process.

This path depends on an upstream compromise or unsafe future release; no such compromise was confirmed during this static audit.

Impact Assessment

In the worst case, a compromised dependency could execute arbitrary code with the privileges of the user or service installing or running the Skill. That could expose the API key, modify project files, access other data available to the process, or alter network requests ...[truncated 298 chars]

Remediation
View remediation

Remediation Suggestions

  1. Generate and commit a lock or constraints file containing exact reviewed versions.
  2. Use hash-checked installation, such as pip install --require-hashes, with hashes generated from trusted artifacts.
  3. Upgrade dependencies through an explicit review and testing process rather than resolving arbitrary future versions during deployment.
  4. Use a trusted package index and disable unintended fallback indexes to reduce dependency-confusion risk.
  5. Run dependency vulnerability scanning in continuous integration and rebuild lock files when security updates are approved.
  6. Install and execute dependencies in an isolated environment with only the filesystem and network permissions required by the Skill.
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (27)

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
95% confidence
Finding

The file describes a HackerNews service, but the referenced configuration/project structure appears copied from a different '小笨羊高考' service and includes secret storage behavior not disclosed in the purpose statement. This kind of description-behavior mismatch is a supply-chain and trust problem because reviewers may approve a seemingly harmless content tool that actually targets a different backend and persists credentials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The file describes a HackerNews service, but the referenced configuration/project structure appears copied from a different '小笨羊高考' service and includes secret storage behavior not disclosed in the purpose statement. This kind of description-behavior mismatch is a supply-chain and trust problem because reviewers may approve a seemingly harmless content tool that actually targets a different backend and persists credentials.

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
74% confidence
Finding

The model_post_init method force-reads .env and extracts XBY_APIKEY through custom parsing, bypassing normal configuration handling and broadening secret access within the component. In this skill context, that is more concerning because the service is supposed to provide HackerNews data functions, not aggressively harvest and normalize credentials from local files.

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
72% confidence
Finding

Directly reading the entire .env file to search for a specific API key unnecessarily exposes all file contents to the process and increases the blast radius if future code logs or mishandles that content. This is a risky secret-handling pattern, especially given the skill's stated purpose does not justify custom credential ingestion logic.

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

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The function explicitly persists an API key to .env, creating a durable local secret that may be exposed to version control, file syncing, backups, or other users on the system. In the context of a HackerNews data skill, embedding credential-writing capability is more dangerous because it expands secret-handling scope beyond the apparent business need.

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
90% confidence
Finding

The skill exposes capabilities implying environment access, file read/write, and network use, but declares no explicit tool scope or permission boundaries. In an agent setting, this weakens least-privilege controls and makes it harder for users or orchestrators to understand that the skill can persist secrets and communicate externally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs the model to collect an API key from the user and save it, but does not clearly warn that the credential will be persisted or explain retention and access implications. This creates avoidable secret-handling risk because users may provide credentials without informed consent about storage behavior.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill creates a natural-language flow for soliciting a secret from the user and then persisting it for future use. In a hostile or misdescribed skill context, this materially increases the chance of credential capture, long-term retention, and later misuse, especially since the backend identity is already inconsistent with the advertised purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The workflow and project structure appear copied from another skill, creating inconsistencies between the stated HackerNews purpose and the likely actual target service. This increases the risk of misrouting data, invoking unintended tools, or misleading users about where their requests and secrets are sent.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The example tool invocation in the workflow references a different function than the tools actually defined below, indicating the document is internally inconsistent. In agent systems, inconsistent instructions can cause wrong-tool execution, accidental data disclosure to unintended endpoints, or bypass of expected safety review paths.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Instructing the model to directly display raw API response data can expose sensitive fields, reflected user inputs, hidden metadata, or backend error details that were never meant for end users. This is more dangerous here because the actual upstream service identity is unclear, so the returned payload may contain unrelated or overbroad data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code performs a network POST to an external API and sends both user-supplied parameters and a credential header. While the behavior is implemented clearly, there is no confirmation prompt, user-facing disclosure, or warning in comments/docstrings near the transmission to inform users that data and credentials are being sent off-host.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Settings类的文档字符串明确表述该配置属于“高考Skill”,而清单说明当前技能是HackerNews数据服务。这不是单纯的信息缺失,而是直接指向另一类产品/用途,容易误导审计者和调用方对该代码真实意图的判断。

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This module implements persistent API key storage to a local .env file even though the advertised skill purpose is HackerNews search and analysis. Persisting credentials on disk increases the chance of accidental disclosure through source control, backups, local compromise, or other tooling that reads project files, and the capability is not obviously necessary from the stated skill context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code stores the API key in .env without any user-facing disclosure, warning, or consent flow. Silent credential persistence is dangerous because users may assume the key is ephemeral while it is actually left on disk where it can be exposed through repository inclusion, shared workspaces, logs, or endpoint compromise.

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 range instead of an exact pinned version, making builds non-reproducible and allowing different environments to resolve to different releases. This increases supply-chain risk and makes it harder to ensure that a deployed version is not affected by known vulnerabilities.

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
88% confidence
Finding

Requests has multiple published advisories, and because the manifest does not pin a version, there is no way to verify from this file alone whether deployments will use a patched or affected release. The issue is therefore not that requests is inherently vulnerable here, but that dependency ambiguity can allow a vulnerable version to be installed.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Using an unpinned pydantic version means the installed package may vary over time or across systems, undermining reproducibility and potentially introducing vulnerable or breaking releases unexpectedly. In an agent-facing service, this can affect reliability and security posture if dependency resolution pulls an unsafe version.

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, and the unpinned specification prevents verification that the resolved version is outside affected ranges. This creates avoidable uncertainty in the supply chain and may result in vulnerable versions being pulled during installation.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

An unpinned pydantic-settings dependency allows package resolution to drift, which can silently introduce vulnerable or incompatible releases into deployments. This is a supply-chain hygiene issue rather than an immediate exploit, but it weakens confidence in the runtime environment.

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

Unverifiable Dependency: pydantic-settings has 1 known advisory(ies) (CVE-2026-58203 (pydantic-settings: NestedSecretsSettingsSource follows symlinks outside secrets_)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding

Because pydantic-settings is not pinned, the manifest cannot demonstrate whether installed versions are patched against known advisories. This is a low-severity but real dependency governance weakness that can matter if the package interacts with secrets or filesystem-based settings.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

Specifying python-dotenv with only a minimum version permits uncontrolled upgrades and inconsistent dependency resolution, which can expose deployments to newly introduced vulnerable versions. This is especially relevant for software that may load environment configuration at runtime.

Content

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

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

Static analysis

No suspicious patterns detected.