Back to skill

Security audit

Ctx-Lockstep

Security checks for vulnerabilities and agentic risk

Overview

This context-management skill has a coherent purpose, but it needs review because it can persistently modify repositories and workspace files with weak path and hook-safety controls.

Review before installing. Use it only on projects where you are comfortable with .ctx-lockstep files, a workspace-level PROJECT_SYSTEM.md, and a persistent post-commit hook. Confirm exact paths, avoid overwrite mode unless needed, inspect any existing .git/hooks/post-commit before initialization, and remember that commit subjects may be saved in commits.log.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/init_project.py:117
Finding

Unvalidated Path Components Allow Writes Outside Intended Project and Workspace Roots

Content
View full analysis
`', f'`{project_dir.parent}`') if write_text(system_path, content, overwrite=overwrite): created.append(str(system_path)) else: skipped.append(str(system_path)) ``` ### Technical Analysis The values of `project_name` and `project_rule_filename` are used as path components without validation. The implementation does not reject: - Absolute paths - Parent-directory components such as `..` - Embedded path separators - Symlink-based path redirection With `pathlib`, joining a root with an absolute path discards the original root. For example: ```python Path('/approved/workspace') / '/tmp/target' ``` evaluates to `/tmp/target`. Similarly, a value such as `../../outside` can escape the intended root. The resulting paths are subsequen ...[truncated 2112 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/init_project.py:67
Finding

Initialization Can Reactivate Untrusted Existing Git Hook Code

Content
View full analysis
str: """Idempotently install post-commit hook and return action description.""" git_dir = project_dir / '.git' if not git_dir.exists(): return 'skipped: non-git project' hooks = git_dir / 'hooks' hooks.mkdir(exist_ok=True) hook_path = hooks / 'post-commit' block = HOOK_BODY if hook_path.exists(): content = hook_path.read_text(encoding='utf-8', errors='replace') if HOOK_MARK_BEGIN in content: return 'skipped: hook already installed' # Append to an existing hook without replacing user logic hook_path.write_text(content.rstrip() + '\n\n' + block + '\n', encoding='utf-8') action = 'appended to existing post-commit hook' else: hook_path.write_text('#!/bin/sh\n\n' + block + '\n', encoding='utf-8') action = 'created post-commit hook' try: hook_path.chmod(hook_path.stat().st_mode | 0o111) except OSError: pass return action ``` ### Technical Analysis When an existing `.git/hooks/post-commit` file is found, the script preserves all existing contents, appends the ctx-lockstep block, and then adds executable permission to the entire file. This creates a dangerous transition when the existing hook is intentionally or incidentally non-executable. A non-executable hook may contain: - Disabled legacy commands - Unreviewed code from an untrusted repository archive - Attacker-planted shell commands - Content not intended to be interpreted as a program The unconditional `chmod(... | 0o111)` activates both the new ctx-lockstep block and all pre-existing contents. Git will then execute the complete hook after a later commit. The script neither displays the existing hook f ...[truncated 1500 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
scripts/init_project.py:35
Finding

Unescaped Commit Subjects Create a Persistent Prompt-Injection and Log-Integrity Channel

