Back to skill

Security audit

Trace Debuger

Security checks for vulnerabilities and agentic risk

Overview

The skill appears intended for trace debugging, but it can send raw operational logs and repository context into Codex without enough scoping, redaction, or user control.

Install only if you are comfortable with trace logs and selected repository context being processed by Codex and written into a local Markdown report. Use sanitized logs, avoid production secrets or customer data, restrict Jaeger and Elasticsearch URLs to trusted endpoints, and delete generated reports yourself if they should not persist.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/trace_debuger.py:149
Finding
Unredacted Elasticsearch Logs Are Forwarded to an External-Capable Analysis Process<![CDATA[ ## Vulnerability Details **File Location**: `scripts/trace_debuger.py:149-164` and `scripts/trace_debuger.py:281-302` **Vulnerability Type**: Sensitive data exposure through external analysis **Risk Level**: High ### Vulnerable Code ```python logs.append({ "ts": str(ts) if ts is not None else "", "service": src.get("fields.service") or fields.get("service") or src.get("service") or "unknown", "span_id": src.get("span_id") or "", "level": src.get("level") or "", "msg": str(msg), "error": src.get("error") or "", "caller": src.get("caller") or "", "raw": src, }) ``` ```python def run_codex_analysis(repo_path: str, logs: List[Dict[str, Any]]) -> Tuple[Optional[str], Optional[str]]: if not repo_path or not os.path.isdir(repo_path): return None, "repo_path 不存在,跳过 codex 分析" # 控制上下文长度,避免提示词过大 picked = logs[:200] payload = "\n".join([json.dumps(l, ensure_ascii=False) for l in picked]) prompt = ( "这是我的日志,请根据日志结合代码帮我排查分析bug,输出bug原因及解决方案,必须保持固定的格式。\n" "固定格式如下:\n" "1) Bug原因:<...>\n" "2) 证据:<...>\n" "3) 解决方案:<...>\n\n" "日志如下(JSON Lines):\n" + payload ) try: p = subprocess.run( ["codex", "exec", prompt], cwd=repo_path, capture_output=True, text=True, timeout=240, ) ``` ### Technical Analysis Every normalized Elasticsearch record retains the complete `_source` document in the `raw` field. The script then serializes as many as 200 complete records and supplies the resulting text to `codex exec`. Elasticsearch logs may contain authorization headers, session cookies, access tokens, personal information, request and response bodies, internal hostnames, database identifiers, or proprietary application data. The implementation applies no field allowlist, secret masking, data classification, destination verification, or explicit user confirmation before invoking Codex. Althoug ...[truncated 1150 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `raw` field from normalized records supplied to Codex. 2. Use an explicit allowlist containing only fields required for diagnosis. 3. Redact authorization headers, cookies, tokens, passwords, API keys, email addresses, and other regulated data before serialization. 4. Require explicit user approval before sending logs to an externally backed analyzer. 5. Clearly document the analysis destination, retention behavior, and data-handling policy. 6. Add a local-only mode that never invokes a network-backed model. 7. Limit both the number and maximum serialized size of records. 8. Add automated tests using representative secrets to verify that sensitive values cannot reach the Codex prompt. ]]>

T01 · Skill Instruction Hijacking

Error
Location
scripts/trace_debuger.py:281
Finding
Untrusted Log Content Can Inject Instructions into the Codex Analysis Prompt<![CDATA[ ## Vulnerability Details **File Location**: `scripts/trace_debuger.py:281-302` **Vulnerability Type**: Indirect prompt injection through attacker-controlled logs **Risk Level**: High ### Vulnerable Code ```python def run_codex_analysis(repo_path: str, logs: List[Dict[str, Any]]) -> Tuple[Optional[str], Optional[str]]: if not repo_path or not os.path.isdir(repo_path): return None, "repo_path 不存在,跳过 codex 分析" # 控制上下文长度,避免提示词过大 picked = logs[:200] payload = "\n".join([json.dumps(l, ensure_ascii=False) for l in picked]) prompt = ( "这是我的日志,请根据日志结合代码帮我排查分析bug,输出bug原因及解决方案,必须保持固定的格式。\n" "固定格式如下:\n" "1) Bug原因:<...>\n" "2) 证据:<...>\n" "3) 解决方案:<...>\n\n" "日志如下(JSON Lines):\n" + payload ) try: p = subprocess.run( ["codex", "exec", prompt], cwd=repo_path, capture_output=True, text=True, timeout=240, ) ``` ### Technical Analysis Log messages and error values are potentially attacker-controlled. They are concatenated directly into the same prompt that contains the analysis instructions. The prompt does not establish that log contents are untrusted data and must never be interpreted as instructions. The Codex process is launched with the selected repository as its working directory. A malicious log entry could attempt to override the requested task, direct the analyzer to inspect unrelated repository files, disclose source code, manipulate its conclusions, or request additional actions. The ultimate severity depends on the tools, network access, approval policy, and filesystem permissions available to the installed Codex CLI. Simply encoding records as JSON Lines does not create a security boundary: natural-language instructions embedded inside string values remain visible to the model. ### Attack Path 1. An attacker causes an application to log a crafted message, such as instructions to ignore the ...[truncated 861 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Explicitly state in the highest-priority analysis instructions that all log content is untrusted data and that instructions found in logs must never be followed. 2. Place logs in a strongly delimited data section and identify each field as quoted evidence rather than executable instructions. 3. Run Codex in a read-only, sandboxed environment with no unnecessary network, shell, write, or credential access. 4. Restrict repository access to the minimum files needed for diagnosis. 5. Prefer a structured API and schema-constrained response instead of unrestricted agent execution. 6. Validate the generated output against the expected report schema before including it in the report. 7. Detect and flag instruction-like log content for manual review. 8. Require approval for any tool call or access beyond reading explicitly selected source files. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/trace_debuger.py:316
Finding
User-Controlled Jaeger and Elasticsearch URLs Permit Unrestricted HTTP Requests<![CDATA[ ## Vulnerability Details **File Location**: `scripts/trace_debuger.py:316-318`, `scripts/trace_debuger.py:326-327`, and `scripts/trace_debuger.py:367-368` **Vulnerability Type**: Server-side request forgery and internal service access **Risk Level**: Medium ### Vulnerable Code ```python ap.add_argument("--trace-id", required=True) ap.add_argument("--jaeger-url", default="http://127.0.0.1:16686") ap.add_argument("--es-url", default="http://127.0.0.1:9200") ``` ```python jaeger_url = args.jaeger_url.rstrip("/") + f"/api/traces/{trace_id}" j_raw, j_err = http_get_json(jaeger_url) ``` ```python es_search_url = args.es_url.rstrip("/") + f"/{args.es_index}/_search" es_raw, es_err = http_search_json(es_search_url, es_query) ``` The request functions perform the supplied requests without destination validation: ```python req = urllib.request.Request(url, method="GET") with urllib.request.urlopen(req, timeout=timeout) as resp: ``` ```python req = urllib.request.Request(url, data=data, method="GET", headers={"Content-Type": "application/json"}) with urllib.request.urlopen(req, timeout=timeout) as resp: ``` ### Technical Analysis The Jaeger and Elasticsearch base URLs are accepted directly from command-line inputs. The implementation does not validate the scheme, hostname, resolved IP address, port, redirect target, or whether the destination is an approved tracing service. If an untrusted caller can influence these inputs, the Skill becomes an HTTP request primitive operating with the network privileges of the host. It may reach loopback services, private network services, link-local endpoints, or cloud metadata services. Python's standard URL opener also follows redirects under normal configurations, so an initially acceptable host may redirect to a prohibited destination unless every redirect is revalidated. The appended fixed paths reduce but do not eliminate the issue because internal services may respond on those paths, redirect requests, or exp ...[truncated 852 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict requests to an administrator-configured allowlist of Jaeger and Elasticsearch origins. 2. Accept only `http` and `https` schemes. 3. Resolve hostnames before connection and reject loopback, link-local, multicast, unspecified, metadata, and private addresses unless explicitly authorized. 4. Disable redirects or validate the scheme, hostname, resolved address, and port after every redirect. 5. Reject URLs containing embedded credentials or unexpected user-info components. 6. Permit only expected ports and path structures. 7. Separate trusted configuration from untrusted task input. 8. Apply network-level egress controls so the process can reach only approved observability services. 9. Add authenticated TLS for non-local observability endpoints. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/trace_debuger.py:495
Finding
Sensitive Markdown Report Persists Despite Documented Cleanup Requirement<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:67-69` and `scripts/trace_debuger.py:495-497` **Vulnerability Type**: Insecure sensitive-file retention **Risk Level**: Medium ### Vulnerable Documentation and Code The Skill documentation promises local cleanup: ```markdown - After analysis in chat workflow: send the generated Markdown report **as a file attachment** to the user through the chat window, with the strict summary block in the **same message** caption/body (single message only). - The first line must be the real Markdown filename (not placeholder text). - Finally, delete the local Markdown file. ``` The implementation only creates and writes the report: ```python p = Path(output_path) p.parent.mkdir(parents=True, exist_ok=True) p.write_text("\n".join(lines) + "\n", encoding="utf-8") ``` No deletion operation is present after the write. ### Technical Analysis The generated report can contain trace topology, service names, application errors, log messages, repository paths, source-line context, and Codex analysis. The script writes this information to a caller-selected or default path but does not implement the cleanup required by `SKILL.md`. Cleanup is therefore delegated to a later chat-agent action that may never occur when the script is invoked directly, the workflow fails, attachment delivery is interrupted, or the agent omits the cleanup step. The file is also created according to the process umask rather than with an explicitly restrictive mode. ### Attack Path 1. A user executes the Skill for a trace containing sensitive diagnostic data. 2. The script generates the Markdown report at `output_path`. 3. The process exits normally or the subsequent attachment workflow fails. 4. Because the script performs no deletion, the report remains on disk. 5. Another local user, process, backup system, indexing service, or later task reads the retained report. ### Impact Assessment Sensitive operational and source-context data ma ...[truncated 294 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Implement cleanup in a `finally` block after confirmed report delivery. 2. Ensure failure paths also remove temporary reports when retention is not requested. 3. Create the report with restrictive permissions, such as mode `0600`. 4. Prefer a secure temporary directory rather than the current working directory. 5. Provide an explicit `--retain-report` option if persistent output is required. 6. If automatic deletion cannot be guaranteed, remove the cleanup promise from the documentation and clearly disclose retention behavior. 7. Avoid placing unnecessary raw logs, local absolute paths, or source content in the report. 8. Record cleanup failures without printing sensitive report contents. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared purpose suggests local trace/log analysis, but the skill additionally instructs invoking an external analysis tool (`codex exec`) and sending collected logs and possibly repository context to it. This expands the trust boundary and can exfiltrate sensitive operational data or source code to another system without clear disclosure or user consent.

Ssd 3

High
Confidence
99% confidence
Finding
The script forwards raw log content to an external AI tool and then reproduces analysis and related evidence in a Markdown report, establishing two leakage channels: outbound transmission and local persistence. In a trace-debugging workflow, this is particularly dangerous because traces/logs often include high-value operational and customer data, and the report can further spread that data through CI artifacts or tickets.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill declares no explicit tool scope even though it instructs operations that require network access, shell execution, and file read/write. In a skill framework, missing permission boundaries increases the chance of overbroad execution and makes it harder for reviewers or policy engines to constrain sensitive capabilities before the skill runs.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The required output block uses Chinese field labels, and the analysis prompt is also hard-coded in Chinese. This forces a specific language/locale without opt-in or explanation, which violates the language-choice policy for natural-language behavior.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill instructs creation and later deletion of a local Markdown report without clearly warning about the destructive cleanup step. While limited in scope, undeclared deletion can surprise users, interfere with auditing or forensics, and remove artifacts they expected to keep.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
Logs are packaged into a prompt and sent to an external analysis tool without any explicit user-facing warning, consent, or redaction step. Because operational logs frequently contain credentials, tokens, customer data, stack traces, and internal endpoints, this creates a significant confidentiality risk.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
Natural-language strings for the Codex prompt and generated report/output are written in Chinese only, which imposes a specific language on users without opt-in. The file does not indicate that this is a region-specific tool or provide any mechanism to select another language.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
This skill explicitly sends repository-context analysis to an external Codex CLI, combining local code access with production trace/log data. In a debugging skill, that is especially sensitive because traces and logs often contain secrets, identifiers, internal topology, and source details that should not be disclosed to third-party services without strong controls.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
)

    try:
        p = subprocess.run(
            ["codex", "exec", prompt],
            cwd=repo_path,
            capture_output=True,
Confidence
95% confidence
Finding
The script invokes an external `codex` CLI and passes it a prompt built from collected logs while setting `cwd` to the local repository. This creates a code-and-data exfiltration boundary: sensitive logs and repository context can be exposed to an external tool or model, and the trustworthiness of that downstream tool is not verified or constrained here.

Description-Behavior Mismatch

Low
Confidence
86% confidence
Finding
The script performs broad repository walking and extracts code lines based on log-derived caller paths, which goes beyond a narrow 'optional local repository context' expectation. That increases exposure of unrelated source files and can unintentionally include sensitive code fragments in the final report or in downstream AI analysis.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The code creates parent directories and writes a report file containing trace, log, and analysis data, which could include sensitive operational details. Although the output path is configurable, there is no visible prompt, warning comment, or user-facing notice that the script persists this data to disk.

Static analysis

No suspicious patterns detected.