Back to skill

Security audit

ortho-deal-match

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent local deal-matching tool, but it handles business contacts while relying on weak caller-supplied identities for consent, roles, blocking, and data changes.

Use this only in a trusted local/internal environment unless real authentication, object-level authorization, and stronger consent records are added. Do not rely on it to protect private business records or personal contact details in a shared workspace, and protect or back up the data, registry, blocklist, and audit files separately.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/core.py:305
Finding

Caller-Controlled User IDs Allow Account and Owner Impersonation

Content
View full analysis
timedelta(days=PLEDGE_DAYS): return False, ("The pledge has expired."), u limit = { "match": QUOTA_MATCH, "reveal": QUOTA_REVEAL, "publish": QUOTA_PUBLISH }.get(action) if limit is not None: used = used_today(uid, action) if used + need > limit: return False, ("The daily quota is insufficient."), u return True, "", u ``` The original source contains localized user-facing messages; they are translated above without changing the control flow. ### Technical Analysis Every security-sensitive command accepts a user identifier such as `U001` from the command line and treats possession of that identifier as proof of identity. There is no password, session credential, API token, cryptographic signature, operating-system account binding, or interactive identity verification. `is_owner()` grants owner privileges solely by looking up the caller-supplied identifier. Likewise, `check_access()` verifies only that the selected database record exists, has signed the pledge, and has quota remaining. It does not authenticate the process invoking the command. Consequently, knowing or guessing an owner identifier is sufficient to pass owner ch ...[truncated 1467 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/intro.py:108
Finding

Caller-Selected Match Side Bypasses Bilateral Consent and Exposes Contacts

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/publish.py:192
Finding

Missing Object-Level Authorization Allows Unauthorized Publication, Activation, Closure, and Private Record Listing

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/match.py:158
Finding

Explicit Match Inputs Bypass Private-Record Visibility and Match Ownership Controls

Content
View full analysis
c.party_id " "AND d.visibility='public' AND c.visibility='public'" )) elif a.demand: pairs = [(a.demand, r[0]) for r in con.execute( "SELECT id FROM capabilities WHERE status='open' " "AND (visibility='public' OR owner=?)", (a.user,) )] elif a.capability: pairs = [(r[0], a.capability) for r in con.execute( "SELECT id FROM demands WHERE status='open' " "AND (visibility='public' OR owner=?)", (a.user,) )] ``` ```python exist = con.execute( "SELECT * FROM matches WHERE demand_id=? AND capability_id=?", (did, cid) ).fetchone() if exist: out.append(exist) continue con.execute( "INSERT INTO matches " "(id,demand_id,capability_id,score,reason,status,created,updated) " "VALUES (?,?,?,?,?,?,?,?)", (mid, did, cid, s, reason, "suggested", now, now) ) out.append( con.execute("SELECT * FROM matches WHERE id=?", (mid,)).fetchone() ) ``` ```python if a.demand: d = con.execute( "SELECT * FROM demands WHERE id=?", (a.demand,) ).fetchone() if not d: return 1 ``` ### Technical Analysis The `--all` path correctly limits both sides to public records. However, the explicit `--demand` path does not validate the selected demand’s owner or visibility, and the explicit `--capability` path does not validate the selected capability’s owner or visibility. The code can therefore pair an attacker-selected private object with public records, create match rows involving another user’s private record, and immediately print match details. Existing matches are also re ...[truncated 1210 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/core.py:384
Finding

Unauthenticated Blocklist Administration Enables Global Denial of Service

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/core.py:76
Finding

Writable Unkeyed Audit Log Allows Quota Reset and Complete Audit-Chain Forgery

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/init_db.py:143
Finding

Any Local Caller Can Reset Active Data and Rebootstrap as Owner

