Skip to main content
Technology & EngineeringVibe Coding Security320 lines

Trust Misconfiguration Audit

Quick Summary33 lines
The most common vulnerability in AI-generated code isn't SQL injection or XSS — it's trust misconfiguration. Code that assumes everything is fine. Open CORS, admin-level service accounts, raw input passed to shell commands. The AI optimizes for "make it work" with zero weight on "make it survivable in production."

## Key Points

- **All origins** (CORS `*`)
- **All users** (no authentication on endpoints)
- **All input** (no validation or sanitization)
- **All environments** (hardcoded dev credentials used in prod)
- **All permissions** (service accounts with admin access)
- **All network traffic** (no TLS enforcement, no rate limiting)
1. Search the entire codebase for patterns: `password=`, `secret=`, `api_key=`, `token=`, `sk_live`, `sk_test`, `AKIA` (AWS), `ghp_` (GitHub)
2. Check `.gitignore` includes: `.env`, `.env.local`, `.env.production`, `*.pem`, `*.key`, `serviceAccountKey.json`
3. Check git history: `git log --all -p | grep -i "password\|secret\|api_key"` — credentials removed from code may still be in history
4. Check CI/CD configs for hardcoded secrets (use platform secret management instead)
- SQL queries (parameterize instead)
- Shell commands (use safe APIs instead of `exec`)

## Quick Example

```javascript
app.use(cors()); // Allow all origins
// or
app.use(cors({ origin: '*' }));
```

```json
{
  "serviceAccount": "my-app@project.iam.gserviceaccount.com",
  "roles": ["roles/owner"]
}
```
skilldb get vibe-coding-security-skills/trust-misconfiguration-auditFull skill: 320 lines
Paste into your CLAUDE.md or agent config

Trust Misconfiguration Audit

The most common vulnerability in AI-generated code isn't SQL injection or XSS — it's trust misconfiguration. Code that assumes everything is fine. Open CORS, admin-level service accounts, raw input passed to shell commands. The AI optimizes for "make it work" with zero weight on "make it survivable in production."

This skill teaches you to systematically find and fix these trust assumptions before they become incidents.

What Are Trust Misconfigurations?

Trust misconfigurations occur when code implicitly trusts:

  • All origins (CORS *)
  • All users (no authentication on endpoints)
  • All input (no validation or sanitization)
  • All environments (hardcoded dev credentials used in prod)
  • All permissions (service accounts with admin access)
  • All network traffic (no TLS enforcement, no rate limiting)

These aren't bugs in the traditional sense. The code works. Tests pass. It runs on your machine. The vulnerability is invisible until someone exploits it.

The Audit Checklist

1. CORS Configuration

What AI typically generates:

app.use(cors()); // Allow all origins
// or
app.use(cors({ origin: '*' }));

What production needs:

const allowedOrigins = [
  'https://yourdomain.com',
  'https://app.yourdomain.com',
];

app.use(cors({
  origin: (origin, callback) => {
    // Allow requests with no origin (mobile apps, curl, etc.)
    if (!origin) return callback(null, true);
    if (allowedOrigins.includes(origin)) {
      return callback(null, true);
    }
    return callback(new Error('CORS not allowed'), false);
  },
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
}));

