Back to skill

Security audit

gts-operator / OA通用流程管理

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent GTS operator, but it needs review because it stores a powerful 30-day access token in a predictable local file while enabling high-impact business workflow actions.

Install only if you trust this GTS endpoint and are comfortable granting the agent the same tenant permissions as your account for up to 30 days. Use it on a machine and agent profile you control, protect or remove ~/.gts-operator.json after use, revoke authorization when finished, and require clear confirmations for public template publishing, deletion, approvals, and automatic approve/reject rules.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:59
Finding

Long-Lived Bearer Token Stored in a Predictable Plaintext File

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 59–60 and 89–91
Vulnerability Type: Plaintext storage of sensitive authentication credentials
Risk Level: Medium

Vulnerable Code Snippet

markdown
**Credential storage convention (reused across conversations)**:
- This skill persists its token in the Agent's local file
  **`~/.gts-operator.json`**
  (JSON: `{"token": "<jwt>", "saved_at": <unix>, "tenant_id": <int>, "user": {...}}`).
markdown
- `data.status == "authorized"` → Success! `data.token` is a **30-day token**.
  Write the token to `~/.gts-operator.json`.

The same storage design is documented in README.md, lines 78–80.

Technical Analysis

The Skill directs the Agent to persist a bearer token with a 30-day lifetime in a predictable plaintext file in the user's home directory. The instructions do not require:

  • Owner-only permissions such as mode 0600
  • Verification of file ownership or permissions before reading
  • Protection against symbolic-link attacks
  • Atomic, race-resistant file creation
  • Encryption through an operating-system credential store
  • Minimization of additional identity and tenant metadata

A bearer token provides access based solely on possession. Any local user, process, malicious extension, or compromised Skill that can read this file can reuse the token without knowing the account password. Persisting it across conversations increases the exposure period.

This is credential persistence for the Skill's legitimate authentication function rather than a system-persistence backdoor. It is therefore classified as insecure sensitive-data storage.

Attack Path

  1. A user completes the documented OAuth device authorization.
  2. The Agent receives a bearer token valid for 30 days.
  3. Following the Skill instructions, the Agent writes that token in plaintext to ~/.gts-operator.json.
  4. A malicious local process or another user wit ...[truncated 1406 chars]
Remediation
View remediation

Remediation Suggestions

  1. Store the bearer token in the operating system's credential manager, such as Keychain, Credential Manager, or Secret Service, rather than in a plaintext JSON file.
  2. If file storage is unavoidable:
    • Create the file atomically with owner-only mode 0600.
    • Ensure the containing directory is not writable by other users.
    • Reject symbolic links and use no-follow semantics where supported.
    • Verify the file is a regular file owned by the expected user before every read.
    • Refuse to use files with group or world permissions.
    • Write through a securely created temporary file and atomically rename it.
  3. Store only the token and essential expiry metadata. Avoid persisting unnecessary user and tenant details.
  4. Reduce token lifetime where practical and implement refresh-token rotation or short-lived scoped access tokens.
  5. Scope tokens to the minimum API permissions needed for the requested operation.
  6. Provide a reliable cross-session revocation mechanism that does not depend on retaining the original device code.
  7. Delete local credentials securely on logout, revocation, expiry, validation failure, or tenant-context change.
  8. Never include the token in logs, errors, command histories, telemetry, or user-visible output.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
- `controllers/DelegationController.php`(新):
  - `GET /delegations`(`?mine=1`;管理员看全租户,其他用户只看自己的)
  - `POST /delegations`(`user_id` 仅管理员可指定,默认本人)
  - `PUT /delegations/{id}`、`DELETE /delegations/{id}`(撤销为软删除)
  - 服务端挡下:自代理、跨租户用户、时间窗倒置、**同一被代理人生效期重叠的代理**
  - 列表响应附服务端计算的 `state`(`active`/`scheduled`/`expired`/`revoked`)与 `is_active_now`
- `controllers/BizDataController.php`:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
- `controllers/DelegationController.php`(新):
  - `GET /delegations`(`?mine=1`;管理员看全租户,其他用户只看自己的)
  - `POST /delegations`(`user_id` 仅管理员可指定,默认本人)
  - `PUT /delegations/{id}`、`DELETE /delegations/{id}`(撤销为软删除)
  - 服务端挡下:自代理、跨租户用户、时间窗倒置、**同一被代理人生效期重叠的代理**
  - 列表响应附服务端计算的 `state`(`active`/`scheduled`/`expired`/`revoked`)与 `is_active_now`
