Back to skill

Security audit

2026-3-22dataset

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its RAGFlow management purpose, but it needs review because it sends API keys and uploaded documents to a configured URL without enforcing HTTPS or redirect safety.

Install only if you trust the configured RAGFlow endpoint and can use HTTPS or a loopback development URL. Use a narrowly scoped RAGFlow API key, confirm exact dataset or document IDs before deletion, and avoid uploading sensitive files unless the endpoint and network path are trusted.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/common.py:84
Finding

Bearer Credentials and Uploaded Documents May Be Transmitted over Insecure HTTP or Cross-Origin Redirects

Content
View full analysis
str: base_url = (cli_base_url or "").strip() or _require_env_var(RAGFLOW_API_URL_ENV) parsed = urllib.parse.urlsplit(base_url) if not parsed.scheme or not parsed.netloc: raise ConfigError( f"Invalid {RAGFLOW_API_URL_ENV}. Use an absolute URL such as http://127.0.0.1:9380." ) return base_url.rstrip("/") ``` ```python def request_json( url: str, api_key: str, *, method: str = "GET", body: bytes | None = None, content_type: str | None = None, accept: str = "application/json", ) -> dict[str, Any]: headers = {"Authorization": f"Bearer {api_key}"} if accept: headers["Accept"] = accept if content_type: headers["Content-Type"] = content_type request_obj = urllib.request.Request(url, headers=headers, data=body, method=method) try: with urllib.request.urlopen(request_obj, timeout=HTTP_TIMEOUT) as response: return decode_json_response(response.read()) except urllib.error.HTTPError as exc: body_bytes = exc.read() response_payload = decode_json_body(body_bytes) response_text = decode_response_text(body_bytes) message = extract_error_message(body_bytes) if message: raise ApiError( message, http_status=exc.code, api_code=response_payload.get("code") if isinstance(response_payload, dict) else None, response_payload=response_payload, response_body=response_text, ) from None raise ApiError( f"HTTP r ...[truncated 4281 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/parse_status.py:89
Finding

Targeted Parse-Status Requests Retrieve Metadata for Every Document in the Dataset

Content
View full analysis
list[dict[str, Any]]: all_docs: list[dict[str, Any]] = [] page = 1 total: int | None = None while True: docs, page_total = _fetch_documents_page(base_url, api_key, dataset_id, page, DEFAULT_PAGE_SIZE) if total is None: total = page_total all_docs.extend(docs) if len(all_docs) >= total or not docs: return all_docs[:total] page += 1 ``` ```python def _select_documents(documents: list[DocumentStatus], target_ids: list[str] | None) -> list[DocumentStatus]: if not target_ids: return documents documents_by_id = {document.id: document for document in documents} missing_ids = [doc_id for doc_id in target_ids if doc_id not in documents_by_id] if missing_ids: raise DataError("--doc-ids contains document IDs that were not found in the dataset: " + ", ".join(missing_ids)) return [documents_by_id[doc_id] for doc_id in target_ids] ``` ```python def collect_status_payload( dataset_id: str, target_ids: list[str] | None = None, *, base_url: str | None = None, api_key: str | None = None, ) -> dict[str, Any]: resolved_base_url = resolve_base_url(base_url) resolved_api_key = require_api_key(api_key) raw_documents = _fetch_all_documents(resolved_base_url, resolved_api_key, dataset_id) documents = [_normalize_document(raw_doc) for raw_doc in raw_documents] return _build_payload(dataset_id, _select_documents(documents, target_ids)) ``` ### Technical Analysis When the caller supplies `--doc-ids`, the expected scope is limited to those explicitly selected documents. Instead, `collect_status_payload` alwa ...[truncated 2319 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • 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 (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The supplied code is narrowly focused on dataset CRUD subset operations: listing datasets, inspecting a dataset by searching the fetched list, creating a dataset, and deleting datasets. It interacts only with the datasets endpoint and contains no code for document management, parsing control, parse-status checks, search/chunk retrieval, model listing, or dataset updates. Because the declared description presents the skill as covering a substantially broader set of capabilities than this code actually provides, the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 43)May include surrounding context.

md
python3 scripts/upload.py DATASET_ID /path/to/file.pdf --json

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 44)May include surrounding context.

md
python3 scripts/upload.py DATASET_ID /path/to/file.pdf --json

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 · SKILL.md (reported line 69)May include surrounding context.

md
- If a parse status result includes `progress_msg`, surface it directly. For `FAIL`, treat it as the primary error detail.
- Use `--retrieval-test` only for single-dataset debugging or when the user explicitly asks for that endpoint.

## Output Rules

- Follow `reference.md`.
- Use tables for 3+ items when possible.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The function named and documented as stopping document parsing issues a DELETE request to the dataset /chunks endpoint with document IDs. In the context of a RAGFlow dataset-management skill, this can cause destructive data loss instead of a reversible stop action, and users or upstream agents may invoke it believing it is safe operational control rather than deletion.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares access to sensitive capabilities through required environment variables and directs use of local scripts that can read files and make network requests, but it does not define an explicit tool/permission scope. That creates an over-broad execution surface where an agent may use more capability than a reviewer or user expects, especially given dataset management and upload/search operations against an external API.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill advertises destructive delete operations in its description without a prominent upfront warning about irreversible data loss. Although later guardrails require listing items and explicit confirmation, users or orchestrators may rely on the high-level description and underestimate the risk of invoking the skill for deletion workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The delete command issues a destructive API request immediately from user-supplied IDs with no interactive confirmation, dry-run, or force/confirm guard. In an agent skill context, this increases the chance of accidental or misrouted dataset deletion from operator error, prompt confusion, or unsafe automation, even if the underlying API is authenticated.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/common.py (reported line 59)May include surrounding context.

python
return

    for stream_name in ("stdout", "stderr"):
        stream = getattr(sys, stream_name, None)
        if stream is None or not hasattr(stream, "reconfigure"):
            continue
        try:

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code reads a credential from the RAGFLOW_API_KEY environment variable, but there is no nearby comment, docstring, or user-facing message warning that a sensitive credential is being consumed. Under the code-file criteria, access to sensitive environment variables should include some form of disclosure when no other warning is visible in the file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This helper performs outbound HTTP requests with a Bearer API key and may transmit request data, but the code provides no confirmation prompt, logging, or inline comment/docstring disclosing that network transmission occurs. For code files, network calls that transmit user or system data should have some visible disclosure unless the warning is documented elsewhere, which is not evident in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This code performs a network call and includes an Authorization bearer token in the request headers, which transmits credential-bearing data to a remote API. In this file there is no confirmation prompt, user-facing warning, or inline comment/docstring disclosing that the script will contact the API using the configured credential.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.