Back to skill

Security audit

SRT

Security checks for vulnerabilities and agentic risk

Overview

This SRT booking skill is coherent, but it needs Review because it combines account credentials, long-running background automation, Discord reporting of booking details, and weak PID-file process control.

Install only if you are comfortable giving the skill your SRT account credentials and letting it make or cancel reservations under your account. Avoid the continuous monitoring mode unless you understand the background process, cron jobs, log location, Discord destination, and cleanup steps; do not use PID files you did not create, and prefer a pinned, reviewed SRTrain dependency version.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/reserve.py:348
Finding
Unverified PID File Allows Termination of Unrelated Processes<![CDATA[ ## Vulnerability Details **File Location**: `scripts/reserve.py:348-365` **Vulnerability Type**: Unverified process termination through a user-controlled PID file **Risk Level**: High ### Vulnerable Code ```python def run_stop(args): """Send SIGTERM to the background retry process.""" import signal pid_file = validate_safe_path(Path(args.pid_file)) if not pid_file.exists(): print(f"❌ PID 파일이 없습니다: {pid_file}") sys.exit(1) raw = pid_file.read_text().strip() if not raw.isdigit(): print(f"❌ PID 파일 내용이 유효하지 않습니다: {raw!r}") sys.exit(1) pid = int(raw) try: os.kill(pid, signal.SIGTERM) print(f"✅ 프로세스 {pid} 종료 요청 완료") except ProcessLookupError: print(f"⚠️ 프로세스 {pid}는 이미 종료되어 있습니다") except PermissionError: print(f"❌ 프로세스 {pid} 종료 권한 없음") sys.exit(1) ``` ### Technical Analysis The `reserve stop` command accepts an arbitrary PID-file path. Although `validate_safe_path()` restricts the path to the user's home directory or the system temporary directory, it does not establish that: - The file was created by this Skill. - The PID represents an SRT retry worker. - The process start time matches the worker that originally wrote the file. - The file is owned by the current user and has safe permissions. - The file is not a symlink or an attacker-controlled file in a shared temporary directory. After confirming only that the file contains digits, the code passes the value directly to `os.kill()` with `SIGTERM`. Consequently, the command can signal any process that the operating-system account is permitted to signal. This behavior exceeds the minimum privilege needed to stop an SRT retry worker. Path confinement is not process-identity validation. ### Attack Path 1. An attacker or untrusted caller identifies the PID of another process running under the same operating-system account. 2. The attacker creates a file under an accepted location, such as ...[truncated 1077 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store PID files only in a dedicated, application-controlled directory with mode `0700`, rather than accepting arbitrary files throughout the home and temporary directories. 2. Create PID files securely using exclusive creation and reject symbolic links. 3. Store additional worker identity information alongside the PID, including: - A cryptographically random launch token. - The process start time. - The expected executable and command-line arguments. 4. Before signaling, verify that the current process start time and command line match the recorded SRT retry worker. On Linux, this can be checked through `/proc/<pid>/stat` and `/proc/<pid>/cmdline`. 5. Verify that the PID file is a regular file owned by the current user and is not group- or world-writable. 6. Prefer retaining a process handle or using a dedicated authenticated local control channel when lifecycle management occurs within one supervising process. 7. Remove stale PID files after successful shutdown and refuse to act when any identity check fails. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:13
Finding
Unpinned Runtime Dependency Handles SRT Account Credentials<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:13-16` **Additional Locations**: `SKILL.md:40-41`, `SKILL.md:47`, `SKILL.md:52` **Vulnerability Type**: Unpinned third-party dependency and dynamic runtime resolution **Risk Level**: Medium ### Vulnerable Configuration ```yaml "requires": { "bins": ["python3", "uv"], "env": ["SRT_PHONE", "SRT_PASSWORD"] }, "install": [ {"id": "uv", "kind": "uv", "package": "SRTrain", "label": "Install SRTrain from PyPI (uv) — source: https://pypi.org/project/SRTrain / https://github.com/ryanking13/SRT"} ] ``` The documented commands dynamically request the same unpinned package: ```bash uv run --with SRTrain python3 scripts/srt_cli.py train search \ --departure "수서" --arrival "동대구" --date "20260227" --time "200000" ``` ### Technical Analysis The dependency declaration specifies `SRTrain` without an exact version, lockfile, or integrity hash. The documented use of `uv run --with SRTrain` allows dependency resolution to occur when commands are run. The imported package executes in the same Python process as the Skill and is directly supplied with the user's sensitive SRT credentials. Relevant calls include: ```python srt = SRT(credentials['phone'], credentials['password']) ``` This credential transmission is necessary for the declared SRT authentication, search, reservation, listing, and cancellation functionality. No repository code was found sending credentials to an unrelated endpoint. However, the trustworthiness of that behavior depends on whichever package version is resolved at runtime. If the package distribution or maintainer account is compromised, or a malicious future release is published, that release could execute arbitrary code and access both credentials and the user's local execution context. ### Attack Path 1. A malicious or compromised release of the `SRTrain` package is published through the configured package source. 2. A user executes one of the documented `uv run --with SRTra ...[truncated 1026 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `SRTrain` to an exact, reviewed version instead of using an unconstrained package name. 2. Maintain a committed lockfile containing resolved transitive dependencies. 3. Enforce package integrity hashes during installation. 4. Install dependencies once from an explicitly configured trusted registry rather than dynamically resolving them for every command. 5. Review package source and release changes before updating the pinned version. 6. Use automated dependency scanning and provenance verification where available. 7. Run the Skill in a constrained environment with access only to the credentials and files required for SRT operations. 8. Document the destination and purpose of credential transmission so users understand that SRT authentication necessarily shares the phone number and password with the selected client library and SRT service. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Intent-Code Divergence

High
Confidence
91% confidence
Finding
The documentation claims path validation for SRT_DATA_DIR and --log-file, but this file provides no implementation evidence for that control. If the runtime does not actually enforce these restrictions, an attacker or unsafe prompt could direct logs, PID files, or cache data to arbitrary filesystem locations, potentially overwriting files or exposing sensitive data.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises shell, environment, and file read/write behavior but does not declare any explicit tool scope or permission boundaries. That creates an over-privileged and opaque execution model where an agent may invoke sensitive capabilities without a documented least-privilege contract, increasing the chance of unintended credential exposure or filesystem changes.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill requires SRT account credentials in environment variables but gives no warning about secure handling, redaction, or process/log exposure. In agent and shell-based environments, environment variables can leak through debugging output, subprocess inheritance, crash reports, or misconfigured logging.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The markdown states `Station names (Korean only)` and later specifies extraction from Korean input, which imposes a language constraint in natural-language instructions. Because no user opt-in or alternative language handling is offered, this is a locale/language policy issue under the stated rules.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
LOG_FILE=<choose_any_path>.log
PID_FILE=<choose_any_path>.pid
cd <project_dir> && nohup uv run --with SRTrain python3 scripts/srt_cli.py reserve retry \
  --train-id <id> --timeout-minutes 1440 --wait-seconds 10 \
  --log-file "$LOG_FILE" > /dev/null 2>&1 &
echo $! > "$PID_FILE"
Confidence
92% confidence
Finding
The skill explicitly instructs launching a long-lived background process with nohup and separate cron jobs to monitor and terminate it. This introduces persistence behavior that can outlive the initiating session, making it harder to audit, easier to abuse for unattended activity, and more likely to leave residual processes or files containing sensitive state.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The monitoring flow instructs background logging, log tailing, and Discord reporting, and the examples explicitly mention sending reservation numbers and seat information on success. Without sensitivity warnings or redaction requirements, this can disclose booking details and operational state through logs or third-party messages.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The skill extends beyond train reservation into cron-job orchestration and Discord messaging, which are not necessary for core booking functionality. Expanding into cross-system automation increases the attack surface and can enable persistence, unintended notifications, or data exfiltration of reservation details to third-party channels.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This code presents operational status and error information in Korean, and the pattern continues throughout the file. Because the skill does not offer user language selection or explain that it is intentionally Korea-specific, it violates the language/locale policy for natural-language content.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The skill exposes process-management actions via user-supplied pid_file data and then calls os.kill() on the referenced PID. In the context of an SRT reservation tool, the ability to probe arbitrary process existence and send SIGTERM to arbitrary local processes is unnecessary and can be abused to disrupt unrelated processes if an attacker can influence the PID file path or contents.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This code defines all CLI descriptions and argument help text in Korean only, and elsewhere in the file user-facing status/error messages are also Korean. Under the policy, forcing a specific language without user opt-in or clear justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This Python file contains multiple user-facing natural-language strings in Korean, beginning at L036-L037 and continuing throughout the module. Because the skill does not offer user opt-in for language selection or document that it is intentionally Korea-specific, it appears to force a specific language/locale in violation of the language-choice policy.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
This code file contains user-facing natural-language strings such as examples, help text, and argument descriptions entirely in Korean. The file does not indicate that the locale is region-specific or provide an opt-in/choice for language, which can violate a language/locale policy requiring user choice.

Static analysis

No suspicious patterns detected.