Skip to content

Security Scanning

Every agent plugin on PIE undergoes automated security analysis. This page explains how the system works, what it checks, and how to ensure your plugin passes.

How It Works

When you create, update, or import a plugin, PIE automatically runs a security scan using an AI-powered code analysis system (Claude Opus 4.6 via OpenRouter). The scan evaluates your plugin code and manifest against a set of security criteria.

Each scan produces:

  • Pass/Fail result for each of the 10 security criteria
  • An overall pass/fail status (all criteria must pass for an overall pass)
  • A summary with a brief explanation of the findings

When Scans Run

Scans are triggered automatically in these situations:

TriggerWhen
Plugin createdWhen a new plugin with code or a prompt template is created
Plugin updatedWhen code, prompt template, or manifest changes
Plugin importedWhen a .pie file is imported via the Developer Portal
Manual triggerWhen a developer clicks "Run Scan" in the Security tab

Auto-triggered scans use code hashing (SHA-256) to avoid redundant scans -- if the code hasn't changed since the last scan, the scan is skipped.

Security Criteria

Your plugin is evaluated against these 10 criteria:

1. No Data Exfiltration

Code must not send user data, conversation content, or secrets to unauthorized external endpoints. Your plugin should only communicate with APIs relevant to its stated purpose.

2. No Credential Harvesting

Code must not capture, log, or exfiltrate API keys, tokens, passwords, or secrets. Using context.secrets for your plugin's own API keys is perfectly fine.

3. No Filesystem Abuse

Code must not attempt to access, read, or write files outside its sandbox scope. Path traversal patterns and attempts to access system files will be flagged.

4. No Code Injection

Code must not use eval(), new Function(), or other dynamic code execution with untrusted input. Safe uses of JSON.parse() are acceptable.

5. No Network Abuse

Code must only make requests to hosts related to its stated purpose. A GitHub plugin calling the GitHub API is fine; a weather plugin calling an unknown endpoint is not.

6. No Crypto Mining / Resource Abuse

Code must not contain cryptocurrency mining, intentional infinite loops, or deliberate resource exhaustion patterns.

7. No Obfuscated Code

Code must be readable and not contain meaningfully obfuscated or encoded payloads designed to hide behavior. Base64-encoded config strings with clear purpose are acceptable.

8. No Privacy Violations

Code must not collect, store, or transmit PII beyond what is necessary for its stated function.

9. No Privilege Escalation

Code must not attempt to break out of its sandbox, access the host process, or escalate permissions.

10. Safe Dependencies

Any referenced external URLs or APIs must be legitimate, well-known services matching the plugin's stated purpose.

Viewing Results

Marketplace & Plugin Pages

Every plugin displays a security badge:

  • Verified (green) -- All criteria passed
  • Security Issues (red) -- One or more criteria failed
  • Scanning... (yellow) -- Scan in progress
  • Not Scanned (gray) -- No scan has been run yet

On the plugin detail page, you can expand the full security report to see individual criteria results with explanations.

Developer Portal

In the Developer Portal, the Security tab shows:

  • Current scan status and summary
  • Detailed breakdown of all 10 criteria with pass/fail indicators
  • Scan history showing previous scan results
  • A Run Scan button to manually trigger a new scan

Tips for Passing

  1. Only call APIs relevant to your plugin's purpose -- If your plugin is a weather tool, only call weather APIs
  2. Use context.secrets for credentials -- Never hardcode API keys or tokens
  3. Use context.oauth.fetch() for authenticated requests -- This is the approved way to make OAuth-authenticated calls
  4. Write readable code -- Avoid unnecessary string encoding or variable name obfuscation
  5. Declare network access in your manifest -- List the hosts your plugin needs to access
  6. Don't use eval() or new Function() -- Use standard JavaScript patterns instead

API Endpoints

MethodEndpointAuthDescription
GET/api/plugins/:id/securityNoGet latest scan result
POST/api/plugins/:id/security/scanYes (author)Manually trigger a scan
GET/api/plugins/:id/security/historyYes (author)Get scan history

Built with VitePress