Content
View full analysis
/dev/null)" && printf '{{"commit":"%s","date":"%s","subject":"%s"}}\\n' \\ "$(git rev-parse --short HEAD)" \\ "$(date '+%Y-%m-%d %H:%M')" \\ "$(git log -1 --pretty=%s)" \\ >> "$_cl_root/.ctx-lockstep/commits.log" }} 2>/dev/null {1}'''.format(HOOK_MARK_BEGIN, HOOK_MARK_END) ``` Drift-log processing and output: ```python def git_drift(project: Path) -> dict: log = project / '.ctx-lockstep' / 'commits.log' pending, items = 0, [] if log.exists(): lines = [l.strip() for l in log.read_text(encoding='utf-8').splitlines() if l.strip()] pending = len(lines) items = lines[-10:] # Show at most the latest 10 entries return {'git': True, 'pending': pending, 'items': items, 'hint': 'commits.log has pending entries; checkpointing is recommended'} ``` ```python if result['pending'] > 0: unit = 'pending commits' if is_git else 'changed files since checkpoint' print(f"DRIFT: {result['pending']} {unit} (last_checkpoint: {lc})") for it in result['items']: print(f" - {it}") print(f" → {result['hint']}") ``` ### Technical Analysis The hook constructs JSON using shell `printf` and inserts the commit subject directly into a quoted JSON field. The subject is not encoded with a JSON-aware serializer. A crafted subject containing quotation marks, backslashes, control characters, terminal escape sequences, or unexpected line content can therefore: - Produce malformed JSON - Alter the apparent structure of a record - Manipulate terminal output - Mislead the pending-item display - Embed natural-lang ...[truncated 2243 chars]
Remediation
View remediation
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 (14)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README advertises automatic git hook installation as part of initialization but does not prominently warn that the skill will modify the target repository. Repository-modifying behavior without clear advance notice can violate user expectations, introduce persistent local execution paths, and make accidental activation more harmful.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The invocation phrases are broad enough to overlap with ordinary project-management requests like '恢复项目' or '帮我接管这个项目目录', which can cause the skill to activate in situations where the user did not specifically intend long-term state management. In this skill, unintended activation matters because the documented behavior includes scanning project state and potentially modifying repository configuration, so ambiguous triggers increase the chance of surprise side effects.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill instructs the agent to read and write project files and execute Python and shell commands, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates an avoidable trust gap: a caller cannot easily tell from the manifest that the skill may modify repository contents, install hooks, or inspect filesystem state, increasing the chance of overbroad execution in sensitive workspaces.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The heading and surrounding instructional content present the skill in Chinese as the default operating language, while the policy requires avoiding forced language or locale constraints unless the user is given a choice or the limitation is justified. Although line L003 includes an English summary, the rest of the operational guidance does not offer an opt-in language choice.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The recovery trigger phrases are broad conversational terms such as '恢复项目', '进入项目', and '回到项目', which can overlap with normal discussion and cause the skill to activate or switch context unintentionally. In a context-management skill, accidental activation can expose prior project state, read the wrong project metadata, or steer the assistant into an unintended workspace, making the issue more dangerous than in a non-stateful skill.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documented trigger phrases for resuming or entering a project are very broad and overlap with ordinary conversational language such as '恢复项目' or '回到项目'. In an agent skill, ambiguous activation criteria can cause the skill to engage unexpectedly, leading to unintended reads, writes, registry scans, or state changes in the user's workspace without sufficiently explicit intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The example command list includes generic phrases like '恢复项目', '回到项目', and '退出项目' but does not specify exact matching rules, disambiguation behavior, or when the assistant should ignore them in ordinary dialogue. This increases the risk of accidental skill triggering and unintended context switching or persistence operations, especially in shared or long-running sessions where such phrases may appear naturally.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The restore trigger phrases are broad and conversational (e.g., '恢复项目', '进入项目', '回到项目'), which can overlap with normal dialogue and cause the skill to activate or alter project-state handling when the user did not intend a registry-driven recovery flow. In a context-management skill, this can lead to unintended reads/writes of project metadata, confusion about the active project, or accidental disclosure of available project names and paths during candidate listing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script automatically installs or appends to .git/hooks/post-commit for any detected Git repository, which changes repository behavior without an explicit confirmation step at the moment of action. In this skill’s context, that hook records commit metadata into a project-local log, so the risk is not arbitrary code execution by itself, but it can surprise users, affect developer workflows, and normalize silent persistence inside repositories.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The template’s headings and instructional text are entirely in Chinese, which effectively forces a specific language for use of the recovery document. Under the policy, locale or language constraints should either be optional for the user or clearly justified as region-specific; neither is present here.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The documented hook automatically records commit subjects into a plaintext project-local log file, and the documentation does not clearly warn users that commit messages may contain sensitive information such as ticket references, incident details, internal hostnames, or secrets pasted into subjects. In a long-lived context-management skill, silent persistence of this metadata increases the chance of unintended retention, disclosure, or later exfiltration through backups, repo packaging, or sharing the project directory.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README is entirely written in Chinese and presents the invocation phrases and operating instructions only in that language. There is no indication that the skill offers multilingual use or that the Chinese-only presentation is a documented, justified locale constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file presents all instructions and release requirements only in Chinese, while also referencing external/community distribution. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale restriction is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file’s docstring and several user-facing messages are written in Chinese, including usage context and status strings, but there is no indication that the skill is intentionally region-specific or that users can opt into another language. This creates a locale policy concern because the skill appears to impose a specific language by default.

Content

No source excerpt is available for this finding.