Back to skill

Security audit

blog-big-kimi-kit

Security checks for vulnerabilities and agentic risk

Overview

This blog-management skill is not clearly malicious, but it can modify public blog data, upload local files, and reads unnecessary credential-like data for an unauthenticated API.

Install only if you control the target blog API and are comfortable with an agent creating, deleting, and uploading live content there. Avoid using it with sensitive local file paths, do not place credentials under the BLOG_BIG_KIMI_KIT prefix for this no-auth API, prefer HTTPS, and require explicit human confirmation before deletes, hard deletes, account creation, or uploads.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
blog-big-kimi-kit.py:109
Finding

Unrestricted Base URL Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: blog-big-kimi-kit.py, lines 109-128 and 167-190
Vulnerability Type: Unrestricted outbound request destination
Risk Level: Medium

Vulnerable Code

python
def _get_base_url():
    """获取 API base URL——4 级优先级(与凭据读取一致)。"""
    creds = _load_credentials()
    base_url = creds.get('base_url', '').rstrip('/')
    if not base_url:
        print("未检测到 %s_BASE_URL 环境变量,也未在 .project-info/ 找到配置。" % _CRED_PREFIX)
        print("请输入目标系统 API 地址(如 http://host:port):")
        base_url = input("> ").strip().rstrip('/')
        if not base_url:
            print("错误:API 地址不能为空", file=sys.stderr)
            sys.exit(3)
        if not (base_url.startswith("http://") or base_url.startswith("https://")):
            print("错误:地址必须以 http:// 或 https:// 开头", file=sys.stderr)
            sys.exit(3)
        print("提示:可通过 export %s_BASE_URL=\"%s\" 永久设置,避免每次输入。" % (_CRED_PREFIX, base_url))
    return base_url
python
base_url = _get_base_url()
creds = _load_credentials()
auth_result = _build_auth(creds)

url = f"{base_url}{path}"

try:
    if method == 'GET':
        resp = requests.get(url, params=params, timeout=30, **auth_kwargs)
    elif method == 'POST':
        resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
    elif method == 'PUT':
        resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
    elif method == 'PATCH':
        resp = requests.patch(url, json=payload, timeout=30, **auth_kwargs)
    elif method == 'DELETE':
        resp = requests.delete(url, params=params, timeout=30, **auth_kwargs)

Technical Analysis

The API destination can be obtained from project configuration, an environment variable, or interactive input. The only validation applied to an interactively supplied value is that it starts with http:// or https://. Values loaded from configuration or the environment do not receive even that validation.