Audit question: Does any CORS configuration use * or allow all origins? Does it allow credentials with wildcard origins (browser will block this, but misconfigured proxies won't)?

2. Service Account Permissions

What AI typically generates:

{
  "serviceAccount": "my-app@project.iam.gserviceaccount.com",
  "roles": ["roles/owner"]
}

What production needs:

{
  "serviceAccount": "my-app@project.iam.gserviceaccount.com",
  "roles": [
    "roles/cloudsql.client",
    "roles/storage.objectViewer"
  ]
}

Audit question: Does any service account, IAM role, or database user have more permissions than the minimum required for its specific function? Can you list exactly which permissions each service account uses?

3. Hardcoded Credentials

What AI typically generates:

DB_URL = "postgresql://admin:supersecret@db.example.com:5432/myapp"
API_KEY = "sk_live_abc123def456"
JWT_SECRET = "my-jwt-secret-key"

What production needs:

import os

DB_URL = os.environ["DATABASE_URL"]
API_KEY = os.environ["API_KEY"]
JWT_SECRET = os.environ["JWT_SECRET"]

# Validate they exist at startup
for var in ["DATABASE_URL", "API_KEY", "JWT_SECRET"]:
    if not os.environ.get(var):
        raise RuntimeError(f"Required environment variable {var} is not set")

Audit steps:

  1. Search the entire codebase for patterns: password=, secret=, api_key=, token=, sk_live, sk_test, AKIA (AWS), ghp_ (GitHub)
  2. Check .gitignore includes: .env, .env.local, .env.production, *.pem, *.key, serviceAccountKey.json
  3. Check git history: git log --all -p | grep -i "password\|secret\|api_key" — credentials removed from code may still be in history
  4. Check CI/CD configs for hardcoded secrets (use platform secret management instead)

4. Input Validation

What AI typically generates:

app.post('/search', (req, res) => {
  const query = req.body.query;
  const results = db.query(`SELECT * FROM products WHERE name LIKE '%${query}%'`);
  res.json(results);
});

What production needs:

import { z } from 'zod';

const searchSchema = z.object({
  query: z.string().min(1).max(200).trim(),
  page: z.number().int().min(1).max(100).default(1),
  limit: z.number().int().min(1).max(50).default(20),
});

app.post('/search', (req, res) => {
  const parsed = searchSchema.safeParse(req.body);
  if (!parsed.success) {
    return res.status(400).json({ error: 'Invalid input', details: parsed.error.issues });
  }

  const { query, page, limit } = parsed.data;
  const results = db.query(
    'SELECT * FROM products WHERE name LIKE $1 LIMIT $2 OFFSET $3',
    [`%${query}%`, limit, (page - 1) * limit]
  );
  res.json(results);
});

Audit question: Is any user input used directly in:

  • SQL queries (parameterize instead)
  • Shell commands (use safe APIs instead of exec)
  • File paths (validate and sandbox)
  • HTML output (escape or use a template engine)
  • URL redirects (whitelist allowed destinations)
  • Regular expressions (sanitize to prevent ReDoS)

5. Authentication & Authorization

What AI typically generates:

// "Protected" route that checks nothing
app.get('/api/admin/users', (req, res) => {
  const users = db.getAll('users');
  res.json(users);
});

What production needs:

function requireAuth(req, res, next) {
  const token = req.headers.authorization?.replace('Bearer ', '');
  if (!token) return res.status(401).json({ error: 'No token provided' });

  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET);
    req.user = payload;
    next();
  } catch {
    return res.status(401).json({ error: 'Invalid token' });
  }
}

function requireRole(role) {
  return (req, res, next) => {
    if (req.user.role !== role) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }
    next();
  };
}

app.get('/api/admin/users', requireAuth, requireRole('admin'), (req, res) => {
  const users = db.getAll('users');
  // Strip sensitive fields before returning
  const safe = users.map(({ password, ...rest }) => rest);
  res.json(safe);
});

Audit question: For every API endpoint, can you answer: Who can access this? What can they do? What data can they see? Is there middleware enforcing this, or is it just "assumed"?

6. Database Security

Common AI patterns to audit:

  • Connection strings with admin credentials
  • No connection pooling limits (DoS vector)
  • No query timeouts (slow query = locked connection)
  • Raw queries accepting user input
  • No row-level security or tenant isolation
  • Backups not encrypted or not configured

The fix:

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20,                    // Connection pool limit
  idleTimeoutMillis: 30000,   // Close idle connections
  connectionTimeoutMillis: 5000, // Fail fast on connection issues
  statement_timeout: 10000,    // Kill queries running > 10s
  ssl: process.env.NODE_ENV === 'production'
    ? { rejectUnauthorized: true }
    : false,
});

