Back to skill

Security audit

letpub-skills

Security checks for vulnerabilities and agentic risk

Overview

The skill does useful LetPub journal lookups, but it stores and logs LetPub account credentials/session cookies in ways users should review carefully before installing.

Install only if you are comfortable with this skill handling your LetPub login. Do not put reusable passwords or live browser cookies in the project directory unless you can protect those files, keep them out of version control/logs/backups, and rotate/revoke them if exposed.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/login.py:93
Finding

Reusable account credentials are stored in plaintext inside the project directory

Content
View full analysis
tuple: """ 从 assets/credentials.json 加载账号密码 Returns: (email, password) 元组 """ credentials_file = os.path.join(os.path.dirname(__file__), '..', 'assets', 'credentials.json') if not os.path.exists(credentials_file): raise FileNotFoundError(f"找不到账号配置文件: {credentials_file},请先创建并填入 email 和 password") with open(credentials_file, 'r', encoding='utf-8') as f: data = json.load(f) email = data.get('email', '').strip() password = data.get('password', '').strip() if not email or not password: raise ValueError("assets/credentials.json 中 email 或 password 为空,请填写") return email, password ``` The documented configuration in `SKILL.md:59-69` instructs users to populate the file as follows: ```json { "email": "your@email.com", "password": "your_password" } ``` ### Technical Analysis The Skill stores a reusable LetPub email address and password in an unencrypted JSON file under `assets/`. The implementation does not use an operating-system credential store, encrypted secret storage, or restrictive file-permission enforcement. Because the secret is located inside the project tree, it can also be included inadvertently in source-control commits, archives, backups, diagnostic bundles, or Skill redistribution. Sending the credentials to LetPub's declared HTTPS login endpoint is necessary for authenticated comment retrieval and is not, by itself, unauthorized exfiltration. The vulnerability is the persistent plaintext storage model rather than the first-party HTTPS login operation. ### Attack Path 1. A user follows `SKILL.md` and writes a valid LetPub email address and password into `assets/credentials.json`. 2. The plaintext file remains in the project directory after authentication. 3. Anot ...[truncated 911 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/login.py:57
Finding

Authentication session cookies are logged in full and persisted without access-control hardening

Content
View full analysis
str: """ 一键登录并保存 cookies Args: email: 登录邮箱 password: 登录密码 Returns: 登录后的 cookies 字符串 """ cookies_str, response = login(email, password) # 检查登录结果 print(f"登录响应: {response.text}") print(f"获取到的 cookies: {cookies_str}") # 保存到文件 save_cookies(cookies_str) print("Cookies 已保存到 assets/cookies.json") return cookies_str ``` ### Technical Analysis Session cookies such as `PHPSESSID` are bearer credentials: possession may be sufficient to act as the authenticated user until the session expires or is revoked. `auto_login()` prints the complete cookie string to standard output. Depending on the execution environment, this value can be retained in terminal capture, CI/CD logs, centralized logging, Agent transcripts, notebooks, or diagnostic output. The function also prints the complete login response, which unnecessarily increases the chance that server-returned account or authentication information will enter logs. `save_cookies()` persists the same bearer token as plaintext under the project directory. It relies on default file creation behavior and does not explicitly enforce owner-only permissions. The documentation also recommends manually copying browser cookies into this file, increasing exposure of an existing authenticated browser session. The cookie is transmitted on ...[truncated 1558 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (31)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill is presented as a data retrieval utility, but it also instructs the system to read local credentials, log into a third-party service, persist authentication cookies, and automatically renew sessions. Because these are sensitive authentication behaviors, under-describing them increases the risk of unintended credential exposure and user surprise.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill is presented as a data retrieval utility, but it also instructs the system to read local credentials, log into a third-party service, persist authentication cookies, and automatically renew sessions. Because these are sensitive authentication behaviors, under-describing them increases the risk of unintended credential exposure and user surprise.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill is presented as a data retrieval utility, but it also instructs the system to read local credentials, log into a third-party service, persist authentication cookies, and automatically renew sessions. Because these are sensitive authentication behaviors, under-describing them increases the risk of unintended credential exposure and user surprise.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill is presented as a data retrieval utility, but it also instructs the system to read local credentials, log into a third-party service, persist authentication cookies, and automatically renew sessions. Because these are sensitive authentication behaviors, under-describing them increases the risk of unintended credential exposure and user surprise.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