The implementation does ...[truncated 2101 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require an explicit allowlist of approved API hostnames and ports.
  2. Parse the destination with urllib.parse.urlsplit rather than checking string prefixes.
  3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved addresses using Python's ipaddress module.
  4. Explicitly block cloud metadata destinations, including IPv4 and IPv6 equivalents.
  5. Disable redirects with allow_redirects=False, or validate every redirect destination using the same checks.
  6. Revalidate the connected address to mitigate DNS rebinding and time-of-check/time-of-use discrepancies.
  7. Require HTTPS except for explicitly approved local development environments.
  8. Reject URLs containing user information, fragments, unexpected paths, or unsupported ports.
  9. Separate configuration of the trusted service from task-controlled input so untrusted content cannot silently change the destination.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
blog-big-kimi-kit.py:44
Finding

No-Authentication Mode Unnecessarily Reads Credential Material

Content
View full analysis

Vulnerability Details

File Location: blog-big-kimi-kit.py, lines 44-105 and 169-171
Vulnerability Type: Excessive access to sensitive configuration
Risk Level: Medium

Vulnerable Code

python
def _load_credentials():
    """获取认证凭据——4 级优先级(与 base_url 一致)。

    1. 项目知识:递归扫描 .project-info/ 下所有 JSON 文件(secrets.{PREFIX}_*)
    2. 环境变量:扫描 {PREFIX}_* 开头变量(项目知识缺失时回退)
    3. 当前上下文:A2A context 已注入的环境变量(已包含在步骤 2)
    4. 交互输入:以上都无时提示用户输入
    """
    creds = {}
    creds.update(_load_from_project_knowledge())
    for k, v in os.environ.items():
        u = k.upper()
        if u.startswith(_CRED_PREFIX):
            if 'USERNAME' in u or u.endswith('_USER'):
                creds.setdefault('username', v)
            if 'PASSWORD' in u or u.endswith('_PASS'):
                creds.setdefault('password', v)
            if 'TOKEN' in u:
                creds.setdefault('token', v)
            if 'API_KEY' in u:
                creds.setdefault('api_key', v)
            if 'BASE_URL' in u:
                creds.setdefault('base_url', v)
    return creds
python
def _load_from_project_knowledge():
    """从 .project-info/ 目录递归查找 JSON 配置文件,读取 secrets.{PREFIX}_* 字段。

    不固定文件名——扫描所有 .json 文件,检查是否含 secrets/config 字段。
    .project-info/ 由 grape worker 物化到 agent 工作目录(cwd)下,直接在当前目录查找。
    base_url 和 secrets 都严格按 {PREFIX}_ 前缀精确匹配,不做 fallback。
    """
    import glob
    creds = {}
    for filepath in glob.glob('.project-info/**/*.json', recursive=True):
        try:
            with open(filepath) as f:
                data = __import__('json').load(f)
            secrets = data.get('secrets', {})
            config = data.get('config', {})
            prefix = _CRED_PREFIX + '_'
            for key, val in secrets.items():
                if key.upper().startswith(prefix):
                    if 'USERNAME' in key.upper():
                        creds.setdefault('username', val)
                    if 'PASSWORD' in key.upper():
                        c
...[truncated 2842 chars]
Remediation
View remediation

Remediation Suggestions

  1. When _AUTH_TYPE == "none", do not invoke a generic credential loader.
  2. Read only the exact BLOG_BIG_KIMI_KIT_BASE_URL environment variable.
  3. Do not inspect secrets objects, password fields, token fields, usernames, or API keys for an unauthenticated API.
  4. Replace recursive discovery of .project-info/**/*.json with a specifically named and documented configuration file.
  5. Parse only the exact expected configuration key and reject unknown credential-related fields.
  6. Avoid broad environment iteration; use os.environ.get() for the single required variable.
  7. Keep authentication-specific loading code isolated and unreachable unless an authenticated mode is explicitly enabled.
  8. Add tests proving that no secret files or credential environment variables are read in no-authentication mode.

T09 · Insecure Skill Coding Practices

Warning
Location
blog-big-kimi-kit.py:338
Finding

User Passwords Can Be Exposed Through Command-Line Arguments and Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: blog-big-kimi-kit.py, lines 123-124, 338-350, and 622-628
Vulnerability Type: Insecure handling and transmission of sensitive data
Risk Level: Medium

Vulnerable Code

python
if not (base_url.startswith("http://") or base_url.startswith("https://")):
    print("错误:地址必须以 http:// 或 https:// 开头", file=sys.stderr)
    sys.exit(3)
python
def cmd_create_user(args):
    """能力 L:创建用户"""
    # POST /api/users
    payload = {'uname': args.uname}
    if args.phone is not None:
        payload['phone'] = args.phone
    if args.pwd is not None:
        payload['pwd'] = args.pwd
    if args.email is not None:
        payload['email'] = args.email
    if args.img is not None:
        payload['img'] = args.img
    result = _api_request('POST', '/api/users', payload=payload)
    return result
python
p_cu = sub.add_parser('create-user', help='创建用户')
p_cu.add_argument('--uname', type=str, required=True, help='用户名(必填)')
p_cu.add_argument('--phone', type=str, default=None, help='手机号')
p_cu.add_argument('--pwd', type=str, default=None, help='密码')
p_cu.add_argument('--email', type=str, default=None, help='邮箱')
p_cu.add_argument('--img', type=str, default=None, help='头像,默认 img/moren.jpg')

Technical Analysis

The create-user command accepts a password through the --pwd command-line argument and places it directly into the JSON request body. Command-line secrets may be exposed through:

  • Shell history files.
  • Process listings and process-inspection interfaces.
  • Terminal logs.
  • Automation logs that record invoked commands.
  • Error reports or job metadata.

The URL validation explicitly accepts both HTTP and HTTPS. If HTTP is selected, the password is transmitted without transport encryption. Any party able to observe the network path can recover the JSON payload. Because the destination is not restricted, a misleading or malicious base URL can also intentionally collect the submitted credential. ...[truncated 1230 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require HTTPS for every operation that sends passwords or other sensitive personal data.
  2. Reject http:// for create-user; if plaintext HTTP is needed for local testing, require a separate explicit development-only override.
  3. Remove the --pwd command-line option.
  4. Read passwords through getpass.getpass() or protected standard input so they do not appear in process arguments or shell history.
  5. For automation, support a restrictive secret file descriptor or a dedicated secret manager rather than a command-line value.
  6. Ensure debug logging and exception handlers never serialize request bodies containing passwords.
  7. Display a clear error if certificate verification fails; do not offer an insecure verification bypass.
  8. Document that passwords must be unique and must not be reused across services.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (19)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
84% confidence
Finding

The skill documents parameterization of destructive endpoints, including article deletion with an option to disable soft-delete, but does not describe strong validation, authorization expectations, or confirmation gates around those parameters. In the context of a public unauthenticated API, attacker-influenced inputs could drive harmful state-changing requests, including irreversible deletion, making parameter abuse more dangerous than in a read-only skill.

Content

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

md
1. **API 路径拼写 lables**。标签端点实际路径为 `/api/lables`(非 `labels`),子命令用正确拼写 `labels`,脚本内部请求时用实际路径 `lables`。
2. **文章详情返回嵌套结构**。`GET /api/articles/{id}` 返回 `{"code":200,"data":{"article":{...},"comments":[...]}}`,article 和 comments 是嵌套字段。
3. **文章删除默认软删除**。`DELETE /api/articles/{id}` 默认 `soft=true`,需用 `restore-article` 恢复。传 `--soft false` 硬删除。
4. **文件上传用 multipart/form-data**。`POST /api/upload` 字段名 `file`,`/api/upload/multiple` 字段名 `files`,不是 JSON body。脚本用 `files=` 参数传递。
5. **分页参数 page/size**。`GET /api/articles` 支持 `page`(默认1)、`size`(默认10,最大100)、`lid`(标签筛选,默认0=不限)、`keyword`(关键词搜索)。
6. **说说创建 content 必填**。`POST /api/moods` 的 `content` 字段必填,`title` 和 `src` 可选。

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
81% confidence
Finding

The code iterates over environment variables to discover any values with the skill prefix, including credentials and base URL, rather than reading only narrowly scoped keys. In an agent setting this broad secret-harvesting pattern increases exposure of sensitive configuration and can combine with arbitrary base URL input to route authenticated requests or file uploads to an unintended endpoint.

Content

Scanner excerpt · blog-big-kimi-kit.py (reported line 64)May include surrounding context.

python
# 1. 项目知识优先
    creds.update(_load_from_project_knowledge())
    # 2. 环境变量回退:项目知识缺失的字段从环境变量补充
    for k, v in os.environ.items():
        u = k.upper()
        if u.startswith(_CRED_PREFIX):
            if 'USERNAME' in u or u.endswith('_USER'):

Tainted flow: 'files' from open (line 443, file read) → requests.post (network output)

High
Category
Data Flow
Confidence
92% confidence
Finding

This POST helper can transmit file handles opened from local paths to a remote server, and the upload commands accept arbitrary user-supplied file paths. In an agent context, that creates a real data-exfiltration risk because sensitive local files in the workspace or host environment could be sent to an attacker-controlled base URL.

Content

Scanner excerpt · blog-big-kimi-kit.py (reported line 195)May include surrounding context.

python
if method == 'GET':
            resp = requests.get(url, params=params, timeout=30, **auth_kwargs)
        elif method == 'POST':
            resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
        elif method == 'PUT':
            resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
        elif method == 'PATCH':

Tainted flow: 'files' from open (line 443, file read) → requests.put (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · blog-big-kimi-kit.py (reported line 197)May include surrounding context.

python
elif method == 'POST':
            resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
        elif method == 'PUT':
            resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
        elif method == 'PATCH':
            resp = requests.patch(url, json=payload, timeout=30, **auth_kwargs)
        elif method == 'DELETE':

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill exposes effective capabilities to read project files, inspect environment variables, and make network requests, but it does not declare any explicit tool scope or allowed-tools policy. In a public, unauthenticated blog-management skill, this increases the chance the agent can overreach into unintended local data or external targets without a clear least-privilege boundary.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill supports destructive actions including delete operations and file deletion/upload, but does not present a prominent user-facing warning or confirmation requirement about data loss, permanence, or target validation. Because the API is explicitly unauthenticated and public, accidental or manipulated invocation could lead to unauthorized content deletion or unwanted file operations with little friction.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation explicitly states the API is public and unauthenticated while exposing sensitive state-changing operations including article/user/comment/message creation, update and deletion, plus file upload and file deletion. In the context of a blog publishing skill, this enables arbitrary content tampering, account creation, spam, destructive deletion, and possible malicious file hosting, so the risk is far beyond a documentation issue if the implementation matches the spec.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill is framed as blog content publishing, but it also exposes user enumeration and user creation operations. That broader-than-advertised scope increases the chance an agent or user invokes account-management actions without realizing the privilege and security implications.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · blog-big-kimi-kit.py (reported line 92)May include surrounding context.

python
for filepath in glob.glob('.project-info/**/*.json', recursive=True):
        try:
            with open(filepath) as f:
                data = __import__('json').load(f)
            secrets = data.get('secrets', {})
            config = data.get('config', {})
            prefix = _CRED_PREFIX + '_'

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · blog-big-kimi-kit.py (reported line 195)May include surrounding context.

python
if method == 'GET':
            resp = requests.get(url, params=params, timeout=30, **auth_kwargs)
        elif method == 'POST':
            resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
        elif method == 'PUT':
            resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
        elif method == 'PATCH':

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · blog-big-kimi-kit.py (reported line 197)May include surrounding context.

python
elif method == 'POST':
            resp = requests.post(url, json=payload, files=files, timeout=30, **auth_kwargs)
        elif method == 'PUT':
            resp = requests.put(url, json=payload, files=files, timeout=30, **auth_kwargs)
        elif method == 'PATCH':
            resp = requests.patch(url, json=payload, timeout=30, **auth_kwargs)
        elif method == 'DELETE':

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill implements create-user even though its stated purpose is content publishing, enabling account provisioning on a remote system outside the expected task boundary. In a no-auth public-API model, this can facilitate unauthorized account creation, abuse of backend resources, or unexpected identity-management actions by an agent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The upload commands read arbitrary local files and send them to the configured remote API without any explicit warning about data sensitivity. In an agent environment, users may not understand that specifying a path can transmit secrets, SSH keys, config files, or proprietary project data off-host.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file mandates a specific comment format beginning with a fixed prefix and Chinese-language response structure, but does not offer user language selection or explain why Chinese-only output is required. This can conflict with language/locale policy expectations when the user or environment may require another language.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

文件标题、说明、端点描述和数据模型注释均仅以中文呈现,没有提供多语言选项,也没有说明该技能或文档仅面向特定中文使用场景。根据规则,未经用户选择而强制单一语言/locale 可能构成自然语言层面的组织策略问题。

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specifier requests>=2.20.0 is unpinned, so installations may resolve to different versions over time. This weakens reproducibility and makes it harder to ensure vulnerable or incompatible releases are excluded, especially in a skill that interacts with many external blog APIs and may be deployed repeatedly in different environments.

Content

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

text
requests>=2.20.0

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

Because requests is not pinned, there is no way to verify that the installed version is free from known advisories, including recent issues affecting credential handling and request validation. In a blog publishing skill that may authenticate to backend APIs and perform outbound HTTP requests, an affected requests version could expose secrets or weaken transport security depending on runtime resolution.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

This JSON manifest enumerates many invocation commands for the skill, but it does not define any activation boundaries, negative examples, or context limits for when these commands should be used. In a manifest-style file, the lack of explicit trigger scope can make invocation semantics overly broad and increase the chance of unintended use.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The user-facing natural-language fields in descriptions, cleanup instructions, environment variable annotations, and notes are written in Chinese throughout the file, with no indication that language is optional or configurable. Per the policy, a skill should not impose a specific language or locale without user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.