Back to skill

Security audit

Gsdata

Security checks for vulnerabilities and agentic risk

Overview

This is a functional GSData API adapter, but it exposes credentials and remote account changes through under-scoped network and raw endpoint controls that need review before installation.

Review this before installing. Use only least-privileged GSData credentials, avoid custom base URLs, require an HTTPS allowlisted endpoint, disable or tightly restrict gsdata_raw, and manually confirm any warning-rule, ranking-group, account, or recipient-management operation before running it.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
gsdata_adapter.py:24
Finding
Credential-Derived Authentication Material Transmitted over Plaintext HTTP## Vulnerability Details **File Location**: `gsdata_adapter.py:24`, `gsdata_adapter.py:203-213`, `gsdata_adapter.py:408-410`, and `gsdata_adapter.py:453-460` **Vulnerability Type**: Plaintext transmission of sensitive authentication material **Risk Level**: High ### Vulnerable Code ```python DEFAULT_BASE_URL = "http://databus.gsdata.cn:8888/api/service" ``` ```python def make_sign(params: Dict[str, Any], app_secret: str) -> str: # GSData signature: md5(app_secret + "_" + sorted(kv concat) + "_" + app_secret) sorted_items = sorted(params.items(), key=lambda x: x[0]) concat = "".join(f"{k}{v}" for k, v in sorted_items) raw = f"{app_secret}_{concat}_{app_secret}" return hashlib.md5(raw.encode("utf-8")).hexdigest() def make_access_token(app_key: str, sign: str, router: str) -> str: return base64.b64encode(f"{app_key}:{sign}:{router}".encode("utf-8")).decode( "utf-8" ) ``` ```python sign = make_sign(params, self.app_secret) token = make_access_token(self.app_key, sign, route) headers = {"access-token": token} ``` ```python def _request( self, method: str, params: Dict[str, Any], headers: Dict[str, str] ) -> requests.Response: # GSData gateway commonly accepts params in query/body against one base URL. if method == "POST": return requests.post( self.base_url, data=params, headers=headers, timeout=30 ) return requests.get(self.base_url, params=params, headers=headers, timeout=30) ``` ### Technical Analysis The adapter defaults to an unencrypted `http://` GSData endpoint. Every non-dry-run request includes an `access-token` containing the application key, a secret-derived MD5 signature, and the selected API route. Request parameters are also transmitted in either the URL query string or POST body. Base64 is only reversible encoding and provides no confidentiality. Although the application secret itself is n ...[truncated 1665 chars]
Remediation
## Remediation Suggestions 1. Replace the default endpoint with an official HTTPS endpoint. 2. Reject any base URL whose scheme is not `https`. 3. Retain TLS certificate verification and do not introduce `verify=False`. 4. Consider pinning or allowlisting the expected GSData hostname. 5. Fail closed if HTTPS is unavailable rather than falling back to plaintext HTTP. 6. If the GSData protocol supports it, migrate from MD5-based signing to a modern construction such as HMAC-SHA-256. 7. Confirm that the server enforces short validity periods, nonces, timestamps, and replay protection for signed requests. 8. Avoid placing sensitive query data in URL parameters where the API permits use of protected POST bodies.

T09 · Insecure Skill Coding Practices

