AI App Security Scanner
ShipSafe
ShipSafe is the review step between 'the app runs' and 'the app is safe to deploy'. It scans AI-built codebases for leaked secrets, unsafe env usage, wildcard CORS, missing security headers, noisy production logs, and the auth-related issues that the free lite layer does not fully cover.
What it fixes
- Hardcoded API keys, tokens, and passwords left in source code.
- Missing .gitignore or .env.example hygiene before a repo gets pushed.
- Server secrets leaking into the browser through dangerous NEXT_PUBLIC_* variables.
- Wildcard CORS and missing security headers in shipping API routes.
- Production console.log noise and select('*') overfetching left behind by AI tooling.
- Auth and access-control bugs that do not show up in a simple secret scan.
What's inside
- The free lite scanner pattern for hardcoded secrets, config hygiene, wildcard CORS, console logging, and select('*') checks.
- A deeper paid review layer for auth logic, broken access control, and ownership verification.
- getSession() vs getUser() detection for Supabase-auth patterns that look correct but are not safe server-side.
- Supabase RLS policy analysis and SQL migration scanning.
- API handler authorization review plus npm audit integration.
- Auto-fix mode, baseline suppression, and a fuller category score breakdown.
- Reference guides such as auth-review.md and a fix-playbook for remediation.
Before / After
Without rules
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY!
)
export async function GET() {
return Response.json({ ok: true }, {
headers: { "Access-Control-Allow-Origin": "*" }
})
}
console.log(process.env.STRIPE_SECRET_KEY)With rules
import "server-only"
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)
const allowedOrigins = new Set(["https://0toprod.dev"])
export async function GET(request: Request) {
const origin = request.headers.get("origin") ?? ""
const response = Response.json({ ok: true })
if (allowedOrigins.has(origin)) {
response.headers.set("Access-Control-Allow-Origin", origin)
}
response.headers.set("X-Frame-Options", "DENY")
return response
}Free vs Full
The free repo is a useful first pass. The paid ShipSafe layer is where the more dangerous review work starts.
| Layer | Free GitHub Scanner | Full ShipSafe |
|---|---|---|
| Hardcoded secret detection | Included | Included |
| .env and .gitignore checks | Included | Included |
| NEXT_PUBLIC audit | Included | Included |
| CORS and security headers | Included | Included |
| console.log and select('*') | Included | Included |
| Auth logic review | Not included | Included |
| getSession() vs getUser() | Not included | Included |
| Supabase RLS policy analysis | Not included | Included |
| SQL migration scanning | Not included | Included |
| API handler authorization audit | Not included | Included |
| Broken access control detection | Not included | Included |
| Ownership verification | Not included | Included |
| npm audit integration | Not included | Included |
| Auto-fix mode | Not included | Included |
| Baseline suppression | Not included | Included |
| Score depth | Basic score | Full 3-layer score |
| Reference guides | Not included | Included |
Compatibility
ShipSafe is positioned as both a standalone scanner and a skill layer for AI coding environments.
| Platform | Format | Status |
|---|---|---|
| Claude Code | SKILL.md | Supported |
| OpenAI Codex CLI | SKILL.md | Supported |
| Windsurf | skills directory | Portable |
| Continue.dev | skills directory | Portable |
| Standalone CLI | scripts/scan_repo.py | Supported |