Security Audit
Published by ricardojpalves in solo-builder-security-audit
What this skill does
Use when you want a security and production-readiness report on a project — before launch, after adding auth/payments, or when something feels fragile. Covers IDOR, vertical privilege escalation, OAuth security, RLS, webhooks, secrets, exposed .git, rate limiting, race conditions, injection, SSTI, LFI, open redirects, file uploads, CSRF, security headers, cryptography, JWT attacks, log hygiene, supply chain, GraphQL, observability, business logic flaws, AI/LLM security (prompt injection, memory
Add Security Audit to your agent
Review the source and files first. When you are ready, copy the prompt instruction or use the CLI command supported by your environment.
Install with a prompt
Paste this into a compatible coding agent:
add this skill "security-audit" from https://github.com/ricardojpalves/solo-builder-security-auditInstall with the CLI
Run this command in a controlled environment after reviewing the repository:
npx skills add https://github.com/ricardojpalves/solo-builder-security-audit --skill security-auditSkill instructions
Security Audit
Run a full security and robustness audit on the current project. Produce a structured report.
Confidence levels — use these for every finding:
- HIGH — vulnerable pattern confirmed AND user-controlled input reaches it. Real risk.
- MEDIUM — pattern found but input source unclear or partially mitigated by framework.
- LOW — pattern exists but framework/library likely handles it (flag anyway, note why it's probably safe).
Framework awareness: Before flagging, check whether the framework already handles it. Examples: ORMs parameterise queries by default; React escapes JSX output; Next.js sanitises certain inputs. Don't flag false positives from built-in protections — note them as PASS with a brief reason.
Status for each item:
- ✅ PASS — confirmed safe
- ⚠️ NEEDS ATTENTION — present but incomplete or misconfigured
- ❌ FAIL — missing or broken
- N/A — not applicable
For every ⚠️ or ❌, name the exact file and line number (or where the fix should be added). Include confidence level.
1. Authorisation (not just authentication)
- Every API/route endpoint that returns user data has an ownership check — not just a login check. Example: does
GET /api/orders/:idverify the order belongs to the logged-in user? - Trace the data flow: does user-supplied ID reach the database query without an ownership check?
- Can a logged-in user access another user's records by changing an ID in the URL or request body? (horizontal privilege escalation / IDOR)
- Are resource IDs sequential integers (easy to enumerate)? Note: UUIDs alone don't fix this — ownership checks do.
- Vertical privilege escalation: Can a regular user reach admin-only endpoints or elevate their role by manipulating a request parameter, header, or JWT claim? Check every admin/internal route — is the role check server-side, or trusted from client-supplied data?
- OAuth security (if using Google/GitHub/social login): Is the
stateparameter generated, stored, and validated on every OAuth flow? Missing state = OAuth CSRF (attacker can link their account to victim's session). Are OAuth callback URLs validated against an allowlist? Is the scope requested limited to what's actually needed? - Account enumeration: Do login and password-reset endpoints return different error messages for "user not found" vs "wrong password"? Consistent error messages ("Invalid credentials") prevent attackers from building a list of valid accounts.
2. Supabase Row Level Security (if applicable)
- Is RLS enabled on all tables that contain user data?
- Do all RLS policies reference
auth.uid()— not justtrue? - List every RLS policy and flag any that grant broader access than intended.
3. Webhooks
- Are all webhook endpoints (Stripe or any provider) validating the incoming signature before processing?
- For Stripe: is
stripe.webhooks.constructEvent()called with the endpoint secret before any business logic? - Could a fake POST trigger a payment confirmation, subscription change, or data write?
4. Secrets & Credentials
- Are any API keys, secrets, or passwords hardcoded in source code?
- Are any secrets in frontend/client-side code visible in the browser?
- Is
.envin.gitignore? Check git history too — removed secrets may still exist in old commits. - Are environment variables validated at startup (fast fail if missing)?
- Exposed
.gitdirectory: Is the.gitfolder blocked from web access on the deployed server? If accessible at/.git/config, the entire source code history (including deleted secrets) can be downloaded. Check deployment config, nginx/Apache rules,.vercelignore, or equivalent. Bots scan for this continuously. - Cloud storage misconfiguration: Are any S3 buckets, GCS buckets, or equivalent cloud storage resources publicly accessible when they shouldn't be? Check bucket policies and ACLs — a single misconfigured bucket can expose all user-uploaded files.
5. Cryptography
- Are passwords hashed with a strong algorithm (bcrypt, argon2, scrypt)? Flag MD5, SHA1, or plain SHA256 for passwords as ❌ FAIL.
- Are JWTs verified with a strong secret (not a weak or default key)? Is the
algfield validated? The "none" algorithm attack — where an attacker setsalg: noneto bypass signature verification — is a real exploit in misconfigured JWT libraries. - Is sensitive data encrypted at rest where needed (PII, payment data)?
- Are any custom crypto implementations present? (Flag immediately — use established libraries only.)
- Is HTTPS enforced in production? Are there any HTTP endpoints or mixed content issues?
6. Rate Limiting
- Are AI-powered endpoints rate limited? (One bot or viral moment can generate hundreds of dollars in API costs in minutes.)
- Are auth endpoints rate limited? (Login, password reset, email verification are brute-force targets.)
- Is there a hard daily/monthly spending cap set on AI API usage?
7. Race Conditions in Billing & Limits
- Can a single-use coupon be redeemed more than once via parallel requests?
- Can plan limits be bypassed by sending simultaneous requests?
- Are billing-critical operations idempotent or protected by database-level locks?
8. Injection & XSS
Before flagging, check whether the ORM/framework already parameterises queries or escapes output by default.
- Is any SQL built by string concatenation (vs. parameterised queries or ORM)?
- Is user content ever rendered via
innerHTML,dangerouslySetInnerHTML, or equivalent without sanitisation? Trace whether the input is actually user-controlled. - Are user inputs validated and sanitised at the API layer (not just the frontend)?
- Are there any command injection risks (shell exec, child_process with user input)?
- SSRF: are there any server-side HTTP requests built from user-supplied URLs without validation?
- SSTI (Server-Side Template Injection): Is user input ever concatenated into a template string processed by a template engine (Jinja2, Handlebars, Twig, Pug, EJS)? If so, an attacker can inject template syntax and potentially achieve remote code execution. Check every place user data reaches a template renderer.
- LFI / Path Traversal: Is user-supplied input ever used to construct a file path for reading or including files? Without sanitisation,
?file=../../etc/passwdcan read arbitrary server files. Look forfs.readFile,include(),require(), or any file operation that takes user input. - Open redirects: Are there any endpoints that redirect users to a URL from a query parameter (e.g.
?returnTo=,?next=,?redirect=)? Without an allowlist, attackers use trusted domains as a launchpad for phishing. Especially common in OAuth callback handlers and post-login redirects. - File upload security: If users can upload files, is the file type validated server-side (not just by extension or MIME header, which can be spoofed)? Can a user upload an executable file (.php, .sh, .py) that gets served and executed? Are uploaded files stored outside the web root or with execution disabled?
9. CORS, CSRF & Security Headers
- Is CORS configured with a wildcard
*in production? - Are any admin or internal endpoints publicly accessible when they shouldn't be?
- Are there any debug routes, test endpoints, or scaffolding left accessible in production?
- CSRF: Are state-changing requests (POST/PUT/DELETE) protected against cross-site request forgery? Are cookies using
SameSite=StrictorSameSite=Lax? If using session cookies for auth, are CSRF tokens in use? - Cookie flags: Are session/auth cookies set with
httpOnly(not accessible to JS) andSecure(HTTPS only)? If JWTs are stored in localStorage instead of httpOnly cookies, flag as ⚠️. - CSP headers: Is a Content Security Policy header configured? Does it block inline scripts and restrict resource origins?
- Security headers completeness: Are the following headers present on all responses?
X-Frame-Options: DENYorSAMEORIGIN(prevents clickjacking — embedding your app invisibly in an iframe);X-Content-Type-Options: nosniff(prevents MIME-type sniffing attacks);Strict-Transport-Security(HSTS — forces HTTPS even if user types http://);Referrer-Policy(controls what URL is sent in the Referer header to third parties). These are free, one-line additions and missing from the majority of AI-built apps.
10. Production Config & Log Hygiene
- Is DEBUG mode or verbose error logging turned off in production?
- Are detailed error messages (stack traces, DB errors) being returned to the client?
- Are all production environment variables different from development values?
- Log hygiene: Are any logs writing PII (emails, names, addresses), payment data, or secrets? Logs are often less protected than databases — sensitive data in logs is a common overlooked exposure.
- Version disclosure via response headers: Are
Server,X-Powered-By,X-AspNet-Version,X-Generator, or similar headers returning software names and version numbers? These tell attackers exactly which CVEs to try. They should be suppressed or masked in production config (nginx, Express, Next.js headers config, etc.).
11. Supply Chain & Dependencies
Run these tools and include their output in the report:
npm audit --audit-level=high(orpip audit,bundle audit) — summarise critical and high CVEsnpx gitleaks detect --source .— thorough secret scanning including git historynpx semgrep --config=auto .— static analysis for common vulnerability patterns (if available)
Also check manually:
- Are there packages that haven't been updated in 2+ years with known vulnerabilities?
- Are dependencies pinned to exact versions in production (not loose ranges that could pull in malicious updates)?
- Are there any suspicious or typosquatted package names?
12. GraphQL Security (if applicable — skip if not using GraphQL)
- Is GraphQL introspection disabled in production? (Exposes your entire schema to attackers.)
- Is query depth limiting in place? (Deep nested queries can cause DoS.)
- Is query complexity limiting in place?
- Are batching attacks mitigated?
13. Email Deliverability (if using Supabase Auth or transactional email)
- Is the project using Supabase's default SMTP? (Flag as ⚠️ — switch to Resend or Postmark.)
- Are SPF, DKIM, and DMARC configured for the sending domain?
14. Observability & Access Logging
- Is an error monitoring tool (Sentry or equivalent) installed and configured?
- Will the team know when something breaks, or is the first signal an angry user?
- Are access patterns logged in a way that would detect active probing? Example: would you notice if a user hit
GET /api/orders/{id}50 times with different IDs in 2 minutes? If not, IDOR scanning would be invisible until damage is done.
16. AI/LLM Security (if the app uses AI — skip if not)
AI-powered features introduce attack surfaces that traditional security checklists don't cover.
- Prompt injection: Does user-supplied input reach your AI API calls without sanitisation? A user could type instructions that override your system prompt or manipulate the model's behaviour. Example: a support chatbot where the user message is passed directly into the prompt without boundaries.
- Sensitive data in AI calls: Is any PII, payment data, or internal business data being sent to third-party LLM providers (OpenAI, Anthropic, etc.) as part of prompts? Check what gets included in the context — conversation history, user records, documents.
- MCP server trust: If the app uses MCP servers, are they consuming external or user-controlled data? An attacker-controlled MCP response could inject instructions into the agent's tool calls.
- AI output rendered unsanitised: Is AI-generated content rendered directly as HTML? LLM output should be treated as untrusted — sanitise before rendering.
- Model API key exposure: Is the AI API key scoped appropriately? A leaked key isn't just a cost risk — it can be used to exfiltrate data from your system prompt.
- Excessive agency: Does the AI agent have more permissions and tool access than it actually needs? Apply least-privilege — an agent that only needs to read data shouldn't have write or delete capabilities. Every tool exposed to the agent is an attack surface if the agent is manipulated.
- Memory poisoning: If the app uses persistent AI memory (stored conversation history, user context, embeddings), can attacker-controlled inputs corrupt that memory to influence future responses? Check that memory inputs are treated as untrusted data.
- Retrieval abuse (RAG): If the app uses retrieval-augmented generation, can a user craft queries that retrieve documents belonging to other users, or that exfiltrate sensitive context through the retrieval mechanism? Apply the same ownership checks to retrieved documents as to any other user data.
- Resource exhaustion via AI: Can adversarial inputs trigger disproportionately expensive AI operations — long reasoning chains, recursive tool calls, or large context windows — that drain API budget or degrade service? Distinct from rate limiting: this is about input validation at the AI layer.
17. Mobile Security (if the app has a mobile client — skip if web-only)
Mobile apps have a different attack surface from web apps. Check the platform(s) in use.
All mobile (React Native, iOS, Android):
- Secure storage: Are auth tokens, API keys, or sensitive user data stored in
AsyncStorageor equivalent unencrypted storage? These are readable without root on some devices. Use Keychain (iOS) or Keystore (Android) via a library likereact-native-keychainorexpo-secure-store. - Sensitive data in logs: Are any tokens, PII, or API responses logged via
console.logor equivalent? On Android,logcatoutput is accessible to other apps in debug builds. Strip all sensitive logging before release. - Source maps in release builds: Are JavaScript source maps or debug symbols included in the production build? They expose your full source code to anyone who unpacks the binary.
- Biometric auth: If biometric auth is used, is it enforced server-side (the server validates a biometric-backed token) or just cosmetic (client-side gate that can be bypassed)?
- Certificate pinning: For high-sensitivity apps (finance, health), is certificate pinning in place to prevent MITM attacks on rooted/jailbroken devices?
iOS-specific:
- Are there
NSAllowsArbitraryLoadsorNSExceptionDomainsexceptions inInfo.plist? These disable App Transport Security and allow cleartext HTTP. - Is any sensitive data stored in
NSUserDefaults? It is not encrypted and is included in unencrypted device backups. - Are
WKWebViewinstances loading remote content? Check thatallowsInlineMediaPlaybackand JavaScript bridge exposure are intentional.
Android-specific:
- Are any
Activity,Service,BroadcastReceiver, orContentProvidercomponents exported inAndroidManifest.xmlwithout intent filters that justify it? Exported components are accessible to other apps on the device. - Is
android:debuggable="true"present in the release manifest? This allows arbitrary code execution viaadb. - Is
android:allowBackup="true"? On unencrypted Android backups, app data is accessible viaadb backup. - Is ProGuard/R8 obfuscation enabled for release builds?
React Native-specific:
- Is
__DEV__mode disabled in production? Dev mode enables the remote debugger, which can expose the JS runtime. - Is the Metro bundler accessible in production? It should never be reachable from a production build.
- Are any native modules exposed to JS that shouldn't be? Review the bridge surface for unintended capabilities.
18. Business Logic Vulnerabilities
Unlike technical vulnerabilities, business logic flaws come from the app not enforcing its own rules. AI agents build happy paths correctly but almost never consider adversarial use of the intended flow. No automated scanner catches these — they require tracing each monetised or gated feature manually.
For each paid feature, plan limit, or multi-step workflow, check:
- Paywall bypass: Can a free user reach a paid feature by calling the API endpoint directly, manipulating a subscription status parameter, or replaying a request without going through the payment flow?
- Workflow step skipping: In a multi-step process (onboarding, checkout, verification), can a user jump to step 3 without completing steps 1 and 2? Is the sequence enforced server-side, or does the server trust a client-supplied "current step" value?
- Plan limit bypass: Can usage limits (e.g. "5 exports/month") be reset or bypassed by deleting and re-creating an account, switching plans and back, or sending requests across multiple sessions simultaneously?
- Price/value manipulation: In any transaction where the client sends a price, quantity, or discount value — is that value re-validated server-side against the authoritative source? Never trust client-supplied pricing.
- Coupon and referral abuse: Can the same discount code or referral bonus be applied multiple times by the same user across different accounts, sessions, or email aliases?
- Free trial abuse: Can a user create unlimited free trial accounts? Is trial eligibility tied to email, payment method, device, or IP?
- Cancellation and refund flows: Does cancelling a subscription immediately revoke access, or is there a grace period that can be exploited? Can a user claim a refund while retaining access?
Flag each one as ✅ PASS / ⚠️ NEEDS ATTENTION / ❌ FAIL with the exact endpoint or code path where enforcement should happen.
15. Bug Chains (Compound Risks)
After completing the individual checks above, look for combinations of issues that chain into larger exploits. Individual bugs that look low-risk can become critical when stacked.
Examples to look for:
- Minor info leak + no rate limiting + sequential/predictable IDs = account takeover via IDOR scanning
- Weak auth token + no expiry + no access logging = silent long-term compromise
- CORS wildcard + missing ownership check + exposed admin endpoint = full data access from any origin
Flag any combination you find as a separate CHAIN RISK finding, even if the individual components were only ⚠️ on their own.
Output Format
Write the full report to a file named security-audit-[project-name]-[YYYY-MM-DD].md in the project root. Include every finding with file paths, line numbers, confidence levels, and fix guidance.
In the chat session, show only the summary:
Security Score: [X/10]
One line — sarcastic and fun. Calibrate the tone to the score. Examples:
- 9–10: "Honestly impressive. You might be the first vibe coder to not leave the front door open."
- 7–8: "Mostly solid. A few things that would make a pentester's eyes light up, but nothing embarrassing yet."
- 5–6: "It works! It also has some gaps that would make a security researcher mildly excited."
- 3–4: "Your app is a gift to the hacker community. They appreciate your generosity."
- 0–2: "Congratulations — you've built a public API for your users' data. Very generous of you."
Everything after the score is professional and direct.
CRITICAL (fix before launch)
All ❌ FAIL items — file + line + confidence level + one-line fix.
NEEDS ATTENTION
Count per category only (e.g. "3 items — see report"). No details in chat.
PASSED
One-line list of categories confirmed safe.
TOP 3 NEXT STEPS
The three highest-priority fixes, in order.
Then: Full report saved to security-audit-[project-name]-[YYYY-MM-DD].md
Files included
- CONTRIBUTING.md
- LICENSE
- README.md
- SKILL.md

