Back to skill

Security audit

猎聘求职助手

Security checks for vulnerabilities and agentic risk

Overview

This Liepin job-assistant skill matches its stated purpose, but it handles account credentials and can change resume or application state with weak credential handling and limited enforced user-control safeguards.

Review carefully before installing. Prefer setting LIEPIN_TOKEN through a secure environment or secret manager, do not paste real tokens into chat, avoid using the plaintext config.json path, and require explicit review before any resume edit or job application. Treat the token as account access that can expose resume data and perform Liepin actions until it expires or is revoked.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/set-token.js:44
Finding
Liepin Token Is Accepted Through Process Arguments and Stored in Plaintext## Vulnerability Details **File Location**: `scripts/set-token.js:44-58` **Vulnerability Type**: Plaintext credential exposure through command-line arguments and insecure file storage **Risk Level**: Medium ### Vulnerable Code ```javascript var args = process.argv.slice(2); if (args.length === 0 || args[0] === '--show') { showStatus(); } else if (args[0] === '--clear') { if (fs.existsSync(configPath)) { fs.unlinkSync(configPath); console.log('已清除 config.json'); } else console.log('没有 config.json 可清除'); } else { var dir = path.dirname(configPath); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync(configPath, JSON.stringify({ token: args[0] }, null, 2)); console.log('已保存到 config.json'); console.log('Tip: 也可以设置环境变量 LIEPIN_TOKEN 更安全'); } ``` The insecure invocation pattern is also explicitly documented at `SKILL.md:39-43`: ```bash node scripts/set-token.js <token> ``` ### Technical Analysis The credential is read directly from `process.argv`. Depending on the operating system and execution environment, command-line arguments can be exposed through process inspection utilities, monitoring systems, audit logs, terminal history, or wrapper scripts. The token is then serialized directly into `config.json` using `fs.writeFileSync` without an explicit restrictive file mode. Consequently, the file's permissions depend on the process umask and any permissions already associated with the file. The implementation does not verify that the resulting file is readable only by its owner. The credential reportedly remains valid for up to 90 days and authorizes authenticated Liepin operations, including access to résumé information and account-mutating actions. ### Attack Path 1. A user follows the documented command and passes the Liepin token as a command-line argument. 2. A local user, process monitor, shell-history collector, or logging integration records ...[truncated 948 chars]
Remediation
## Remediation Suggestions 1. Do not accept credentials as positional command-line arguments. Read the token from a non-echoing interactive prompt, standard input, or an operating-system credential store. 2. Create `config.json` with an explicit owner-only mode such as `0600`: ```javascript fs.writeFileSync( configPath, JSON.stringify({ token: token }, null, 2), { mode: 0o600 } ); ``` 3. If the file already exists, verify and correct its permissions before writing. 4. Ensure the containing directory is not writable or readable by unintended users. 5. Prefer a platform secret store or a dedicated secrets manager rather than plaintext JSON. 6. Update `SKILL.md` and `references/api.md` so examples never place real credentials in command-line arguments. 7. Document token revocation and rotation procedures for suspected exposure. 8. Consider rejecting tokens with leading or trailing whitespace and avoid printing any token-derived substring unless operationally necessary.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/liepin-mcp.js:133
Finding
Caller-Controlled MCP Tool Dispatch Lacks an Allowlist and Enforced Confirmation## Vulnerability Details **File Location**: `scripts/liepin-mcp.js:52-68` and `scripts/liepin-mcp.js:133-145` **Vulnerability Type**: Unrestricted dispatch of authenticated, potentially state-changing MCP operations **Risk Level**: Medium ### Vulnerable Code Tool names and arguments are inserted directly into the authenticated request: ```javascript function mcpRequest(toolName, arguments_) { return new Promise(function(resolve, reject) { var config = loadConfig(); var id = Date.now(); var bodyObj = { jsonrpc: '2.0', id: id, method: 'tools/call', params: { name: toolName, arguments: arguments_ || {} } }; var body = JSON.stringify(bodyObj); ``` The values originate directly from command-line input without an allowlist, operation-specific schema validation, or confirmation gate: ```javascript var toolName = args[0]; var toolArgs = {}; if (args.length > 1) { try { toolArgs = JSON.parse(args[1]); } catch (e) { console.error('Invalid params JSON: ' + args[1]); process.exit(1); } } mcpRequest(toolName, toolArgs) ``` ### Technical Analysis The wrapper forwards any caller-provided `toolName` and JSON object to the remote MCP endpoint while attaching the user's Liepin token. It does not restrict calls to the methods documented by the Skill, distinguish read-only methods from state-changing methods, or validate operation-specific argument types and fields. `SKILL.md:94` instructs the Agent to display job details and obtain user confirmation before every application. This is a documentation-only control. The executable client does not require or verify confirmation before dispatching `user-apply-job`, résumé modification methods, or other server-recognized methods. Arbitrary tool names are not equivalent to local code execution because they are sent to the fixed Liepin HTTPS endpoint. Nevertheless, the desi ...[truncated 1688 chars]
Remediation
## Remediation Suggestions 1. Define a strict allowlist of supported MCP methods rather than forwarding arbitrary names. 2. Maintain operation-specific JSON schemas and reject unknown fields, missing fields, invalid types, and out-of-range values before sending requests. 3. Separate read-only operations from state-changing operations. 4. Require an explicit, short-lived confirmation artifact for job applications and résumé modifications. The confirmation should bind the exact operation and normalized arguments, rather than relying on a generic Boolean flag. 5. Display the target job or exact résumé changes before requesting approval. 6. Reject execution if the confirmed operation differs from the final request. 7. Consider exposing dedicated command handlers instead of a generic arbitrary-tool dispatcher. 8. Log state-changing operations without recording tokens or unnecessary personal data. 9. Keep server-side authorization and validation enabled because client-side controls alone cannot protect against a modified client.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (10)