Error
Location
gsdata_adapter.py:641
Finding
Unrestricted Base URL Override Can Redirect Authentication Material to an Attacker-Controlled Host## Vulnerability Details **File Location**: `gsdata_adapter.py:641-644`, `gsdata_adapter.py:753-757`, and `gsdata_adapter.py:453-460` **Vulnerability Type**: Unvalidated credential destination and excessive network configurability **Risk Level**: High ### Vulnerable Code ```python parser.add_argument( "--base-url", default=os.getenv("GSDATA_BASE_URL", DEFAULT_BASE_URL), help="GSData gateway base URL", ) ``` ```python adapter = GsDataAdapter( app_key=args.app_key or "DUMMY_APP_KEY", app_secret=args.app_secret or "DUMMY_APP_SECRET", base_url=args.base_url, mapping_path=Path(args.mapping), ) ``` ```python def _request( self, method: str, params: Dict[str, Any], headers: Dict[str, str] ) -> requests.Response: # GSData gateway commonly accepts params in query/body against one base URL. if method == "POST": return requests.post( self.base_url, data=params, headers=headers, timeout=30 ) return requests.get(self.base_url, params=params, headers=headers, timeout=30) ``` ### Technical Analysis The network destination can be replaced through either the `--base-url` command-line argument or the `GSDATA_BASE_URL` environment variable. No scheme, hostname, port, or path validation is applied before the adapter sends the `access-token` and user-supplied parameters to that destination. As a result, a poisoned execution environment or unsafe command invocation can redirect credential-derived authentication material to an arbitrary server. Allowing unrestricted destinations is broader than necessary for the declared purpose of communicating with the GSData platform. The application secret is not sent directly. However, the destination receives the application key, secret-derived signature, route, and request parameters contained in or accompanying the access token. ### Attack Path 1. An attacker gains influence over the process ...[truncated 1109 chars]
Remediation
## Remediation Suggestions 1. Pin the production endpoint to an official HTTPS GSData hostname. 2. Validate the parsed URL before generating or transmitting authentication material. 3. Enforce an allowlist for the scheme, hostname, port, and expected API path. 4. Remove the environment override in production or require an explicit development-only mode. 5. Never allow production credentials to be used when a custom endpoint is selected. 6. Reject loopback, link-local, private-network, non-HTTPS, and unexpected redirect destinations unless specifically required and safely configured. 7. Disable automatic cross-origin redirects for authenticated requests or strip authentication headers before any permitted redirect. 8. Log the selected destination without logging credentials or access tokens so destination changes can be audited.

T09 · Insecure Skill Coding Practices

Warning
Location
gsdata_adapter.py:463
Finding
Raw API Interface Can Bypass Write Confirmation through Heuristic Route Classification## Vulnerability Details **File Location**: `gsdata_adapter.py:396-405`, `gsdata_adapter.py:463-470`, `gsdata_adapter.py:677-689`, and `gsdata_adapter.py:792-801` **Vulnerability Type**: Incomplete authorization enforcement for potentially mutating requests **Risk Level**: Medium ### Vulnerable Code ```python if self._is_write_route(route) and not allow_write: return { "ok": False, "error": "WRITE_BLOCKED", "message": ( "This route is considered write/high-risk. " "Pass allow_write=true after explicit confirmation." ), "route": route, "method": method, } ``` ```python @staticmethod def _is_write_route(route: str) -> bool: if "/warning/" in route: # warning module has both read and write; keep reads open if route.endswith(("/index", "/news", "/stats")): return False return True return any(s in route for s in WRITE_SUFFIX_HINTS) ``` ```python p_raw = sub.add_parser("raw", help="Invoke arbitrary route via gsdata_raw") p_raw.add_argument("--path", required=True) p_raw.add_argument("--method", default="GET") p_raw.add_argument("--params", help='JSON object, e.g. \'{"id":"123"}\'') p_raw.add_argument("--params-file", help="Path to JSON object file") p_raw.add_argument( "--param", action="append", default=[], help="Repeatable key=value param. Example: --param id=123", ) p_raw.add_argument("--dry-run", action="store_true") p_raw.add_argument("--allow-write", action="store_true") ``` ```python if args.cmd == "raw": result = adapter.invoke( tool="gsdata_raw", action="call_any_endpoint", params=_merge_params(args.params, args.params_file, args.param), dry_run=args.dry_run, allow_write=args.allow_write, explicit_path=args.path, explicit_method=args.method, ) ...[truncated 2172 chars]
Remediation
## Remediation Suggestions 1. Require `--allow-write` for every raw request, regardless of path or HTTP method. 2. At minimum, treat all methods other than GET and HEAD as potentially mutating. 3. Deny unknown raw routes by default and permit only routes present in trusted endpoint metadata. 4. Replace substring matching with an explicit per-endpoint classification of read-only and mutating operations. 5. Fail closed when an endpoint cannot be conclusively classified as read-only. 6. Keep the raw interface disabled in normal agent use or place it behind a separate development option. 7. Require explicit user confirmation containing the exact route, method, and material parameters before executing a mutating request. 8. Add tests covering unknown paths, non-GET methods, redirects, and mutating routes whose names do not contain the current write suffix hints.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Credential Access

