Back to skill

Security audit

AI-Shifu Course Creator

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent AI-Shifu course-management assistant with sensitive but disclosed platform login, publishing, and analytics capabilities.

Install only if you intend to let the agent manage AI-Shifu courses and analytics for your account. Expect it to store reusable login tokens under your user config directory, create or edit local course files, open authorization/admin pages in the app browser, and perform confirmed platform actions such as import, publish, archive, or analytics queries.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
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
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
Findings (74)

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Storing authentication material in ${XDG_CONFIG_HOME:-~/.config}/ai-shifu/credentials.json creates a concrete credential-access surface, especially if file permissions, encryption, rotation, and revocation are not enforced. Because this skill performs authenticated platform actions and accesses learner/course data, token theft could enable unauthorized account access, content modification, analytics access, or impersonation.

Content

Scanner excerpt · CHANGELOG.md (reported line 34)May include surrounding context.

md
- Print course links with `Admin console`, `Preview URL`, and optional `Published URL` labels, without explanatory text. Open each delivered course or lesson's admin page in the Agent's built-in browser after successful operations and verification, respecting browser opt-outs. Report queued navigation as pending and keep course results intact when the browser is unavailable or opening fails.
- Ask new platform users to choose their current region (China or Other countries or regions), initialize the matching service silently, and remember it outside the Skill package. Preserve explicit service configuration, support custom deployments on request, and block platform calls until configured. Match official contact links to the selected service and preserve resource URLs returned by image uploads without assuming a CN domain.
- Replace SMS login with a browser authorization flow: `login` prints a verification link and pairing code, `login --wait` collects the token once the user approves the request on the AI-Shifu approval page, and no command sends a text message any more. Credentials move from the skill's `.env` to `${XDG_CONFIG_HOME:-~/.config}/ai-shifu/credentials.json` so upgrading or reinstalling the skill no longer signs the user out, and a token left behind by an older version is migrated on first run.
- Use platform-supplied learner context in Course Prompts to personalize open expression while preserving the course author's intended audience, each Teaching Prompt's fixed decisions, and neutral behavior when no relevant learner profile is available.
- Initialize a missing `.env` from `.env.example` before every course CLI command, allow an optional `SHIFU_BASE_URL`, keep `https://app.ai-shifu.cn` as the fallback, and preserve the configured URL when SMS login updates the token.
- Add a low-friction teacher-avatar follow-up after teacher identity intake and a version-aware `set-avatar` CLI path that accepts JPG/PNG, auto-compresses to 2 MB, warns on non-square 
...[truncated 24 chars]

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill reportedly performs self-update checks via outbound HTTP requests and local manifest caching, which is outside the stated course-authoring role. Undisclosed network egress to GitHub or loopback endpoints can leak environment metadata, create supply-chain exposure, and surprise users who did not ask for update behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill reportedly performs self-update checks via outbound HTTP requests and local manifest caching, which is outside the stated course-authoring role. Undisclosed network egress to GitHub or loopback endpoints can leak environment metadata, create supply-chain exposure, and surprise users who did not ask for update behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill reportedly performs self-update checks via outbound HTTP requests and local manifest caching, which is outside the stated course-authoring role. Undisclosed network egress to GitHub or loopback endpoints can leak environment metadata, create supply-chain exposure, and surprise users who did not ask for update behavior.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · references/authentication.md (reported line 22)May include surrounding context.

md
4. Map “中国” / “China” to `site --set cn` and “其他国家或地区” / “Other countries or regions” to `site --set com` internally. If the user explicitly requests a custom deployment, use `site --url <user-supplied-URL>` instead; ask for its service URL only if it is missing. An explicitly requested service or existing configuration takes precedence over regional defaults.
5. Initial `site` setup creates an ordinary profile named `default`; the user need not choose a profile name during first use. Require `status=configured` with the intended address internally, fix the returned profile for the task, then continue verification or the original task immediately. Do not announce the selected address, echo configuration output, or ask for another confirmation. If saving fails, explain the impact in plain language and keep platform operations paused; do not silently use another site. The selection persists across sessions and Skill upgrades and does not select the conversation or course language.