This section explicitly directs users to place email/password credentials into a local credentials.json file. Direct credential collection and local plaintext storage are dangerous because any compromise of the workspace, logs, backups, or version control can expose third-party account access.

Content

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

评论需要登录才能获取。脚本已支持自动登录续期:

  1. 在 letpub_skills/assets/credentials.json 填入账号密码:
json
{ "email": "your@email.com", "password": "your_password" }

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

The documented behavior automatically reads credentials.json and re-authenticates transparently when cookies expire. Silent credential reuse increases the sensitivity of the skill because it can access and act on stored secrets without an explicit fresh user action, expanding the blast radius if the skill is misused or compromised.

Content

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

{ "email": "your@email.com", "password": "your_password" }

text

2. 调用 `get_journal_comments()` 时,若 cookie 已失效,脚本会**自动读取 credentials.json 重新登录**并更新 `cookies.json`,对调用者完全透明。

3. 如需手动触发登录:

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This passage confirms automated detection of cookie failure followed by automatic re-login using credentials.json and cookie updates. Automated secret use coupled with persistent session material makes the skill more dangerous, since compromised local files or over-broad agent permissions could yield continued authenticated access.

Content

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

md
> - **无学术诚信负评**(任一评论命中以下关键词即整体淘汰,**一票否决**):`学术道德`、`学术不端`、`抄袭`、`剽窃`、`政治原因`、`分赃`、`黑幕`、`要求引用`、`强制引用`
>
> **去重与 Cookie 失效检测**:
> `fetch_all_comments` 已内置基于 `floor` 的去重逻辑。若连续 2 页拿到的都是同一批评论(即新页评论与已有集合完全重合),说明 cookie 很可能已失效——此时 `get_journal_comments` 会**自动触发重新登录**(读取 `credentials.json` 并更新 `cookies.json`),然后重试。若续期后仍无新数据,函数会自动停止翻页,不会无限循环。
>
> 在最终输出中,对每个推荐期刊附上审核结果摘要:评论条数、平均分、慢审比例、是否存在诚信负评。

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The directory structure documents dedicated storage locations for credentials and cookies inside the skill workspace. Publishing or standardizing these paths makes secret discovery easier for any other code or agent component with filesystem access, and it normalizes insecure local secret persistence.

Content

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

md
letpub_skills/
├── SKILL.md                    # 操作手册(本文件)
├── assets/
│   ├── credentials.json        # 账号密码(用户填写)
│   └── cookies.json            # 登录 cookies(自动生成,无需手动修改)
├── scripts/
│   ├── login.py                # 自动登录与 cookie 续期

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The function table explicitly advertises loading credentials from credentials.json and automatic login/session renewal. This confirms that credential access is a core behavior, increasing the attack surface if the skill is integrated without strict permission controls or secure secret handling.

Content

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

md
| 模块 | 函数 | 说明 |
|------|------|------|
| `login` | `load_credentials()` | 从 credentials.json 读取账号密码 |
| `login` | `auto_login(email, password)` | 登录并保存 cookies |
| `login` | `ensure_logged_in()` | 检查 cookie 有效性,失效时自动续期 |
| `search_journal` | `search_journal(name)` | 自动补全搜索,返回 `journal_id` |

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

This function loads account credentials from a local JSON file, establishing explicit credential access behavior. In isolation credential use may be legitimate, but in this skill it is risky because the capability is broader than the advertised purpose and relies on plaintext local secret storage that can be stolen or accidentally exposed.

Content

Scanner excerpt · scripts/login.py (reported line 95)May include surrounding context.

python
def load_credentials() -> tuple:
    """
    从 assets/credentials.json 加载账号密码

    Returns:
        (email, password) 元组

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

Opening assets/credentials.json to read email and password means the skill accesses stored credentials directly from disk. If the workspace is shared, synced, backed up, or committed, those credentials can be compromised and reused by an attacker.

Content

Scanner excerpt · scripts/login.py (reported line 100)May include surrounding context.

python
Returns:
        (email, password) 元组
    """
    credentials_file = os.path.join(os.path.dirname(__file__), '..', 'assets', 'credentials.json')
    if not os.path.exists(credentials_file):
        raise FileNotFoundError(f"找不到账号配置文件: {credentials_file},请先创建并填入 email 和 password")
    with open(credentials_file, 'r', encoding='utf-8') as f:

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The code validates that credentials.json contains non-empty email and password, confirming dependence on stored account secrets as a normal execution path. This reinforces the insecure operational pattern of persistent local credentials rather than ephemeral or protected secret handling.

