Back to skill

Security audit

TCL (Lyon public transport network)

Security checks for vulnerabilities and agentic risk

Overview

This is a localized Lyon transit schedule helper with some overconfident source-selection wording, but no evidence of credential access, persistence, destructive behavior, or hidden data flow.

Reasonable to install if you want a French TCL Lyon schedule helper and understand it depends on a local tcl.db whose freshness is not verified here. For real-time delays, disruptions, missing database errors, or time-sensitive trip planning, corroborate with an official live source rather than relying on the skill's instruction to avoid web search.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (2)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:3
Finding

Absolute Source-Selection Instructions Override Agent Tool Choice

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
tcl_tool.py:303
Finding

Unbounded Departure Limit Can Trigger Excessive Database Queries and Output

Content
View full analysis
= ? {} AND t.service_id IN ({}) ORDER BY st.departure_time LIMIT ? """.format(line_filter, ",".join("?" * len(active))), params).fetchall() ``` The command-line parser converts the supplied value to an integer but does not enforce minimum or maximum bounds: ```python if cmd == "departures": limit = int(remaining[2]) if len(remaining) >= 3 else 5 print(get_next_departures(arg, limit=limit, line=line)) ``` ### Technical Analysis The `limit` argument is parameterized, so this is not SQL injection. However, it is accepted without range validation. SQLite interprets a negative `LIMIT`, including `LIMIT -1`, as no limit. Very large positive values can similarly cause the query to retrieve substantially more data than the documented default of five records. The stop search can return up to ten matching stops. The departure query is then executed separately for each stop, and every returned row is loaded using `fetchall()` and converted into output strings. A broad stop-name match combined with a negative or excessive limit can therefore increase database work, process memory consumption, and generated o ...[truncated 1478 chars]
Remediation
View remediation
= 3 else 5 except ValueError: raise SystemExit("The departure limit must be an integer.") if not 1 <= limit <= 100: raise SystemExit("The departure limit must be between 1 and 100.") ``` 2. Apply the same validation inside `get_next_departures` so direct Python callers cannot bypass command-line validation: ```python if not isinstance(limit, int) or isinstance(limit, bool): raise ValueError("limit must be an integer") if not 1 <= limit <= 100: raise ValueError("limit must be between 1 and 100") ``` 3. Avoid `fetchall()` where practical. Iterate over a bounded cursor or use `fetchmany()` to keep memory use predictable. 4. Retain SQL parameterization for all caller-controlled values. 5. Add tests covering zero, negative values, very large integers, non-integer input, broad stop-name matches, and direct function invocation. 6. Consider a total response cap across all matched stops rather than applying the maximum independently to each stop. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (2)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest description and primary instructions are written in French and include imperative guidance such as using this source in priority, but do not offer any user opt-in or alternative language. This can violate language/locale policy because the skill appears to enforce a specific language experience without documenting that it is intended only for French-speaking or Lyon-localized users.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

Docstrings, status messages, and CLI output throughout the file are written in French, which effectively forces a specific language for user-facing interactions. The file does not indicate any user opt-in, locale selection, or region-justified language constraint.

Content

No source excerpt is available for this finding.