Back to skill

Security audit

Chinese Talent Scout

Security checks for vulnerabilities and agentic risk

Overview

This skill is disclosed as a talent-scouting tool, but it profiles and scores Chinese GitHub users at scale and shares candidate data with external OpenClaw agents, so it needs careful review before use.

Install only if you have a legitimate, reviewed reason to collect and rank people by Chinese identity or location signals. Use a test workspace first, keep provider and channel credentials outside the skill, review workspace exports before sharing them, prefer --skip-ai when external AI processing is not needed, and do not enable cron until you are comfortable with recurring collection and evaluation.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/talent-scout.mjs:21506
Finding
Untrusted GitHub Content Is Forwarded to AI Agents Without Prompt-Injection Controls<![CDATA[ ## Vulnerability Details **File Location**: `scripts/talent-scout.mjs:21506-21513`, `scripts/talent-scout.mjs:21552-21558`, and `scripts/talent-scout.mjs:25081-25110` **Vulnerability Type**: Indirect prompt injection through untrusted GitHub metadata **Risk Level**: Medium ### Vulnerable Code The evaluator receives candidate profiles and signals containing externally controlled GitHub content: ```js const result = await callAgent("evaluator", { task: "batch_deep_evaluation", candidates: batch.map((c3) => ({ username: c3.username, profile: c3.profile, signals: c3.signals, evaluation: c3.evaluation, features: c3.features })) }); ``` The identity agent receives the same type of untrusted profile data: ```js const result = await callAgent("identity", { task: "batch_identity_inference", candidates: batch.map((c3) => ({ username: c3.username, profile: c3.profile, signals: c3.identity?.signals ?? [] })) }); ``` Commit messages are one example of attacker-controlled content incorporated into candidate signals: ```js async function collectCommitSignals(config, cache) { const candidates = /* @__PURE__ */ new Map(); for (const qcfg of config.commit_queries) { const q = qcfg.query; const items = await ghApi( `/search/commits?q=${encodeSearchQuery(q)}&sort=committer-date`, { maxPages: config.api_budget.search_pages_per_query, sleepMs: config.api_budget.search_sleep_ms, accept: "application/vnd.github.cloak-preview+json", cache, cacheTtl: config.cache.ttl.search_results } ); for (const item of items) { const login = item.author?.login.toLowerCase(); if (!login) continue; const signals2 = candidates.get(login) ?? []; signals2.push({ type: labelToSignalType(qcfg.label), detail: `${item.repository.full_name}: ${item.commit.message.slice(0, 60)}`, weight: qcfg.weight, source: "commit-sea ...[truncated 2790 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Establish an explicit trust boundary in every agent request** - State that all candidate fields originate from untrusted public sources. - Instruct the agent never to follow commands, policies, role changes, or tool requests found inside candidate data. - Require the agent to analyze those fields only as quoted evidence. 2. **Separate instructions from data** - Place trusted task instructions in the agent's system or policy layer. - Serialize candidate content inside a clearly delimited data structure. - Avoid concatenating external text into instruction-bearing strings. 3. **Minimize forwarded data** - Send only fields necessary for the specific inference. - Prefer normalized booleans, counts, and allowlisted attributes over complete profile and signal objects. - Truncate and sanitize free-form biographies, repository descriptions, and commit messages. 4. **Validate agent responses** - Enforce a strict response schema. - Constrain confidence values to an expected numeric range. - Validate usernames against the submitted batch. - Reject unknown fields, malformed actions, and unsupported city values. - Do not permit model output to select tools, commands, files, or destinations. 5. **Add defensive evaluation** - Detect common prompt-injection phrases in external text and flag affected candidates for manual review. - Record which source fields contributed to each AI conclusion. - Require human confirmation before high-impact shortlist or outreach decisions. 6. **Add adversarial tests** - Test biographies, repository descriptions, and commit messages containing role-change requests, instruction overrides, fake system messages, and requests to alter scores. - Verify that such content is quoted as evidence and never followed as an instruction. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (10)

Credential Access

High
Category
Privilege Escalation
Content
}
    };
    npmRunPathEnv = ({ env = process4.env, ...options } = {}) => {
      env = { ...env };
      const pathName = pathKey({ env });
      options.path = env[pathName];
      env[pathName] = npmRunPath(options);
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

High
Confidence
97% confidence
Finding
`deepEvaluateBatch()` sends candidate usernames, profiles, signals, evaluations, and features to an external `openclaw` agent. This is a real data-sharing risk because the transfer is off-process/off-tooling boundary, and the code does not show consent, minimization, or clear disclosure controls for the candidate data being transmitted.

Missing User Warnings

High
Confidence
96% confidence
Finding
`inferIdentityBatch()` sends candidate identity-related data to an external agent for nationality/location inference. Because the payload supports sensitive demographic inference and is transmitted externally without an evident approval gate, the privacy and compliance risk is heightened in this skill context.

Natural-Language Policy Violations

High
Confidence
93% confidence
Finding
The skill hard-codes Chinese nationality/location targeting and performs confidence scoring around whether developers are Chinese. In this context, that is more dangerous than generic geo-filtering because it operationalizes sensitive demographic profiling and downstream outreach based on inferred nationality/ethnicity-linked signals.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill exposes broad capabilities through its documented entrypoint and features, including shell execution, network access, file read/write, environment use, cron management, and workspace export, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization gap where an agent runtime may grant more access than is necessary, increasing the blast radius of misuse, prompt injection, or implementation flaws in the underlying scripts.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The skill includes a generic outbound messaging capability across many chat platforms via `sendMessage3()`. In a scouting workflow, this materially expands the trust boundary from local analysis into external communications, enabling candidate data, requests, or other workspace-derived content to be transmitted off-system if invoked or misused.

Context-Inappropriate Capability

Medium
Confidence
99% confidence
Finding
The export command zips the entire `workspace-data` directory, which by design includes `user-data`, `cache`, `output`, and `talents.yaml`, not just a narrowly scoped export artifact. That can unintentionally package candidate data, cached API responses, run outputs, and local operational metadata into a portable file that is easy to share or exfiltrate.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The workspace export creates a shareable ZIP of local data without a clear user-facing warning about the breadth of copied contents. In this skill context, the workspace likely contains sourced candidate profiles, scoring outputs, ignore lists, and caches, so silent archiving increases the chance of privacy-impacting disclosure.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The configuration is explicitly designed to discover and score a specific national group ('Chinese GitHub developers') using nationality/linguistic community signals and ranking sources, but it does not show user consent, lawful basis, or a narrowly documented justification. This creates a profiling and targeting risk because the skill operationalizes collection, scoring, monitoring, and shortlist generation for a protected or sensitive demographic segment at scale.

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
The generated message instructs a recipient to "Apply the update directly to that YAML file," implying the command performs or guarantees the config modification. In reality, runConfigRequestCommand only resolves delivery settings and sends a message through OpenClaw; it does not modify talents.yaml itself.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/talent-scout.mjs:4715