High
Category
Privilege Escalation
Content
DEFAULT_BASE_URL = "http://databus.gsdata.cn:8888/api/service"
DEFAULT_MAPPING_PATH = Path(__file__).with_name("gsdata_tool_mapping_v1.json")
DEFAULT_CREDS_PATH = Path.home() / ".config" / "gsdata" / "credentials.json"


ACCOUNT_PLATFORMS = {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
DEFAULT_BASE_URL = "http://databus.gsdata.cn:8888/api/service"
DEFAULT_MAPPING_PATH = Path(__file__).with_name("gsdata_tool_mapping_v1.json")
DEFAULT_CREDS_PATH = Path.home() / ".config" / "gsdata" / "credentials.json"


ACCOUNT_PLATFORMS = {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Description-Behavior Mismatch

High
Confidence
93% confidence
Finding
The adapter includes warning-rule management actions such as create, update, open, close, and recipient email modification, which are state-changing operations outside the stated query/search scope. Even with `allow_write` gating, the code still exposes administrative functionality that could alter alerts or notification settings if invoked.

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
The `gsdata_raw` path bypasses the curated high-level tool surface and allows callers to target arbitrary GSData routes. In a skill advertised as query-oriented, this materially expands capability and can be used to reach unintended read or write endpoints, undermining least privilege and review assumptions.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The skill is presented as query/search oriented, but the mapping exposes multiple state-changing endpoints for custom rank/group management, including add/delete group and account operations. This creates a capability mismatch: an agent invoked for benign data lookup could be induced to mutate persistent user data or account configuration, increasing the risk of unauthorized actions through prompt confusion or social engineering.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The manifest emphasizes public opinion search, hot-topic analysis, rankings, and data queries, but the mapping also includes warning-rule administration, enable/disable actions, and notification-recipient management. These are privileged configuration operations unrelated to simple querying, so an attacker could abuse the skill’s broader-than-advertised authority to create surveillance rules, alter alerting behavior, or redirect notifications.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill declares access to sensitive capabilities through its design and instructions: it uses environment secrets, reads bundled files, and performs network requests, but it does not constrain tool scope with explicit permissions or allowed-tools metadata. In an agent environment, that increases the chance the skill can invoke broader-than-necessary capabilities or be misused through prompt injection or ambiguous orchestration, especially because it instructs the agent to execute a local adapter script against an external API.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger phrases are broad generic terms like '舆情', '热点', '榜单', and '关键词检索', which can match many ordinary user requests unrelated to this specific skill. In a multi-skill agent, that can cause unintended activation of a capability that reads env-backed credentials and performs external queries, increasing the risk of unnecessary data exposure, wrong-tool execution, or abuse via crafted prompts.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The adapter sends caller-supplied parameters over HTTP(S) via requests.get/requests.post, but there is no print statement, confirmation prompt, or user-facing warning at the request point describing that input data will be transmitted to an external service. Because this is a code file and the operation involves network transmission of potentially user or system data, it meets the missing-warning criterion.

Context-Inappropriate Capability

Medium
Confidence
78% confidence
Finding
The manifest frames the skill as a GSData query adapter and does not mention local credential discovery from environment variables or `~/.config/gsdata/credentials.json`. While authentication may be needed for implementation, automatic access to local secrets is an additional capability not disclosed by the skill’s stated purpose.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The credential resolution logic reads sensitive authentication material from GSDATA_APP_KEY/GSDATA_APP_SECRET and from ~/.config/gsdata/credentials.json, but the file provides no disclosure, confirmation, or user-facing notice that secrets will be accessed. Access to sensitive environment variables or credentials is explicitly in scope for missing-warning findings on code files.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
Adding or deleting email recipients for warning notifications is a state-changing capability that is not justified by the skill’s stated query-focused purpose. If misused, it could redirect sensitive alert content to unauthorized recipients or suppress legitimate monitoring by removing intended recipients, causing privacy leakage and operational blind spots.

Static analysis

No suspicious patterns detected.