The hidden information is initialization machinery, not links the user needs to act on: browser authorization links, course links, and eligible official contact links still follow their normal display rules. Only show configuration details when the user explicitly requests them for inspection or troubleshooting; do not add them to normal progress, success, or error messages.

An unknown profile, incomplete temporary configuration, or mismatched credential source is a configuration error, not an invitation to try another profile. If changing a profile's URL is blocked by its authorization state, explain that the user must log out of that profile first or create a separate profile; never delete credentials or change the destination to bypass the error. Temporary configuration cannot start or resume browser authorization: select or configure a named profile explicitly for that flow, preserving the user's intended service.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/cli/cli-reference.md (reported line 91)May include surrounding context.

}

text

Profile IDs are generated opaque identifiers used for safe cross-platform directories, independent of user-facing names. Each `profiles/<id>/` contains its own `credentials.json` and optional `pending-device-auth.json`. Both bind authorization to the normalized issuing `base_url`; mismatches fail before sending credentials. Writes are atomic and use owner-only permissions where supported. `profile list` returns `{"profiles": [...]}` with each entry's `name`, `base_url`, `default`, and `credentials_present`, never tokens; presence does not prove that login is valid. `profile default` returns `{"default_profile": "<name>"}`, or null when unconfigured.

On first use of legacy configuration, the CLI migrates a known saved service and matching credentials into an ordinary profile named `default`. Legacy `.env` configuration is considered with its existing precedence; process-exported tokens are never persisted. A pending request migrates only when its issuing URL matches. Credentials whose source cannot be established remain untouched and require a fresh login to the intended profile. The CLI writes and validates new files before committing version-2 settings, then removes only successfully migrated legacy credentials and `.env` fields. Migration can resume after interruption and is not repeated once completed. New `.env` values after migration remain temporary overrides.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/profile_store.py (reported line 122)May include surrounding context.

python
}
```

Profile IDs are generated opaque identifiers used for safe cross-platform directories, independent of user-facing names. Each `profiles/<id>/` contains its own `credentials.json` and optional `pending-device-auth.json`. Both bind authorization to the normalized issuing `base_url`; mismatches fail before sending credentials. Writes are atomic and use owner-only permissions where supported. `profile list` returns `{"profiles": [...]}` with each entry's `name`, `base_url`, `default`, and `credentials_present`, never tokens; presence does not prove that login is valid. `profile default` returns `{"default_profile": "<name>"}`, or null when unconfigured.

On first use of legacy configuration, the CLI migrates a known saved service and matching credentials into an ordinary profile named `default`. Legacy `.env` configuration is considered with its existing precedence; process-exported tokens are never persisted. A pending request migrates only when its issuing URL matches. Credentials whose source cannot be established remain untouched and require a fresh login to the intended profile. The CLI writes and validates new files before committing version-2 settings, then removes only successfully migrated legacy credentials and `.env` fields. Migration can resume after interruption and is not repeated once completed. New `.env` values after migration remain temporary overrides.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/profile_store.py (reported line 365)May include surrounding context.

python
}
```

Profile IDs are generated opaque identifiers used for safe cross-platform directories, independent of user-facing names. Each `profiles/<id>/` contains its own `credentials.json` and optional `pending-device-auth.json`. Both bind authorization to the normalized issuing `base_url`; mismatches fail before sending credentials. Writes are atomic and use owner-only permissions where supported. `profile list` returns `{"profiles": [...]}` with each entry's `name`, `base_url`, `default`, and `credentials_present`, never tokens; presence does not prove that login is valid. `profile default` returns `{"default_profile": "<name>"}`, or null when unconfigured.

On first use of legacy configuration, the CLI migrates a known saved service and matching credentials into an ordinary profile named `default`. Legacy `.env` configuration is considered with its existing precedence; process-exported tokens are never persisted. A pending request migrates only when its issuing URL matches. Credentials whose source cannot be established remain untouched and require a fresh login to the intended profile. The CLI writes and validates new files before committing version-2 settings, then removes only successfully migrated legacy credentials and `.env` fields. Migration can resume after interruption and is not repeated once completed. New `.env` values after migration remain temporary overrides.

Context Leakage

