Back to skill

Security audit

PayPal

Security checks for vulnerabilities and agentic risk

Overview

This PayPal integration skill is documentation-only and mostly purpose-aligned, but it needs review because some payment examples could produce unsafe financial workflows if copied directly.

Review and strengthen generated code before using it in production. Require authenticated server-side authorization, transaction ownership checks, exact amount and currency validation, merchant validation, idempotency keys or atomic event claims, refund limits, and audit logging for all capture, subscription, webhook, dispute, and refund flows.

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

T09 · Insecure Skill Coding Practices

Error
Location
patterns.md:29
Finding

Incomplete Server-Side Order Validation Before Payment Capture

Content
View full analysis
{ const token = await getToken(); // First verify the order const order = await fetch(`https://api.paypal.com/v2/checkout/orders/${orderId}`, { headers: { 'Authorization': `Bearer ${token}` } }).then(r => r.json()); if (order.status !== 'APPROVED') { throw new Error(`Invalid order status: ${order.status}`); } // Then capture const capture = await fetch(`https://api.paypal.com/v2/checkout/orders/${orderId}/capture`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); return capture.json(); }; ``` ### Technical Analysis The capture function accepts an `orderId` that the documented frontend submits to the server. Before capture, the server retrieves the selected PayPal order but validates only that its status is `APPROVED`. The function does not verify that: - The order belongs to the authenticated application user or current checkout. - The PayPal order is linked to the expected internal order. - The amount equals the server-side expected amount. - The currency equals the expected currency. - The payee merchant ID is the intended merchant. - The order intent and purchase units match the expected transaction. This omission is especially significant because `SKILL.md` lines 74–84 explicitly state that amount, currency, and merchant must be checked before fulfillment. The operational capture pattern does not implement those checks. ### Attack Path 1. An attacker starts or identifies a lower-value PayPal order available through the same integration. 2. The attacker approves that lower-value order through PayPal. 3. During a higher-value application checkout, the attacker sends the approved lower-value ...[truncated 1085 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
webhooks.md:31
Finding

Webhook Idempotency Race Allows Duplicate Side Effects

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (16)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

javascript
// Token expires ~8 hours — handle refresh
const getToken = async () => {
  const res = await fetch('https://api.paypal.com/v1/oauth2/token', {
    method: 'POST',
    headers: {
      'Authorization': `Basic ${Buffer.from(`${clientId}:${secret}`).toString('base64')}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

PayPal webhooks MUST be verified via API call — not simple HMAC:

javascript
// POST /v1/notifications/verify-webhook-signature
const verification = await fetch('https://api.paypal.com/v1/notifications/verify-webhook-signature', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · patterns.md (reported line 8)May include surrounding context.

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · patterns.md (reported line 33)May include surrounding context.

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · patterns.md (reported line 83)May include surrounding context.

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · patterns.md (reported line 8)May include surrounding context.

javascript
const createOrder = async (amount, currency = 'USD') => {
  const token = await getToken();
  const res = await fetch('https://api.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The examples show payment capture, subscription creation, and refund operations without emphasizing that these are financially sensitive, potentially irreversible actions that require explicit user authorization and server-side access control. In an agent skill context, omission of such warnings can encourage unsafe reuse where destructive financial actions are exposed without confirmation or role checks.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · patterns.md (reported line 83)May include surrounding context.

javascript
// Create product first
const product = await fetch('https://api.paypal.com/v1/catalogs/products', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
}).then(r => r.json());

// Then create plan
const plan = await fetch('https://api.paypal.com/v1/billing/plans', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({

External Transmission

Medium
Category
Data Exfiltration
Confidence
68% confidence
Finding

While sending a refund request to PayPal is expected in a payment system, the example documents a refund primitive with no visible authorization, approval workflow, or business-rule validation. In an agent skill context, this can normalize exposing refund capability as a simple callable action, which could lead to unauthorized financial reversals if copied into production without strong controls.

Content

Scanner excerpt · patterns.md (reported line 121)May include surrounding context.

md
const token = await getToken();
  const body = amount ? { amount: { value: amount, currency_code: 'USD' } } : {};
  
  return fetch(`https://api.paypal.com/v2/payments/captures/${captureId}/refund`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
    body: JSON.stringify(body)

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes checkout flows, subscriptions, webhook verification, OAuth handling, and security validation. This file also documents a refund capability, which is a distinct payment operation beyond the stated scope and is not implied by the listed features.

Content

No source excerpt is available for this finding.