7. Environment Leakage

What AI typically generates:

// Returns full error stack to client
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message, stack: err.stack });
});

What production needs:

app.use((err, req, res, next) => {
  // Log full error internally
  console.error('Unhandled error:', err);

  // Return safe error to client
  res.status(500).json({
    error: process.env.NODE_ENV === 'production'
      ? 'Internal server error'
      : err.message
  });
});

Audit: Search for stack, err.message, console.log(req), JSON.stringify(process.env), debug endpoints left enabled, and any response that might leak internal paths, versions, or configuration.

Running the Audit

Quick Automated Scan

# Search for common trust misconfigurations
echo "=== Hardcoded Secrets ==="
grep -rn "password\s*=\s*['\"]" --include="*.{js,ts,py,go,java,rb}" .
grep -rn "api_key\s*=\s*['\"]" --include="*.{js,ts,py,go,java,rb}" .
grep -rn "secret\s*=\s*['\"]" --include="*.{js,ts,py,go,java,rb}" .
grep -rn "sk_live\|sk_test\|AKIA\|ghp_\|gho_" .

echo "=== Open CORS ==="
grep -rn "cors()\|origin:\s*['\"\`]\*" --include="*.{js,ts}" .

echo "=== Shell Injection Vectors ==="
grep -rn "exec(\|execSync(\|spawn(" --include="*.{js,ts}" .
grep -rn "os\.system\|subprocess\.call\|subprocess\.run" --include="*.py" .

echo "=== Missing .gitignore entries ==="
for f in .env .env.local .env.production serviceAccountKey.json; do
  grep -q "$f" .gitignore 2>/dev/null || echo "MISSING from .gitignore: $f"
done

echo "=== Admin/Owner Permissions ==="
grep -rn "roles/owner\|roles/editor\|AdministratorAccess\|root" --include="*.{json,yaml,yml,tf}" .

echo "=== Raw SQL ==="
grep -rn "query(\`\|query(f\"\|query('" --include="*.{js,ts,py}" .

Manual Review Priorities

  1. Authentication middleware — Is it applied to every protected route, or just some?
  2. Error handling — Do errors leak internal details to clients?
  3. File upload — Is file type validated? Is the storage sandboxed?
  4. Rate limiting — Does any public endpoint lack rate limiting?
  5. HTTPS — Is TLS enforced in production? Are there HTTP fallbacks?
  6. Dependency audit — Run npm audit, pip audit, or equivalent. AI often picks outdated packages.

The "Before You Ship" Checklist

Before any AI-generated code goes to production:

  • All credentials are in environment variables, not in code
  • .gitignore covers all secret files
  • Git history has been checked for leaked secrets
  • CORS is restricted to known origins
  • All user input is validated and sanitized
  • SQL queries use parameterized statements
  • Service accounts follow least-privilege
  • Authentication is enforced on every protected endpoint
  • Error responses don't leak internal details
  • Rate limiting is configured on public endpoints
  • Database connections have pool limits and timeouts
  • File uploads are type-checked and size-limited
  • Dependencies have been audited for known vulnerabilities
  • TLS is enforced in production
  • Logging doesn't capture sensitive data (passwords, tokens, PII)

Why AI Gets This Wrong

AI coding assistants optimize for functional correctness. They make code that works. But security is about adversarial correctness — making code that works even when someone is actively trying to break it.

The AI has never been burned by a production incident. It hasn't stayed up until 3am rotating leaked credentials. It doesn't have the scar tissue that makes experienced developers automatically reach for parameterized queries and least-privilege service accounts.

That scar tissue is what this audit replaces. Run it on every AI-generated codebase before shipping. The 30 minutes it takes is cheaper than the incident it prevents.

Install this skill directly: skilldb add vibe-coding-security-skills

Get CLI access →