Back to skill

Security audit

Enable Stripe Payments Within Your Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed Stripe payment-gate demo, but its payment entitlement can be forged, reused, or granted from unrelated Stripe sessions.

Review before installing or using this as more than a demo. It should not be relied on for production paid access until entitlement is validated server-side or with signed, user-bound, product-bound receipts, exact Stripe product/session checks, protected local storage, expiry/revocation handling, and pinned dependencies.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/check_payment.py:43
Finding

Forgeable Local Receipt Allows Payment-Gate Bypass

Content
View full analysis
None: payload = { "email": email, "session_id": session_id, "ts": int(time.time()), "checksum": hashlib.sha256(f"{email}:{session_id}".encode()).hexdigest(), } RECEIPT_PATH.write_text(json.dumps(payload)) def _read_receipt() -> dict | None: if not RECEIPT_PATH.exists(): return None try: data = json.loads(RECEIPT_PATH.read_text()) expected = hashlib.sha256( f"{data['email']}:{data['session_id']}".encode() ).hexdigest() if data.get("checksum") == expected: return data except (json.JSONDecodeError, KeyError, TypeError): pass return None ``` ```python def check_payment_status() -> bool: """True if a valid local receipt exists.""" return _read_receipt() is not None ``` ### Technical Analysis The receipt checksum is a plain SHA-256 digest whose complete input—`email` and `session_id`—is stored in the same attacker-editable file. It contains no server-held secret and therefore provides no authenticity guarantee. Any local actor able to create or modify `~/.skill-payment-demo-receipt` can calculate a matching checksum. `check_payment_status()` accepts that receipt without querying Stripe or validating the session identifier, payment state, product, or user. ### Attack Path 1. Select an arbitrary email and arbitrary session identifier. 2. Calculate `SHA256(":")`. 3. Create `~/.skill-payment-demo-receipt` containing those values and the calculated checksum. 4. Invoke the Skill or call `check_payment_status()`. 5. `_read_receipt()` recomputes the attacker-known digest and accepts the forged receipt. 6. The Skill considers payment ...[truncated 357 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/check_payment.py:27
Finding

Host-Global Receipt Causes Cross-User Entitlement Sharing

Content
View full analysis
None: payload = { "email": email, "session_id": session_id, "ts": int(time.time()), "checksum": hashlib.sha256(f"{email}:{session_id}".encode()).hexdigest(), } RECEIPT_PATH.write_text(json.dumps(payload)) ``` ```python def check_payment_status() -> bool: """True if a valid local receipt exists.""" return _read_receipt() is not None ``` ### Technical Analysis The Skill stores exactly one receipt at a fixed path derived from the operating-system account’s home directory. The authorization check asks only whether any checksum-valid receipt exists. It does not compare the receipt’s email to the current requester or bind the entitlement to an authenticated user, tenant, product, or invocation. In environments where multiple Agent users share one service account, a receipt generated for one customer becomes a global entitlement for every customer using that runtime. ### Attack Path 1. User A completes payment and invokes `complete_payment_verification()`. 2. The Skill writes User A’s receipt to the fixed home-directory path. 3. User B later accesses the Skill through the same Agent host and OS account. 4. `check_payment_status()` finds User A’s receipt. 5. Because no current-user comparison occurs, User B is granted premium access. The same path can also be exploited by planting the forgeable receipt described in the preceding finding. ### Impact Assessment One paying user can unintentionally unlock protected behavior for all unrelated users sharing the process account. The scope includes every tenant and session relying on this single rece ...[truncated 143 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/check_payment.py:82
Finding

Stripe Verification Accepts Unrelated or Insufficiently Validated Checkout Sessions