High
Category
Data Exfiltration
Confidence
75% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · references/pedagogy.md (reported line 31)May include surrounding context.

md
| Purpose | Placement | Teaching purpose |
| --- | --- | --- |
| `learner_context` | An early course or module point | Collect context that improves later teaching. |
| `pre_content_thinking` | Before the relevant explanation | Elicit an initial judgment that the explanation can refine. |
| `lesson_end_self_check` | At each lesson end | Let the learner check or consolidate the lesson's core understanding. |

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · references/session-controls.md (reported line 38)May include surrounding context.

md
## Version Check

Run `python3 scripts/shifu-cli.py check-update` only when the user explicitly asks to check or update this skill. Do not check automatically during startup, installation, local writing, or ordinary course operations. An unread remote version state never blocks those tasks.

- Treat the result as internal control data unless the user requests diagnostic details.
- If frontmatter marks `version_management: plugin`, the command skips the release lookup. Standalone uses the skill-level check.

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/teaching-prompt.md (reported line 135)May include surrounding context.

md
Encode the already-resolved author-editable layout without changing teaching content or order:

- Put exactly one standalone `<!-- ... -->` comment immediately before each resolved teaching block; do not reuse a comment across blocks or add another navigation comment to a block.
  - Put the resolved free-form result text inside the wrapper without rewriting it; the wrapper is the only fixed form.
  - Keep the body concise because `markdownflow.md#preprocessing` removes it before runtime.
  - If the body would contain the literal delimiter `<!--` or `-->`, rephrase the outcome.

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/teaching-prompt.md (reported line 184)May include surrounding context.

md
- Explain the selected path.
  - Contrast it with the other path.

<!-- One course-wide goal now guides later examples and emphasis -->

- Create a question-only slide.
  - Make "What course-wide goal should later lessons use?" its complete central question.

Credential Access

High
Category
Privilege Escalation
Confidence
78% confidence
Finding

The code rewrites the '.env' file while handling sensitive fields like 'SHIFU_TOKEN', which means credentials may remain stored in plaintext in a commonly exposed developer artifact. Although the replacement is atomic and uses mode 0600 on the temporary file, plaintext secret persistence in '.env' still increases the risk of accidental disclosure via source control, backups, or local file access.

Content

Scanner excerpt · scripts/profile_store.py (reported line 376)May include surrounding context.

python
and _digest(current.get(key, "")) == expected]
        if clear_keys:
            # Work on a private copy; interruption can leave either the old or new
            # .env but never a half-written file. The journal makes cleanup retryable.
            fd, temp_name = tempfile.mkstemp(dir=str(self.env_file.parent), prefix=".tmp-profile-")
            try:
                with os.fdopen(fd, "w", encoding="utf-8") as handle:

Credential Access

High
Category
Privilege Escalation
Confidence
81% confidence
Finding

This logic explicitly loads saved values from '.env', including potential service URLs and tokens, as part of migration. In the context of a course-creation/analytics skill that may access learner progress, orders, revenue, and other account data, a stolen token could expose sensitive operational and user information from the AI-Shifu platform.

Content

Scanner excerpt · scripts/profile_store.py (reported line 414)May include surrounding context.

python
raise ProfileError("Unsupported profile configuration version.")
        settings = settings or {}
        env = self._env_values()
        # Leave environment-dependent .env configurations as temporary inputs.
        # Their eventual URL/token cannot be proven from saved state alone.
        indirect_env = any("${" in env.get(key, "") for key in ("SHIFU_BASE_URL", "SHIFU_TOKEN"))
        migration_env = {} if indirect_env else env

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

The migration logic reads legacy credentials from plaintext 'credentials.json' and '.env'-derived values, meaning bearer tokens are handled and persisted in local files outside a dedicated secret manager. If the config directory or env file is readable by other local users, an attacker could recover tokens and impersonate the user against the AI-Shifu service.

Content

Scanner excerpt · scripts/profile_store.py (reported line 418)May include surrounding context.