Content

Scanner excerpt · scripts/login.py (reported line 108)May include surrounding context.

python
email = data.get('email', '').strip()
    password = data.get('password', '').strip()
    if not email or not password:
        raise ValueError("assets/credentials.json 中 email 或 password 为空,请填写")
    return email, password

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

When cached cookies are absent or deemed invalid, the script automatically falls back to loading stored credentials and re-authenticating. This creates a persistent credential-backed renewal loop that increases the exposure window and makes unauthorized reuse easier if either the credential file or cookie store is compromised.

Content

Scanner excerpt · scripts/login.py (reported line 150)May include surrounding context.

python
if existing and 'PHPSESSID=' in existing:
            return existing

    # cookies 无效或强制续期,使用 credentials.json 重新登录
    email, password = load_credentials()
    cookies_str, response = login(email, password)
    response_text = response.text.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The error path explicitly references assets/credentials.json as the expected source of account secrets, further embedding insecure file-based secret handling into the workflow. While this line alone does not exfiltrate credentials, it indicates a design centered around local plaintext secret storage.

Content

Scanner excerpt · scripts/login.py (reported line 156)May include surrounding context.

python
response_text = response.text.strip()

    if not response_text.startswith('SUCCESS'):
        raise RuntimeError(f"自动登录失败,响应: {response_text},请检查 assets/credentials.json 中的账号密码")

    save_cookies(cookies_str)
    return cookies_str

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The main execution path automatically reads credentials and initiates login, making credential access a default behavior rather than an explicit, narrowly scoped action. In an agent-skill context this is especially sensitive because simply running the script consumes stored secrets and may produce persistent session artifacts.

Content

Scanner excerpt · scripts/login.py (reported line 163)May include surrounding context.

python
if __name__ == "__main__":
    # 从 credentials.json 读取账号密码,自动登录并保存 cookies
    email, password = load_credentials()
    print(f"使用账号: {email}")
    cookies = auto_login(email, password)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documentation describes capabilities that require network access plus local file reads/writes for credentials and cookies, but it declares no explicit tool scope or permission boundaries. This creates an authorization ambiguity where a host agent may expose broader capabilities than users expect, especially since the skill also performs authentication state management.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation instructs users to store raw account credentials in a local JSON file without any warning about plaintext secret storage, file permissions, leakage risk, or safer alternatives. This materially raises the chance of credential theft through repository commits, backups, local compromise, or accidental sharing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation instructs users to copy authenticated LetPub session cookies from their browser into a local JSON file, which is effectively handling live session credentials. Storing reusable session tokens in plaintext without warnings about sensitivity, scope, expiration, or storage hygiene increases the risk of credential theft, account hijacking, and unintended reuse by other tools or users on the same system.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description and the main usage documentation are written entirely in Chinese, and the examples rely on Chinese category names such as "计算机科学" and "计算机:人工智能". This indicates a language/locale constraint for using the skill, but the file does not offer an English alternative, user opt-in, or a justification that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code detects expired cookies and then silently calls ensure_logged_in(force=True) before retrying the request with refreshed authentication. Although the function docstrings describe cookie handling, there is no user-facing prompt, warning, or visible logging that the skill may perform a forced login and transmit authenticated session data over the network.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file implements login, credential loading, and persistent authenticated session handling, which exceeds the stated skill purpose of journal querying and recommendation. This mismatch matters because users may not expect the skill to collect, store, and reuse account secrets, increasing the chance of over-privileged behavior and accidental credential exposure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code reads credentials from a local file and stores reusable authenticated cookies on disk, creating a local credential and session-token cache. If the host, repository, logs, backups, or workspace files are exposed, an attacker can reuse those secrets to hijack the user's LetPub account without knowing the password.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script prints both the login response and the full session cookies to stdout. Console output is commonly captured by terminals, CI logs, shell history tooling, or agent transcripts, so this can directly leak active session tokens that enable account takeover.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code expects plaintext credentials in assets/credentials.json and writes session cookies to disk without any user-facing warning or safeguards. In the context of an agent skill, this is more dangerous because users may not realize the skill creates persistent local authentication artifacts that can be copied, committed, or harvested by other processes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The instructions require the AI to read and use CATEGORY_CN and SUBCATEGORY_CN, and the overall skill description is written as if Chinese-language categories are mandatory. This can violate language/locale policy when users are not given a choice of language or told that the workflow is China/Chinese-specific.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/login.py:151

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
SKILL.md:75