- `controllers/BizDataController.php`:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

The skill enables publication and deletion operations in a public template market with dynamic discovery and conversational execution, which raises the risk of an agent being socially engineered into publishing or removing marketplace content without sufficiently strong confirmation. The README also notes there is no review in the public directory, making misuse more impactful because one tenant admin can affect shared market visibility immediately.

Content

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

md
用户型审批人降级为 placeholder,缺依赖入 warnings 不阻断,导入单事务。
  - v2.1.0 **共享市场**:`POST /templates/publish`、`GET /templates/market`、
    `GET /templates/market/{id}/preview`、`POST /templates/market/{id}/install`、
    `DELETE /templates/market/{id}` —— 无审核公共目录,任一租户 admin 可发布、
    发布者可下架(非属主 404);`template_market` 表(软删除)。
  - v2.1.1 **子表自动包含**:`buildPackage()` 递归拉入被引用子表(含多层嵌套),
    因此分享/导出/发布**只需传主表 id**,明细表随包自动带上。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
| "超过 X 小时自动通过/自动驳回" | SOP-G 超时处理(**§0.1 需确认** + `acknowledged`) |
| "我下周休假,审批转给小李" | SOP-G 代理人(`POST /delegations`,给自己设无需确认) |
| "看看谁设了代理/我的代理" | SOP-G 代理人列表(`GET /delegations?mine=1`) |
| "取消代理/休假结束" | SOP-G 撤销代理(`DELETE /delegations/{id}`,本人可做) |

不匹配以上任何项 → 不臆测,向用户复述你的理解并问"是这个意思吗"。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
| "超过 X 小时自动通过/自动驳回" | SOP-G 超时处理(**§0.1 需确认** + `acknowledged`) |
| "我下周休假,审批转给小李" | SOP-G 代理人(`POST /delegations`,给自己设无需确认) |
| "看看谁设了代理/我的代理" | SOP-G 代理人列表(`GET /delegations?mine=1`) |
| "取消代理/休假结束" | SOP-G 撤销代理(`DELETE /delegations/{id}`,本人可做) |

不匹配以上任何项 → 不臆测,向用户复述你的理解并问"是这个意思吗"。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
- 浏览:`GET /templates/market`(`?mine=1` 只看自己发布的)。
- 安装:先 `GET /templates/market/{id}/preview` 看依赖 → `POST /templates/market/{id}/install {code_suffix?}`(只影响本租户,**无需确认**,但要把 warnings 如实转述给用户)。
  - 安装前若 `missing_form_codes` 非空,先提示用户;`user_bound_nodes>0` 说明审批人会被降级。
- 下架:`DELETE /templates/market/{id}` —— **仅发布者**可下架(非属主 404),软删除;**§0.1 需确认**(别人可能已安装该模板)。

**对市场的诚实说明**(用户问到时):当前是无审核的公共目录——任何租户管理员都能发布,无人审核内容;发布者只能下架自己的条目,平台没有全局管理员角色。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
- `user_id` 仅管理员可填(代他人设置);**给自己设代理不用填**,默认就是自己。
   - 时间格式 `YYYY-MM-DD HH:MM:SS`,`end_at` 必须晚于 `start_at`。
4. 复核:`GET /delegations`(管理员看全租户)或 `GET /delegations?mine=1`(只看自己)。响应带服务端算好的 `state`(`active`/`scheduled`/`expired`/`revoked`)与 `is_active_now`,**直接用它们向用户汇报状态,不要自己拿时间戳比**。
5. 撤销:`DELETE /delegations/{id}`(软删除)。**如实告知**:撤销只停掉**后续**新建任务的改派,**已经躺在代理人待办里的任务不会被收回**(一个人在办的事不该被抽走)。这时要提醒用户"这几条需要你自己去找代理人处理"。

**服务端会挡下的情况**(提前避开,别等报错):自己代理自己、`delegate_id`/`user_id` 不同租户、时间窗倒置、**同一被代理人已有生效期重叠的代理**。遇到重叠报错时,先 `GET /delegations` 看是哪一条在占用,让用户决定改时间还是先撤销旧的。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
- `user_id` 仅管理员可填(代他人设置);**给自己设代理不用填**,默认就是自己。
   - 时间格式 `YYYY-MM-DD HH:MM:SS`,`end_at` 必须晚于 `start_at`。