Missing User Warnings

High
Confidence
98% confidence
Finding
The documentation explicitly instructs users to send their Liepin authentication token in chat, which encourages disclosure of a sensitive credential through an unsafe channel. If chat logs are retained, exposed to plugins, or reviewed by operators, the token could be reused to access the user's account and perform job-search, resume, or application actions on their behalf.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill documents use of the LIEPIN_TOKEN environment variable and token-setting scripts, but it does not declare an explicit tool scope or permissions boundary. That mismatch can lead to overbroad access assumptions and makes it harder to audit whether the skill should be allowed to read environment secrets, increasing the risk of unintended secret access in agent environments.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger phrases include very broad terms such as '找工作', '搜职位', and '投简历', which are common in ordinary conversation and can cause the skill to activate when the user did not specifically intend to use Liepin. Unintended activation is risky here because the skill handles credentials, resume data, and potentially irreversible actions like job applications.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill supports viewing and modifying resumes, which necessarily involves highly sensitive personal data, but the description does not clearly warn users that this data will be transmitted to an external Liepin service. Without an explicit disclosure, users may unknowingly expose PII, employment history, education details, and other sensitive resume content to a third party.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The API reference documents actions that can modify resume data and submit job applications, but it does not warn that these operations affect persistent user data or may be difficult to undo. In an agent setting, lack of explicit confirmation requirements increases the risk of accidental resume changes or unintended applications triggered from ambiguous user requests.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This code performs an HTTP POST to an external service and includes both user-supplied parameters and the x-user-token credential in the request headers. Aside from generic usage/error output, there is no explicit disclosure in the script that invoking it transmits provided data and a stored token to a remote server, which is a safety-relevant network operation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script accepts a sensitive Liepin access token as a command-line argument and writes it directly to config.json in plaintext, while only mentioning that environment variables are 'more secure' after storage. Persisting tokens unencrypted on disk increases exposure to local compromise, backup leakage, source-control accidents, and shell history/process-list disclosure when the token is passed on the command line.

Natural-Language Policy Violations

Low
Confidence
71% confidence
Finding
The file is written entirely in Chinese and instructs the user at L016 to send a Chinese command phrase (`设置猎聘token <token值>`). Because no alternative language option or justification for a Chinese-only interface is provided, this may violate the policy against forcing a specific language without user opt-in.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The script's usage examples hard-code Chinese content such as the address value "北京", and inline comments are also exclusively Chinese. For a general-purpose skill, this can imply a language/locale assumption without any user opt-in or indication that the tool is region-specific.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
Several comments and console messages are written only in Chinese, including status, clear, and save messages. This imposes a specific language on users without any apparent opt-in or documented region-specific constraint, which matches the language/locale policy concern.

Static analysis

No suspicious patterns detected.