| name | perkcord-security-inspection |
| description | Defensive security inspection workflow for Perkcord auth, payment, Convex, Discord, and deployment boundaries. |
| compatibility | opencode |
| metadata | {"audience":"maintainers","repo":"perkcord","domain":"security"} |
Perkcord Security Inspection Skill
Purpose
Run repeatable defensive security inspections for Perkcord without leaking sensitive findings into public logs, issues, pull requests, or artifacts.
When To Use
- The user asks for a vulnerability inspection, security review, or pre-launch security pass.
- A change touches auth, sessions, payment providers, webhooks, entitlements, Discord role projection, provider credentials, or tenant isolation.
- A scheduled/private runner needs a standard playbook for security triage.
- A security finding needs classification into public issue, private advisory, or human triage.
Disclosure Guardrails
- Treat auth, payment, entitlement, provider credential, OAuth token, Discord role, webhook, and tenant isolation findings as private by default.
- Do not put exploit detail in public GitHub issues, PR descriptions, public Actions logs, public artifacts, or public comments.
- Use public GitHub issues only for sanitized hardening work that does not reveal a bypass or sensitive route/function.
- Use GitHub Security Advisories for confirmed security-sensitive findings. Do not request a CVE unless explicitly asked.
- If running in a public GitHub Actions context, print only sanitized pass/fail summaries.
- Do not run live probes against production or preview targets without explicit target authorization from the user.
Required Context
- Read
AGENTS.md and AGENTS.local.md when present.
- Identify whether the task is code inspection only, local dynamic testing, or authorized live testing.
- Confirm the correct deployment lane before any live investigation; default production lane is the active white-label/client lane from local agent context.
- Check whether related private advisories, public issues, or open PRs already exist before filing new tracking items.
Inspection Mindset
Start broad, then narrow. The examples in this skill are known Perkcord risk patterns, not a complete checklist. Before using them, map the current codebase shape and look for new trust boundaries, new runtimes, new provider flows, new queues, or new external integrations that are not named here.
For each boundary, ask:
- Who is allowed to call this?
- What tenant or guild is this scoped to?
- What data crosses this boundary?
- Can a browser, public Convex client, bot, provider, or internal service reach it directly?
- Does failure block safely, retry safely, or accidentally grant access?
Known Risk Patterns
Use these as prompts, not limits:
- Public Convex functions that perform server-only work.
- Shared service credentials that authorize unrelated REST capabilities.
- Secret-bearing data returned across HTTP or client-visible boundaries.
- Webhook data paths that can bypass signature verification or replay controls.
- Checkout or entitlement flows that trust browser-provided provider/tier state.
- Discord role projection and queue-worker calls that rely on caller-supplied actor fields.
- Cookie-authenticated mutations without same-origin or CSRF protection.
- Logs, audit events, outbound webhooks, or persisted errors containing raw provider/OAuth/Discord details.
- Recovery or lookup flows whose immediate responses reveal account or subscription existence.
Finding Classification
Classify each finding before filing or discussing it publicly.
Private Advisory
Use for:
- Auth bypass or authorization boundary failures.
- Entitlement escalation or Discord role projection compromise.
- Payment/webhook integrity issues.
- Plaintext provider credential exposure.
- OAuth token, Discord token, or encrypted token material exposure.
- Tenant isolation failures.
- Public access to server-only Convex functions.
- Concrete bypass mechanics for checkout or member access policy.
Severity scale for private findings:
- Critical: likely direct entitlement, payment, credential, token, or tenant compromise.
- High: strong access-control or data-exposure risk with credible abuse path.
- Medium: security-relevant hardening or conditional exposure that should be fixed before launch.
- Low: defense-in-depth, hygiene, or low-impact disclosure risk.
Public-Safe Issue
Use for sanitized work such as:
- Generic CSRF/same-origin hardening.
- Generic reliability or idempotency hardening.
- Dependency, secret-scan, or CI hygiene.
- Test coverage gaps when the issue body avoids exploit details.
- Launch-gate checklists that do not name vulnerable functions/routes.
Needs Human Triage
Use for:
- Plausible but unverified findings.
- Architecture concerns with unclear exploitability.
- Findings that require credentials, live traffic, provider access, or product judgement.
- Cases where remediation complexity may outweigh risk and needs an owner decision.
Inspection Workflow
- Read the repo instructions and local context.
- Map current entry points and runtimes before checking known risk patterns.
- Identify trust boundaries and data flows: browser, Convex public functions, Convex internal functions, REST, provider webhooks, bot worker, scheduled jobs, and external services.
- Explore for new surfaces not named in this skill.
- Verify suspected critical/high findings directly in code before filing them.
- Classify each finding before creating public or private tracking.
Boundary Checks
Convex
- Search for public
query(, mutation(, and action( exports under convex/convex.
- Review functions accepting
actorType, actorId, guildId, provider IDs, Discord IDs, tokens, credential-like data, or queue IDs.
- Ask whether each public function is safe for an arbitrary Convex client to call.
- Prefer
internalQuery, internalMutation, and internalAction for service-only workers, webhook processors, queue claim/complete functions, and audit/diagnostic writes.
- Check returned documents for
oauth, encrypted secrets, provider credentials, PII, and raw payloads.
REST
- Review
convex/convex/http.ts and convex/convex/restApi/** route registration and auth helpers.
- Identify routes that use a global shared API key and accept caller-provided
guildId.
- Check whether sensitive routes have capability-specific or tenant-scoped authorization.
- Check responses for secret-bearing fields such as provider secret keys, webhook secrets, transaction keys, API keys, OAuth tokens, or encrypted token blobs.
Webhooks And Payments
- Verify raw-body signature validation happens before JSON parsing or provider event recording.
- Verify webhook replay/idempotency keys are scoped sufficiently for the provider and tenant model.
- Trace normalized provider events into entitlement grant creation/update.
- Check browser-provided checkout fields against server-owned tier/provider configuration.
- Check fail-open behavior around provider, Discord, or credential lookup failures.
Web App Auth And Sessions
- Verify OAuth state cookies are random, checked, and cleared.
- Verify return paths reject absolute and scheme-relative redirects.
- Verify session cookies are signed, expiry-bound,
httpOnly, and secure in production.
- Review cookie-authenticated POST routes for same-origin or CSRF protection.
- Avoid direct
request.json() casts; use schema-backed contracts where practical.
Discord
- Review bot and Convex queue-worker functions for real service authentication.
- Check role sync idempotency and safe retry behavior.
- Check role hierarchy and managed-role diagnostics.
- Ensure role and Role Connections updates do not trust caller-supplied
actorType as authorization.
Logging And Data Leakage
- Search for raw
console.error(error), persisted lastError, audit payloads, and outbound webhook payloads.
- Prefer stable categories/codes over raw provider/OAuth/Discord exception strings.
- Do not log secrets, OAuth tokens, full webhook bodies, provider credential payloads, or PII-heavy request data.
Command Guidance
- Run
npm run security:audit when dependency exposure is in scope.
- Check for local
.env* presence, but do not read secret files unless the user explicitly authorizes it.
- If a requested scanner is unavailable locally, report that instead of inventing results.
- For GitHub tracking, use private security advisories for private findings and normal issues only for public-safe items.
Verification Standards
- Independently verify critical and high findings directly in code before filing them.
- Include file and line evidence in private advisory bodies.
- Confirm whether an issue is a true vulnerability, reliability hardening, or uncertain architecture risk.
- Prefer tests that prove a public client cannot invoke server-only behavior.
- For payment/webhook findings, verify both the intended signed path and the unintended bypass path.
- For UI or frontend-affecting security changes, follow the repo UI visual protocol if visuals change.
Tracking Workflow
Confirmed Private Findings
- Create a private draft GitHub Security Advisory.
- Do not request a CVE unless explicitly asked.
- Include summary, impact, confirmed evidence, recommended remediation, and validation checklist.
- Keep proof-of-concept payloads out unless they are necessary for remediation.
- If a PR is created from or for an advisory, keep public wording generic and avoid exploit detail.
Public-Safe Findings
- Create or update a normal GitHub issue.
- Use sanitized wording.
- Avoid vulnerable function names, route names, or bypass mechanics when those details would help exploitation.
- Keep acceptance criteria focused on safe outcomes and tests.
Uncertain Findings
- Report privately to the user with evidence and uncertainty.
- Ask for the minimum decision/access/scope needed to proceed.
- Do not file public tracking until classification is clear.
Scheduled Runner Guidance
Public GitHub Actions
Use only for sanitized gates:
- dependency audit
- secret scanning with normal masking
- allowlist-based boundary checks that print only generic failure text
- tests that fail with safe messages
Do not print:
- vulnerable function or route names
- exploit paths or payload examples
- advisory body drafts
- secrets, token material, provider IDs tied to real tenants, or PII
Safe failure style:
Security boundary check failed. Review private security triage output.
Private Runner
A private runner can run full inspection when logs and artifacts are restricted. It may:
- create private draft advisories
- create private triage reports
- create public issues only for sanitized hardening work
- request human triage for uncertain results
Default scheduled behavior should be human-in-the-loop: do not auto-file public issues for security-sensitive findings.
Private advisory creation should also be gated by human review unless the user has explicitly approved automatic draft advisory creation for confirmed, code-verified findings in that runner.
Output Templates
Finding
## Finding
Severity: Critical | High | Medium | Low
Classification: private-advisory | public-safe-issue | needs-human-triage
Area:
Evidence:
Impact:
Recommended remediation:
Verification:
Tracking recommendation:
Public-Safe Issue Body
## Summary
Track non-sensitive hardening work.
## Scope
- <generic hardening item>
- <test expectation>
## Acceptance Criteria
- <safe expected outcome>
Private Advisory Body
## Summary
<what is wrong, without unnecessary exploit payloads>
## Impact
<what an unauthorized or unintended actor could affect>
## Confirmed Evidence
- `<file>:<line>` <evidence>
## Recommended Remediation
- <smallest safe fix>
## Validation Checklist
- <tests/checks proving remediation>
Post-Run Checklist
After using this skill:
- Critical/high findings were verified directly before filing.
- Findings were classified before any public tracking was created.
- Public issues contain only sanitized hardening language.
- Private advisories include enough evidence and remediation detail for implementation.
- No live probing occurred without explicit authorization.