python
# Their eventual URL/token cannot be proven from saved state alone.
        indirect_env = any("${" in env.get(key, "") for key in ("SHIFU_BASE_URL", "SHIFU_TOKEN"))
        migration_env = {} if indirect_env else env
        old_credentials = read_private_json(self.root / "credentials.json") or {}
        old_pending = read_private_json(self.root / "pending-device-auth.json") or {}
        configured_url = migration_env.get("SHIFU_BASE_URL") or settings.get("base_url")
        raw_url = (configured_url

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

This branch migrates an existing token from legacy 'credentials.json' into a new profile credentials file, preserving plaintext token storage at rest. A local compromise, backup leakage, or permissive filesystem ACLs could expose the token and allow account/session misuse on the associated service.

Content

Scanner excerpt · scripts/profile_store.py (reported line 447)May include surrounding context.

python
elif (isinstance(old_token, str) and old_token.strip() and credential_url
              and normalize_base_url(credential_url) == url):
            records.append((credentials_path(context), {"base_url": url, "token": old_token.strip()}))
            legacy_files["credentials.json"] = _digest((self.root / "credentials.json").read_text(encoding="utf-8"))
        if old_pending.get("base_url") and normalize_base_url(old_pending["base_url"]) == url:
            records.append((pending_auth_path(context), {**old_pending, "base_url": url}))
            legacy_files["pending-device-auth.json"] = _digest((self.root / "pending-device-auth.json").read_text(encoding="utf-8"))

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/shifu-cli.py (reported line 29)May include surrounding context.

python
from skill_update import DEV_CACHE_FILE, check_for_update

# ── Constants ──────────────────────────────────────────────────────────────────
ENV_FILE = Path(__file__).resolve().parent.parent / ".env"
ENV_EXAMPLE_FILE = ENV_FILE.with_name(".env.example")

SITE_URLS = profiles.SITE_URLS

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/shifu-cli.py (reported line 66)May include surrounding context.

python
MAX_COURSE_PAGES = 10
# ── Shared Infrastructure ──────────────────────────────────────────────────────
def ensure_env_file():
    """Create the runtime .env from .env.example when it does not exist."""
    if ENV_FILE.exists():
        return
    if not ENV_EXAMPLE_FILE.exists():

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/shifu-cli.py (reported line 78)May include surrounding context.

python
MAX_COURSE_PAGES = 10
# ── Shared Infrastructure ──────────────────────────────────────────────────────
def ensure_env_file():
    """Create the runtime .env from .env.example when it does not exist."""
    if ENV_FILE.exists():
        return
    if not ENV_EXAMPLE_FILE.exists():

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/shifu-cli.py (reported line 3533)May include surrounding context.

python
handler = commands.get(args.command)
    if handler:
        try:
            process_env = dict(os.environ)
            load_env()
            if args.command not in {"check-update", "build"}:
                profile_store().migrate_legacy(process_env)

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · CHANGELOG.md (reported line 3)May include surrounding context.

md
## 1.2.11 - 2026-10-09

- Preserve Course Prompts during reimport and lesson revision baselines during sync; correct lesson history, validate course ordering, and simplify course CLI output. Create a verified GitHub Release containing packages for all four channels. Submit ClawHub and SkillHub automatically; WorkBuddy and Doubao packages require manual download from the Release and upload to their platforms.

## Unreleased

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The changelog explicitly states the skill will automatically submit packages to external platforms and open browser pages after operations, but it also says links are printed "without explanatory text." In an agent skill, undocumented or weakly disclosed outbound actions can cause unintended account-affecting operations, unexpected data sharing, or user confusion about what the agent is doing on their behalf.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The changelog describes browser-based authorization and persistent credential storage in a user config directory, but it provides no indication of consent flow, local protection, or privacy notice. In a skill that manages platform logins and learner/course operations, this increases the risk of users unknowingly leaving reusable tokens on disk or misunderstanding how their credentials and profile data are handled.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill appears to rely on powerful capabilities (environment, filesystem, network, shell) but does not declare any explicit tool scope or permission boundaries. That makes it difficult to constrain what the skill may access at runtime and increases the blast radius if routing, prompt injection, or implementation mistakes cause unintended tool use.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger conditions are extremely broad and cover many ordinary course, analytics, and prompt-related terms, which can cause the skill to activate in contexts the user did not intend. Over-triggering matters more here because the skill routes into authentication, deployment, management, analytics, and other high-impact workflows.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.