Back to skill

Security audit

Signet Guardian

Security checks for vulnerabilities and agentic risk

Overview

This payment-guard skill is not clearly malicious, but it needs review because it can permit payments by default and its spending-limit controls are not strong enough for a financial safety gate.

Review and change the policy before relying on this skill. Set paymentsEnabled to false until explicitly configured, require confirmation for all payments if unsure, avoid concurrent payment flows near the monthly cap, protect the ledger from local modification, and prefer pinned or locally installed tooling instead of unpinned npx commands.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/signet-cli.ts:263
Finding

Concurrent preflights can exceed the monthly payment cap before recording

Content
View full analysis
policy.maxPerMonth) { appendLedger({ ts: new Date().toISOString(), amount, currency, payee, purpose, status: 'denied', reason: `Would exceed monthly limit (${policy.currency} ${policy.maxPerMonth})`, ...audit, }); return { result: 'DENY', reason: `Would exceed monthly limit of ${policy.currency} ${policy.maxPerMonth} (already spent ${policy.currency} ${monthSpent.toFixed(2)} this month)`, }; } ``` The locked recording operation occurs only after the external payment is expected to have completed: ```ts async function record( amount: number, currency: string, payee: string, purpose: string, idempotencyKey?: string, callerSkill?: string ): Promise<{ ok: true } | { ok: false; error: string }> { return withLock(() => { const policy = loadPolicyFromConfigOrFile(); if (!policy) return { ok: false, error: 'Policy missing or invalid' }; if (currency !== policy.currency) { return { ok: false, error: `Policy currency is ${policy.currency}; request must use ${policy.currency}` }; } const monthSpent = getMonthSpent(policy.currency); if (monthSpent + amount > policy.maxPerMonth) { return { ok: false, error: `Would exceed monthly limit of ${policy.currency} ${policy.maxPerMonth} (already ${policy.currency} ${monthSpent.toFixed(2)} this month)`, }; } if (idempotencyKey && hasIdempotencyKey(idempotencyKey)) { return { ok: true }; // idempotent: already recorded } appendLedger({ ts: new Date().to ...[truncated 2102 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/signet-cli.ts:166
Finding

Malformed ledger entries are silently ignored, causing payment-limit checks to fail open

Content
View full analysis
{ try { const entry: LedgerEntry = JSON.parse(line); if ( entry.ts?.startsWith(monthKey) && entry.status === 'completed' && typeof entry.amount === 'number' && entry.currency === currency ) { return entry.amount; } } catch {} return 0; }) .reduce((sum, a) => sum + a, 0); } ``` ### Technical Analysis The ledger is security-critical state used to enforce the monthly cap. If a JSONL line cannot be parsed, the empty `catch` block suppresses the error and maps the entry to zero. Structurally invalid entries, entries with unexpected field types, and partially written lines are also excluded from the spending total. The implementation therefore treats an unreadable spending record as if no spending occurred. A security control should instead fail closed when the state needed to calculate authorization cannot be trusted. The ledger is not cryptographically authenticated. A local process or user that already has write access to the ledger can corrupt or modify completed entries so they are ignored by subsequent policy checks. Accidental filesystem corruption or interrupted writes can produce the same result without an attacker. ### Attack Path 1. A completed transaction exists in `references/ledger.jsonl`. 2. A local actor with write access modifies that line so it is invalid JSON, or changes a security-relevant field to an unexpected type. 3. `getMonthSpent()` catches the parsing error or rejects the field and returns zero for that line. 4. The calculated monthly expenditure becomes lower than th ...[truncated 794 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
references/policy.json:1
Finding

Bundled fallback policy enables payments without explicit first-run opt-in

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (31)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill claims to be a payment guard that returns ALLOW/DENY/CONFIRM_REQUIRED and enforces policy limits, but the analyzed file only documents that behavior and provides no executable enforcement. In a payment-control context, this mismatch is dangerous because dependent payment skills may trust the guard's contract and proceed as if policy checks, caps, and recording are being enforced when they are not.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The --edit path executes whatever program is named in the EDITOR environment variable via spawnSync. In agent or automation contexts, environment variables may be attacker-influenced, so invoking signet-policy --edit can become arbitrary local command execution under the agent's privileges.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
82% confidence
Finding

The documented policy edit, wizard, and migration flows imply persistent state changes to security-relevant payment controls, yet the README does not emphasize the persistence and downstream effect on future agent payment decisions. In the context of a middleware intended to gate payments, persistent configuration changes materially affect the trust boundary and can reduce protections across sessions if altered accidentally or by a misled operator.

Content

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

}

text

Create or edit with:

```bash
npx tsx scripts/signet-cli.ts signet-policy --edit

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes this skill as payment guard middleware that performs preflight policy checks and records successful payments. This file also exposes signet-report for spending reports and signet-policy for showing, editing, and migrating policy data, which expands the skill from guard middleware into policy-management and reporting functionality.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The script invokes npx -y tsx without pinning an exact package version, so execution depends on whatever version npm resolves at runtime. If a compromised or unexpected tsx version is fetched, arbitrary code could run in the context of this payment-related test workflow.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

This command again uses unpinned npx -y tsx, which can download and execute a non-deterministic package version at runtime. Because the script is exercising payment guard logic, compromise of the toolchain could falsify results or execute attacker-controlled code during validation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

An unpinned npx package execution introduces supply-chain risk by trusting the latest resolvable tsx package each time the script runs. In a security-sensitive skill related to payment authorization, even test scripts matter because developers may run them in trusted environments with credentials or local state.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The script performs another runtime execution of unversioned tsx through npx, allowing code from the package registry to influence local execution. This is particularly risky in payment-related tooling because it could tamper with preflight outcomes such as ALLOW, DENY, or CONFIRM_REQUIRED.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using npx -y tsx without version pinning exposes the script to registry or dependency compromise, enabling arbitrary code execution under the user's permissions. Since this invocation records a payment event, an attacker who controls the executed tool could alter transaction logs or exfiltrate data.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

This final use of npx -y tsx has the same supply-chain weakness: the package version is not fixed, so script behavior can change or become malicious without repository changes. In the context of a payment guard skill, that increases risk because operational reporting and validation outputs may be manipulated.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/signet-cli.ts:644