T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:76- Finding
Unrestricted API endpoint can disclose the bearer token and uploaded document
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly coherent for business-license OCR, but it can upload any readable local file and send the API key plus document to a configurable remote endpoint.
Install only if you are comfortable sending business-license documents to the Scnet OCR service. Before use, keep SCNET_API_BASE at the documented api.scnet.cn HTTPS endpoint, do not process files you are not authorized to upload, and prefer running it only after confirming the exact file path and destination.
scripts/main.py:76Unrestricted API endpoint can disclose the bearer token and uploaded document
scripts/main.py:89Insufficient input restrictions allow arbitrary readable local files to be uploaded
SKILL.md:87Dependency installation is unpinned and lacks integrity verification
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# 获取技能根目录(脚本所在目录的上一级)
SKILL_ROOT = Path(__file__).parent.parent.absolute()
ENV_FILE = SKILL_ROOT / "config" / ".env"
# --- 新增:重试配置 ---
MAX_RETRIES = 3 # 最大重试次数
RETRY_BACKOFF_FACTOR = 2 # 退避因子,每次重试等待时间翻倍
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
INITIAL_RETRY_DELAY = 1 # 初始等待时间(秒)
# --------------------
def load_config():
"""从 .env 文件加载配置,若文件不存在则抛出友好错误"""
if not ENV_FILE.exists():
error_msg = (
"\n===============================================\n"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
INITIAL_RETRY_DELAY = 1 # 初始等待时间(秒)
# --------------------
def load_config():
"""从 .env 文件加载配置,若文件不存在则抛出友好错误"""
if not ENV_FILE.exists():
error_msg = (
"\n===============================================\n"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
INITIAL_RETRY_DELAY = 1 # 初始等待时间(秒)
# --------------------
def load_config():
"""从 .env 文件加载配置,若文件不存在则抛出友好错误"""
if not ENV_FILE.exists():
error_msg = (
"\n===============================================\n"
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
* [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)
* [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
* [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
* [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
* [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
The skill documentation indicates capabilities that can read local files, invoke shell commands, and send data over the network, but it does not declare any explicit tool scope such as allowed-tools or permissions. In an agent environment, this weakens least-privilege controls and can let the skill be auto-invoked with broader access than users may expect, especially since it handles sensitive document images.
The description explicitly limits the skill to recognizing '中国大陆' business licenses, which imposes a locale-specific scope. In the provided text, this locale restriction is not presented as a user choice or clearly justified as a region-specific compliance or product constraint.
The skill is designed to send local business-license images to api.scnet.cn for OCR processing, which is an external transmission of sensitive corporate identity and registration data. Although the README warns about this behavior, the combination of local file access plus third-party upload creates real confidentiality and compliance risk if users do not explicitly consent at invocation time.
SCNET_API_KEY=your_scnet_api_key_here
SCNET_API_BASE=https://api.scnet.cn/api/llm/v1
2. 添加:`SCNET_API_KEY=你的密钥`
3. 设置文件权限为 600(仅所有者可读写)
The trigger guidance says the AI may automatically invoke the skill based on broad OCR-related requests, but it does not clearly limit when invocation is appropriate or require confirmation before uploading sensitive business-license images. Because the skill transmits regulated business information to a third party, ambiguous triggering increases the risk of unintended activation and data exfiltration.
This configuration section confirms a default external API endpoint and reinforces that the skill sends document contents off-device. Given that business licenses contain sensitive organizational data, this transmission is materially risky in agent contexts where uploads may happen automatically or with incomplete user awareness.
| 变量名 | 默认值 | 说明 |
|--------|--------|------|
| SCNET_API_KEY | 必需 | Scnet API 密钥 |
| SCNET_API_BASE | https://api.scnet.cn/api/llm/v1 | API 基础地址(一般无需修改) |
### 输出
The file documents transmission of uploaded documents to an external endpoint, which is a real data-flow/security concern because business licenses and related PDFs/archives are sent off-platform to api.scnet.cn. In this skill context, external transmission is core functionality rather than inherently malicious, but it still expands the trust boundary and can expose sensitive data if users are not clearly informed and protected.
# Sugon-Scnet OCR API 文档摘要
## 接口地址
`POST https://api.scnet.cn/api/llm/v1/ocr/recognize`
## 请求头
- `Content-Type: multipart/form-data`
The documentation instructs clients to upload business license images/files to a third-party remote OCR API using a bearer token, but it provides no warning that these documents contain sensitive company and potentially personal information. In this skill context, the uploaded content includes business registration data, legal representative names, addresses, and possibly PDFs/archives, so omitting disclosure and handling guidance increases privacy, compliance, and unintended data-exfiltration risk.
The docstring, error messages, retry notices, and CLI usage are all presented only in Chinese, which imposes a specific language on users. The file does not offer any user opt-in, alternate locale, or justification that this skill is restricted to a Chinese-only regional context.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
" b) 配置文件:\n"
f" mkdir -p {SKILL_ROOT}/config\n"
f" echo 'SCNET_API_KEY=你的密钥' > {ENV_FILE}\n"
f" chmod 600 {ENV_FILE}\n"
"\n配置完成后重新运行。"
)
sys.exit(error_msg)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
" b) 配置文件:\n"
f" mkdir -p {SKILL_ROOT}/config\n"
f" echo 'SCNET_API_KEY=你的密钥' > {ENV_FILE}\n"
f" chmod 600 {ENV_FILE}\n"
"\n配置完成后重新运行。"
)
sys.exit(error_msg)
The skill uploads user-supplied document files to an external OCR service at api.scnet.cn. Because business licenses contain sensitive corporate and personal data, this creates a real data-exfiltration/privacy risk if users are not explicitly informed, if the endpoint is untrusted or misconfigured, or if the base URL can be altered to another host.
)
sys.exit(error_msg)
config.setdefault('SCNET_API_BASE', 'https://api.scnet.cn/api/llm/v1')
return config
def recognize_with_retry(ocr_type, file_path, config, retry_count=0):
The manifest description states the skill is specifically for '中国大陆' business licenses, which imposes a locale restriction in natural-language metadata without presenting it as an optional or user-selected scope. The policy allows locale constraints when clearly documented and justified, but here it reads as a hard constraint without opt-in language.
The file presents its user-facing changelog primarily in Chinese, including headings and feature descriptions, with no indication that alternative languages are available. Under the language/locale policy, a user-facing skill artifact that effectively enforces a single language without opt-in can be considered a natural-language policy violation.
SQP-3 applies to all file types and covers language or locale policy violations when a skill forces a specific language without user opt-in. This API documentation appears fully Chinese-language and does not indicate that Chinese is optional or required for a justified region-specific context.
No suspicious patterns detected.