Back to skill

Security audit

Hong Kong Bus ETA | 香港巴士預計到達時間

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a legitimate Hong Kong bus ETA helper that uses public transit APIs and skill-local cache files, with no evidence of credential access, exfiltration, or destructive system behavior.

Install only if you are comfortable with the skill making outbound requests to Hong Kong public transit data APIs and maintaining local SQLite/JSON cache files. The cache sync can run in the background when stale, so review or disable that behavior if you require every network update to be manually initiated.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
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 (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose centers on real-time Hong Kong bus ETA lookup with next-bus speed, bilingual ETA output, fuzzy stop matching, multi-line concurrent queries, and fallback handling for no service/last bus. The supplied code only performs static local database operations: stop-name search, nearby-stop search by coordinates, route-stop listing, and database info retrieval. While fuzzy stop matching and bilingual stop fields are partially consistent with the description, the core promised capability—real-time ETA lookup—is absent. There is also no evidence of external API calls, schedule/ETA parsing, concurrency, or no-result ETA fallback behavior. Therefore the description materially overstates and misrepresents the code's actual primary function.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is for an end-user 'next bus' ETA lookup skill. The supplied code chunk is not an ETA query handler; it is an offline maintenance/sync script. It downloads static route/stop data, drops and recreates database tables, inserts route/stop records, creates name indexes, and builds a full CTB stop coordinate cache by calling route-stop and stop metadata APIs. While this data could support a bus ETA skill, the code itself does not implement ETA retrieval, fuzzy matching behavior, bilingual output formatting, no-result fallback logic, or multi-route ETA querying. Its primary purpose is materially different from the declared purpose, so this is a mismatch.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 32)May include surrounding context.

md
**Data Sources:**
- **KMB/LWB**: `https://data.etabus.gov.hk/v1/transport/kmb/`
- **Citybus**: `https://rt.data.gov.hk/v2/transport/citybus/`
- **Bus Stop Data**: `https://data.gov.hk/` (開放數據平台)

### Database Schema | 數據庫結構

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill invokes shell commands, performs network access to public endpoints, and writes local files, but it does not declare enforceable tool permissions such as allowed-tools or permissions. Relying on prose-only restrictions in the README is weak because an execution framework may grant broader capabilities than intended, increasing the blast radius if the skill or its scripts are modified or abused.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest presents the skill as a Hong Kong bus ETA lookup for next-bus/arrival-time queries, but this file only performs local database queries for stop names, nearby stops, route stops, and database metadata. No code here calls live ETA sources or computes arrival times, so the implemented behavior in this file materially differs from the advertised ETA-focused purpose.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 30)May include surrounding context.

md
return d
    
    # Try to refresh, but return cache if fetch fails
    r = fetch("https://data.etabus.gov.hk/v1/transport/kmb/stop")
    if r and 'data' in r:
        s = {st['stop']: st for st in r['data']}
        s['_ts'] = time.time()

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
return d
    
    # Try to refresh, but return cache if fetch fails
    r = fetch("https://data.etabus.gov.hk/v1/transport/kmb/stop")
    if r and 'data' in r:
        s = {st['stop']: st for st in r['data']}
        s['_ts'] = time.time()

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/eta.py (reported line 67)May include surrounding context.

python
return d
    
    # Try to refresh, but return cache if fetch fails
    r = fetch("https://data.etabus.gov.hk/v1/transport/kmb/stop")
    if r and 'data' in r:
        s = {st['stop']: st for st in r['data']}
        s['_ts'] = time.time()

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/eta.py (reported line 272)May include surrounding context.

python
return d
    
    # Try to refresh, but return cache if fetch fails
    r = fetch("https://data.etabus.gov.hk/v1/transport/kmb/stop")
    if r and 'data' in r:
        s = {st['stop']: st for st in r['data']}
        s['_ts'] = time.time()

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/eta.py (reported line 298)May include surrounding context.

python
return d
    
    # Try to refresh, but return cache if fetch fails
    r = fetch("https://data.etabus.gov.hk/v1/transport/kmb/stop")
    if r and 'data' in r:
        s = {st['stop']: st for st in r['data']}
        s['_ts'] = time.time()

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The function signature sets lang="tc" as the default, and the script consistently uses that default unless the caller explicitly supplies another language. This creates a language/locale policy concern because the skill imposes a specific locale by default rather than offering a user choice or opt-in.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The ETA skill has functionality beyond simple lookup: it can spawn a detached background updater after servicing a request. In an agent-skill context, hidden process creation increases attack surface, can bypass caller expectations, and may be abused for persistence-like behavior or unbounded resource consumption if invoked repeatedly.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/eta.py (reported line 478)May include surrounding context.

python
print("\n".join(output))
    if needs_bg_sync:
        sync_script = os.path.join(BASE_DIR, "sync_bus_stops.py")
        try: subprocess.Popen(["python3", sync_script], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
        except: pass

if __name__ == "__main__":

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code drops and recreates the core database tables, which is a destructive operation affecting existing local data. While the script prints progress messages, it does not disclose to the user that running sync will delete and rebuild the current database contents, and that warning is not otherwise visible in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The documentation explicitly constrains output language to tc or en. Under the policy rule for natural-language violations, forcing a specific language/locale without broader user choice or documented justification can be a locale policy issue.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

find_stops_by_name documents and constructs results with name_tc and name_en, but the test code accesses s['stop_name_tc'], which is not produced by the function. This makes the inline usage example contradict the function's actual return shape and can mislead maintainers about what the code returns.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The function signature sets lang='tc' as a default, and the script's natural-language context is Hong Kong-specific, which can bias output toward a specific locale without explicit user opt-in. Under the policy, forced language or locale behavior should either provide a user choice or clearly justify the constraint.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The changelog text implies general support for automatic background synchronization as a standing feature. In practice, the implementation conditionally triggers a detached sync only in one narrow path after successful output generation and when the local database age exceeds 7 days, which is more limited than the documentation suggests.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.