Content
View full analysis
0: bak = os.path.join(archive, f"{os.path.basename(p)}.{stamp}") with open(fp, encoding="utf-8") as src, \ open(bak, "w", encoding="utf-8") as dst: dst.write(src.read()) open(fp, "w", encoding="utf-8").close() ``` The original localized display text has been translated or omitted without changing the relevant operations. ### Technical Analysis Database reset and demo reinitialization are administrative operations but have no authentication or role check. The `--reset` and `--yes` flags confirm intent only; they do not establish authority. Although the old database and JSONL files are backed up or archived, the active state is replaced. `demo.py` empties the active user registry and then registers a new first user, which automatically receives the owner role. Th ...[truncated 1177 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description presents a complete supply-demand matchmaking product, but this code chunk only covers a subset: admission control, quotas, role permissions, blocklist handling, audit chain, and helper functions for access checks and masking. Those parts do align with the declared safeguards, but the core advertised behavior—posting needs/capabilities, automated multi-factor matching, mutual-intent confirmation, and lead import—is absent from the supplied code. There is no evidence of unrelated malicious behavior, but there is a significant description-versus-code scope gap, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
86% confidence
Finding

这段代码与“骨科供需撮合台”领域相关,但实际作用明显更窄:它只是底层数据库建库与运维脚本,而非完整业务实现。代码没有实现核心业务行为,如五维评分撮合、联系方式交换控制、反骚扰/限速/拒访机制、权限系统、哈希链审计、展会名录导入等。虽然表结构为这些能力预留了一些字段,说明可能是该系统的一部分,但就本代码块本身而言,实际行为与声明描述的完整功能存在明显落差。因此应判定为描述与代码行为不完全一致,属于能力被显著高估的情况。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

声明描述的是一个较完整的骨科供需撮合台,核心能力包括需求/能力发布、自动五维评分撮合、实名登记、审计、配额与展会线索导入等。当前代码仅覆盖其中一部分:围绕已存在的 matches 执行 request/accept/decline/reveal/feedback/assign,对‘双方都确认后才交换联系方式’、拒访名单、权限分派、配额检查(reveal 时)和审计留痕有所实现。这与声明中的部分功能一致,但代码块的实际主功能明显更窄,属于“对接与联系方式交换”模块,而不是完整的撮合平台。尤其缺少自动撮合评分、发布需求/能力、实名登记、展会名录导入等声明中的关键能力,因此描述不能准确代表该代码块实际行为。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Blocklist modification is effectively unauthenticated: block and unblock accept a caller-supplied --by value defaulting to 'owner', but there is no authorization check that the actor is actually an owner or even a real user. An attacker can add legitimate companies to the refuse-contact list to suppress matches, or remove blocked entities, undermining both anti-harassment controls and business integrity.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The whoami command takes an arbitrary --user value and prints that user's full contact details, company, title, and purpose without verifying that the requester is the same user or an authorized owner. In a matchmaking platform whose stated purpose is to withhold contact information until mutual confirmation, this directly defeats the privacy and anti-harassment model.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The instruction says branding must uniformly use a specific Chinese name form and forbids other identity forms. This is a natural-language policy constraint that forces a specific locale/language presentation without offering opt-in, alternatives, or a documented region-specific justification.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises and demonstrates shell execution, local file/database writes, environment-variable use, and likely access to an external expo database path, but it does not declare any explicit tool scope or permissions. In an agent environment, this weakens least-privilege controls and can allow unintended invocation with broader capabilities than users or orchestrators expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases include broad business-language terms such as matchmaking, sourcing, lead generation, and connecting buyers and sellers, which can cause the skill to activate in contexts broader than intended. In a skill that handles contact exchange, lead import, and local data writes, accidental invocation increases the chance of privacy-impacting actions or inappropriate processing of commercial data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The workflow explicitly instructs the operator to reveal and pass counterparties’ contact information after both sides indicate interest, but it does not show any explicit consent language, privacy notice, data minimization, or user-facing warning about how personal contact data will be shared. In a B2B matchmaking system handling named individuals, emails, and cross-border parties, this can lead to unauthorized disclosure of personal data, privacy-law noncompliance, and misuse of contact details even if the business intent is legitimate.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation includes a destructive reset command followed by reseeding instructions without an explicit warning that the operation wipes existing data. In an operational or shared environment, a user could run it casually and destroy audit logs, match history, block lists, and registered party data, causing availability and integrity loss.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file’s natural-language interface is entirely in Chinese, including the module docstring, operational descriptions, and command usage guidance. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The module includes identity/role administration capabilities in the same skill that is supposed to support matchmaking workflow, increasing the attack surface around privilege management. In this code the first registrant is automatically made owner, so anyone who can initialize a fresh deployment or registry can gain broad visibility and administrative control without an independent trust bootstrap.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The audit command exposes raw audit entries to any caller without checking identity or role. Because audit details include user IDs, companies, purposes, and operational history, unrestricted access can leak sensitive relationship and activity data beyond what a normal matchmaking user should see.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring and invocation guidance are written only in Chinese, and the script continues with Chinese-only prompts and status messages elsewhere in the file. This imposes a specific language on users without any opt-in or documented locale constraint, which matches the language/locale policy violation criteria.

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/demo.py (reported line 23)May include surrounding context.

python
def run(args, quiet=True):
    r = subprocess.run([PY] + args, cwd=HERE, capture_output=True, text=True,
                       encoding="utf-8", errors="replace")
    if not quiet:
        print(r.stdout)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module docstring and command descriptions are entirely in Chinese, and the script continues this with Chinese-only argparse help and console output. This imposes a specific language on users without opt-in or an explicit statement that the tool is intended only for a Chinese-speaking or region-specific environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The argparse description, --reset help text, and printed status/warning messages are all Chinese-only. Under the policy, forcing a specific language without user choice or clear justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code file contains natural-language instructions, help text, and operational messages entirely in Chinese, and does not indicate that the skill is region-specific or provide any opt-in for another language. Under the policy, forcing a specific language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

cmd_list returns all demands and capabilities unless --mine is explicitly set, and includes associated party names and countries. In a marketplace that claims contact details are only exchanged after mutual interest, broad default enumeration of commercial records increases unauthorized visibility into participant identities and business activity, enabling scraping, profiling, and circumvention of the intended matchmaking/privacy model.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The activate flow converts expo-imported leads into active parties using operator-supplied contact details, making them eligible for matchmaking. In this skill’s context, that creates a pathway to onboard third-party organizations and personal contact data based only on user assertion, which can be abused for impersonation, unauthorized outreach, or privacy violations if consent and verification are weak.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code updates a party record with personal contact information including person, title, email, and phone, which is a safety-relevant data write involving personal data. Although the command enforces that contact details be provided, it does not disclose to the operator at the point of action that these details will be persisted to the database, and there is no surrounding comment or docstring on the write itself explaining this storage behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file’s natural-language documentation describes the module entirely in Chinese and the example normalized outputs are fixed to Chinese standard terms such as 「创伤」 and 「钛合金」. This indicates a language-specific behavior without any user opt-in or explicit justification that the skill is intentionally restricted to a Chinese-language workflow.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The entire skill-facing report is written in Chinese, and there is no indication that users may choose another language or that the skill is explicitly limited to a Chinese-speaking or region-specific context. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/core.py (reported line 167)May include surrounding context.

python
for key, label in (("name", "姓名"), ("company", "公司"),
                       ("title", "职务"), ("contact", "本人联系方式"),
                       ("purpose", "用途")):
        if not getattr(a, key, "").strip():
            print(f"  缺少必填项:{label}(--{key})")
            print("  撮合台的原则:对方要能找到你、回绝你、投诉你,所以联系方式不能省。")
            return 1

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The top-level docstring states that the script '会清空现有数据库与审计日志', implying audit logs are erased. However, the implementation later explicitly says '审计链归档而非清空' and copies existing audit files into an archive before truncating the originals, which preserves historical audit data rather than simply clearing it.

Content

No source excerpt is available for this finding.