4. 复核:`GET /delegations`(管理员看全租户)或 `GET /delegations?mine=1`(只看自己)。响应带服务端算好的 `state`(`active`/`scheduled`/`expired`/`revoked`)与 `is_active_now`,**直接用它们向用户汇报状态,不要自己拿时间戳比**。
5. 撤销:`DELETE /delegations/{id}`(软删除)。**如实告知**:撤销只停掉**后续**新建任务的改派,**已经躺在代理人待办里的任务不会被收回**(一个人在办的事不该被抽走)。这时要提醒用户"这几条需要你自己去找代理人处理"。

**服务端会挡下的情况**(提前避开,别等报错):自己代理自己、`delegate_id`/`user_id` 不同租户、时间窗倒置、**同一被代理人已有生效期重叠的代理**。遇到重叠报错时,先 `GET /delegations` 看是哪一条在占用,让用户决定改时间还是先撤销旧的。

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill description is written as a Chinese-only operator experience and frames the agent as completing all operations through dialogue, but it does not offer any language or locale opt-in. Under the policy, forcing a specific language without user choice is a natural-language policy violation unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The README states that OAuth credentials are persisted in a local file (~/.gts-operator.json) with no accompanying warning about local secret exposure, file permissions, shared-machine risk, or secure storage expectations. For a skill that can perform high-impact administrative actions across tenants, quietly storing long-lived tokens locally increases the chance of credential theft and unauthorized API use if the endpoint or workstation is compromised.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
88% confidence
Finding

The skill supports automatic approval/rejection actions (Auto-approve / reject) that can change business workflow outcomes without a human acting at execution time. In this context—tenant admin, workflow, and approval operations—autonomous decisions are especially sensitive because they can authorize purchases, reject requests, or advance state based only on prior configuration and lazy triggers, leading to unintended or abusive approvals.

Content

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

md
- 字段权限(v2.2.0):隐藏字段双向不可见、发起人与管理员不受限、`required` 空值 400、写入过滤丢弃 hidden、跨租户 404、老流程无键回归。
- **超时 + 代理人(v2.3.0)**:Validator 行为探针 15/15(cc 节点拒绝、范围、必填、`acknowledged` 门禁);
  HTTP 冒烟 **38/38(连跑两次幂等)**——remind 不改状态、**once-only**(重复读只执行一次)、
  transfer 改派且原责任人保留、**转交目标失效时中止且不丢任务**、approve 跨节点自动推进 + `Auto-approve` 留痕、
  reject 关闭单据、代理人改派新任务 + `delegated_from_id`、跨租户代理不可见/不可改(404)/跨租户用户不可当代理人、
  自代理/时间窗倒置/重叠窗口全部拒绝、人工 `complete()` 与 `escalate()` 回归通过、`deadline_at` 现已写入。
  生产发布后已复验:路由上线、鉴权隔离正常、代理人 CRUD 全 200。

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The description says the user only needs to issue natural-language instructions and then lists broad phrases such as "开通租户", "AI 帮我搭表单", and "用对话完成 XX 配置/审批". These overlap with common workplace requests and do not define clear scope boundaries or negative examples, which could cause unintended invocation outside a narrowly defined GTS context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instructions require the agent to output the OAuth authorization prompt in Chinese or the user's language, and later explicitly require translation for Chinese users, reflecting a default locale policy embedded in the skill. Because the skill file is otherwise written as a general operator skill and does not consistently offer a user language choice up front, this can violate a language/locale policy when used with non-Chinese users.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
93% confidence
Finding

The skill supports configuring automatic approval or rejection on timeout, which allows the system to produce irreversible approval outcomes without human review. In an approval-platform skill, this is especially dangerous because it can silently authorize business actions or reject required work based only on elapsed time, and the lazy-trigger design may also obscure when the action actually executes.

Content

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

md
- 用户问"为什么超时了还没自动转交"→ 解释"要有人打开单据或列表才会触发;这是设计如此,不是故障"。
- 想让它立刻执行 → `POST /biz-data/{id}/escalate`,这就是手动触发通道。
- 同一任务**只会执行一次**(服务端用条件更新保证),重复读不会重复转交。不要为了"确保执行"反复调 escalate。
- `approve`/`reject` 自动执行后会在审批记录里留 `Auto-approve:` / `Auto-reject:` 开头的一行,且 actor 是**原处理人**——用户问"谁批的"时如实说明这是超时规则产生的机器判定,不是人点的。

#### G2 配置审批代理人("我下周休假,审批转给小李")