Content
View full analysis
= MIN_AMOUNT_CENTS: return session return None ``` ### Technical Analysis The code searches all completed Checkout Sessions accessible through the configured Stripe account and accepts a session based only on customer email and a minimum total amount. It does not verify: - `payment_status == "paid"`; - the expected Payment Link; - the expected product or price ID; - currency; - Checkout mode; - Skill-specific metadata; - the intended connected account or tenant; or - a session identifier returned from the checkout initiated for this Skill. A Checkout Session’s `status` being `complete` is not a sufficient substitute for validating that the expected payment is paid and belongs to the intended product. Scanning the entire account history also permits an unrelated qualifying purchase under the same email to satisfy this Skill’s gate. ### Attack Path 1. Use an email associated with any completed Checkout Session in the configured Stripe account. 2. Ensure that the unrelated session has an `amount_total` of at least `MIN_AMOUNT_CENTS`. 3. Submit that email to `complete_payment_verification()`. 4. The code scans account-wide sessions and finds the unrelated transaction. 5. Because email and amount match, the session is accepted without product or payment-status validation. 6. A local receipt is written, granting continued ...[truncated 437 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Stripe Dependency Is Not Pinned to a Reviewed Version

Content
View full analysis
=7.0.0 ``` ### Technical Analysis The lower-bound constraint allows installation of any current or future Stripe SDK release satisfying the requirement. It is not an exact version pin, despite documentation describing the dependency as pinned. No lock file or package hash is provided. As a result, identical source code can install different dependency versions over time. Future compromised, malicious, or incompatible releases would be selected automatically during a fresh installation. ### Attack Path 1. A future Stripe package release satisfies `>=7.0.0`. 2. That release is compromised, malicious, or introduces an exploitable regression. 3. A deployment runs `pip install -r requirements.txt`. 4. Package resolution automatically selects the newer release. 5. The dependency executes within the Skill’s Python environment and receives the same process privileges, including potential access to `STRIPE_SECRET_KEY`. No evidence shows that the current Stripe package is malicious; this finding concerns unsafe dependency resolution. ### Impact Assessment A compromised dependency could execute code with the privileges of the Skill runtime and potentially access environment secrets, local files, network resources, and Stripe API capabilities. A merely incompatible update could also break payment verification or alter security-sensitive API behavior. ]]>
Remediation
View remediation
`. - Generate a lock file containing hashes for the package and transitive dependencies. - Install with hash verification in production. - Use automated vulnerability monitoring while applying dependency updates through reviewed pull requests. - Test payment and webhook behavior before promoting version changes. - Update documentation so it does not describe a lower-bound requirement as a pinned dependency. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/check_payment.py:43
Finding

Customer Identifiers Are Written to Disk Without Explicit File Protection

Content
View full analysis
None: payload = { "email": email, "session_id": session_id, "ts": int(time.time()), "checksum": hashlib.sha256(f"{email}:{session_id}".encode()).hexdigest(), } RECEIPT_PATH.write_text(json.dumps(payload)) ``` ### Technical Analysis The receipt stores the customer’s email address and Stripe Checkout Session identifier in plaintext. `Path.write_text()` creates the file using permissions influenced by the process umask; the implementation does not explicitly enforce owner-only access. The write is also non-atomic, so process interruption can leave a truncated authorization record. Although a Checkout Session ID is not equivalent to a Stripe secret key, it is a payment-related identifier and should not be exposed unnecessarily. The email address is personally identifiable information. ### Attack Path 1. The Skill successfully verifies a payment. 2. `_write_receipt()` writes the email and session ID to the home-directory file. 3. Another local process, user, backup system, or support workflow gains access where runtime permissions or operational controls expose the file. 4. The customer identifier and payment-session reference are disclosed. ### Impact Assessment The issue can disclose customer PII and payment-related metadata to actors with local or backup access. It does not directly disclose `STRIPE_SECRET_KEY` or payment-card details. Non-atomic writes may additionally cause denial of entitlement until payment is verified again. ]]>
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- This `SKILL.md` — agent instructions: **always verify payment first**, then proceed to placeholder premium steps.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- This `SKILL.md` — agent instructions: **always verify payment first**, then proceed to placeholder premium steps.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs use of environment variables, imports a script that reads secrets, and documents local receipt file reads/writes, but it does not declare any tool or permission scope in the skill metadata. That mismatch can cause the host or reviewer to underestimate the skill’s real capabilities, increasing the risk of unintended secret access or filesystem persistence when the skill is enabled.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

Do not run premium logic

text

If verification fails, do not proceed. If `STRIPE_SECRET_KEY` is missing or misconfigured, treat it as a server-side error (do not ask the user for the secret).

---

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · evals/evals.json (reported line 7)May include surrounding context.

json
{
      "id": 1,
      "prompt": "I want to use the premium part of the in-skill-stripe-payments-demo skill.",
      "expected_output": "Runs the payment gate first (check_payment_status / get_payment_link / complete_payment_verification); does not claim premium access without verification.",
      "files": ["scripts/check_payment.py", "SKILL.md"]
    },
    {

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The payment gate relies on a local receipt stored at a predictable path in the user's home directory, and the integrity check is only an unhashed deterministic checksum of public fields (email and session_id) with no secret or server-side validation. An attacker with local access can forge or replay a receipt file and cause check_payment_status() to unlock premium behavior without proving payment, making the authorization decision client-side and bypassable.

Content

Scanner excerpt · scripts/check_payment.py (reported line 20)May include surrounding context.

python
2. If not: get_payment_link() — show checkout URL.
  3. User pays, then provides checkout email.
  4. complete_payment_verification(email) — list completed Checkout Sessions,
     match email, require minimum amount, write receipt.

Receipt file: ~/.skill-payment-demo-receipt (JSON + checksum).
"""

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency specification uses a lower-bound only version constraint (stripe>=7.0.0), which allows installation of any future major or minor release. This weakens build reproducibility and can unexpectedly pull in vulnerable or breaking versions, which is especially relevant in a payment-processing skill where dependency behavior affects security-sensitive checkout and verification flows.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
stripe>=7.0.0

Static analysis

No suspicious patterns detected.