T09 · Insecure Skill Coding Practices
- Location
scripts/translate_api.py:29- Finding
Unrestricted API Endpoint Can Disclose Document Content and Bearer Credentials over Plaintext HTTP
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a coherent local document-translation skill, with a privacy caveat if users configure a non-local API endpoint.
Install only if you intend to run a local llama.cpp-compatible translation server. Keep the API URL on localhost for private documents, and do not point it at a remote service unless you trust that service with the full document text and configured bearer key. Use a virtual environment and consider pinning dependency versions.
scripts/translate_api.py:29Unrestricted API Endpoint Can Disclose Document Content and Bearer Credentials over Plaintext HTTP
SKILL.md:69Runtime Dependencies Are Installed without Version or Integrity Pinning
The declared description presents a full PDF translation skill powered by a local llama.cpp model, with multilingual translation, page-by-page translation, and Markdown output. The supplied code chunk does not translate anything at all. It only extracts existing PDF text, retrieves basic metadata, and checks whether the PDF likely contains extractable text. While PDF extraction could be a supporting component of a translation pipeline, this code chunk by itself materially differs from the declared primary purpose and lacks the core advertised capabilities.
The declared description emphasizes a Windows tool for batch PDF translation using a local llama.cpp model, with page-wise extraction and .md output. The supplied code chunk only provides a generic translation API wrapper and CLI for translating raw text from stdin, a text argument, or a text file. It constructs prompts reflecting the three-step translation style and supports arbitrary language directions, which partially aligns with the translation aspect. However, the core advertised capabilities—PDF handling, page extraction, batch document processing, markdown output, and direct local llama.cpp model usage—are absent from this code. Therefore the description materially overstates and misrepresents what this code chunk actually does.
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
if context:
prompt += f"Context:\n{context[:500]}\n\n---\n\n"
prompt += f"Translate the following into {tgt_name}:\n\n{text}"
return prompt
def translate_segment(self, text: str, direction: str = "en2zh",
depth: str = "standard", context: str = "") -> Dict:
The skill documentation advertises capabilities that imply file access, environment-variable use, and HTTP communication, but it does not declare any explicit tool scope such as permissions or allowed-tools. In an agent ecosystem, that omission weakens least-privilege enforcement and can let an agent operate with broader-than-expected access when handling untrusted PDFs, local files, and API settings.
The direction field is fixed to en2zh, which imposes a specific language conversion policy. Under the stated rule, forcing a language or locale without offering user choice or documenting a justified regional constraint is a natural-language policy violation.
The code hard-codes English for language-name display via get_language_name(..., "en"), and the CLI/user-facing output strings are also fixed in English. This imposes a specific language/locale on users without offering a choice, which matches the policy category for language or locale violations.
The generated markdown for translated text uses fixed English headings such as "Translation", "Source", "Direction", and "Generated". Because no locale choice is provided, the skill enforces English in produced artifacts, which is a natural-language locale policy issue.
The PDF output writer again forces English language names and English metadata labels in generated files. This repeated English-only behavior affects all output artifacts and is not presented as an opt-in or region-specific requirement.
This code sends extracted PDF text chunks to translator.translate_segment(...), which implies transmitting document contents to a translation service. Although the script prints progress and its purpose is translation, there is no clear user-facing warning in this file that document data may leave the local system or be processed by an API.
The file contains user/developer-facing natural-language text in Chinese only, beginning with the module description. Under the policy, forcing a specific language without opt-in can be a locale/language policy violation when no alternative or user choice is provided.
The program sends extracted document text to a translation API through LocalTranslator without any explicit privacy notice, consent flow, or sensitivity check. Even if the configured endpoint is local by default, the code accepts arbitrary api_url configuration, so users may unknowingly transmit sensitive document contents to a remote service.
Markdown and text files are read in full and sent to the translation API with no user-facing warning that file contents leave the process boundary. In this skill context, users may translate notes, drafts, or confidential text, so silent transmission increases the risk of accidental data exposure.
The file advertises a local llama.cpp-based translator, but the implementation sends document text to a configurable HTTP API endpoint. This mismatch can cause users to expose sensitive PDF contents under the false assumption that processing stays entirely local, creating a privacy and trust-boundary violation.
The connection check performs network communication despite the skill being described as local PDF translation with a local model. In this context, undocumented network use weakens user expectations about isolation and may lead to sensitive academic or proprietary material being sent to a service outside the user's intended trust boundary.
The requests.post call transmits the full prompt payload, including source text and optional context, to the configured API endpoint. External transmission is security-relevant here because the skill's purpose is document translation, so the payload may include entire pages of sensitive PDF contents and prompt metadata.
payload["model"] = self.model
try:
resp = requests.post(
self.api_url,
headers=self.headers,
json=payload,
The code sends user-supplied text and context to an API without any explicit warning, consent prompt, or redaction step. Because this skill processes PDFs that may contain confidential research, personal data, or unpublished manuscripts, silent transmission materially increases the risk of unintended data disclosure.
The skill documentation begins entirely in Chinese and presents the skill description in that language without indicating that users can choose another language for instructions. Under the stated policy, forcing a specific language without user opt-in is a natural-language locale violation.
The manifest description is specifically scoped to PDF translation with per-page extraction, yet the file discovery logic includes Markdown and plain text files, and later translates them directly. This expands behavior beyond the stated document type in a way not described by the manifest.
The calls get_language_name(src, "en") and get_language_name(tgt, "en") force English for user-visible language labels. This imposes a specific locale choice without offering the user a language preference or documenting a justified locale constraint.
This Python file contains its module description, comments, and several user-facing help/output strings primarily in Chinese, and get_language_name defaults its display language to zh. Under the policy rule, forcing a specific language without user opt-in can be a natural-language locale violation when no alternative or choice is offered.
The code calls get_language_name(..., "en"), hard-coding English for displayed language names. This is a natural-language policy concern because the script imposes a specific locale in user-facing output without any opt-in or configuration option.
The manifest scopes the skill as a PDF translation tool with page-by-page extraction and translation, but file discovery explicitly includes .md and .txt inputs in addition to PDFs. This broadens the actual behavior beyond the stated document type, even though it is related to translation.
For generated translation files, the script uses get_language_name(tgt, "en") and writes English-language headings regardless of user preference. This forces a specific language/locale in user-visible output without offering a choice.
The _write_output method hard-codes "en" when rendering source and target language names, producing English-only metadata in output files. This is a locale policy issue because users are not given a way to select or opt into the display language.
No suspicious patterns detected.