Skip to content

Security Pitfalls

Learn From Others

These are the mistakes that organizations make repeatedly. GE's methodology exists to prevent them structurally — not by hoping agents remember, but by building gates that make these mistakes impossible.


Pitfall 1: Security as Afterthought

The mistake: Build the feature first, add security later. Why it happens: Pressure to deliver. Security feels like it slows down. The reality: Retrofitting security is 10-100x more expensive than building it in. And it never works as well.

GE prevention: Victoria blocks development start until the threat model exists. There is no "later" — security is the starting condition.


Pitfall 2: Threat Model Theater

The mistake: Produce a threat model document, then never use it. Filing it satisfies the process. Nobody reads it during implementation.

Why it happens: Threat modeling is seen as a compliance checkbox rather than an engineering input. The document format is disconnected from the development workflow.

GE prevention: Threat models generate security requirements that become acceptance criteria in work items. Pol's penetration test plan is derived directly from the threat model. If the threat model is not actionable, Victoria rewrites it until it is.


Pitfall 3: Over-Reliance on Framework Security

The mistake: "We use Next.js / Django / Rails, so we are secure." Frameworks provide good defaults, but they do not prevent business logic vulnerabilities, IDOR, authorization bypasses, or misuse of framework features.

Why it happens: Framework documentation emphasizes security features. Developers assume those features are sufficient and always active.

GE prevention: Framework security is the baseline, not the ceiling. Every endpoint still gets explicit authorization checks. Every data access still validates ownership. Pol tests business logic flaws that no framework can prevent.

Common framework traps:

  • CSRF protection disabled for API routes "because it's JSON"
  • ORM used, but raw SQL queries added for "performance"
  • Authentication middleware applied globally but accidentally skipped on new route groups
  • File upload handlers trusting client-provided MIME types

Pitfall 4: Secrets in Code

The mistake: Hardcoding API keys, database passwords, or tokens in source code, environment files committed to git, or configuration files baked into container images.

Why it happens: Convenience during development. "I will move it to Vault later." Later never comes.

GE prevention:

  • Pre-commit hooks scan for secret patterns
  • CI/CD pipeline runs secret scanning on every build
  • All secrets live in Vault, injected at runtime
  • .env files are in .gitignore and never committed
  • Container images contain zero secrets

What counts as a secret:

  • API keys and tokens
  • Database connection strings with credentials
  • Private keys and certificates
  • OAuth client secrets
  • Webhook signing secrets
  • Any value that grants access to a system

Pitfall 5: CORS Misconfiguration

The mistake: Setting Access-Control-Allow-Origin: * because "it makes the API work" during development, then shipping it.

Why it happens: CORS errors are frustrating. The wildcard fixes them instantly. The developer intends to restrict it later.

The consequence: Any website on the internet can make authenticated requests to the API using the user's cookies.

GE prevention:

  • CORS origin is configured per environment in config files
  • Production CORS allows only the exact production domain
  • Wildcard CORS is flagged by CI/CD security scan
  • Credentials mode requires explicit origin (browser enforces this, but misconfigured servers can still leak data via non-credentialed requests)

Correct CORS configuration:

Development: http://localhost:3000
Staging:     https://staging.example.com
Production:  https://app.example.com

Never: *


Pitfall 6: JWT Pitfalls

The mistake: Using JWTs incorrectly in ways that create vulnerabilities that are invisible in normal testing.

Common JWT mistakes:

Mistake Consequence
alg: none not rejected Attacker forges unsigned tokens
Secret key too short Brute-force cracking becomes feasible
No expiry (exp claim) Stolen token valid forever
Token stored in localStorage XSS can steal the token
Symmetric key shared with client Client can forge tokens
No audience (aud) validation Token from one service accepted by another
Sensitive data in payload JWT payload is base64, not encrypted

GE prevention:

  • JWT library configured to reject alg: none
  • Asymmetric keys (RS256/ES256) for cross-service tokens
  • Short expiry (15 minutes) with refresh token rotation
  • Tokens stored in httpOnly, secure, SameSite cookies
  • Payload contains only identifiers, never sensitive data
  • Audience and issuer validation enforced

Pitfall 7: Dependency Vulnerabilities Ignored

The mistake: Running npm audit or pip audit, seeing vulnerabilities, and ignoring them because "they are in dev dependencies" or "the vulnerable function is not called."

Why it happens: Dependency updates break things. The vulnerable code path seems unreachable. The fix requires a major version bump.

The reality: Supply chain attacks (OWASP A03:2025) exploit exactly this complacency. SolarWinds, Log4Shell, and the xz-utils backdoor all targeted the supply chain.

GE prevention:

  • Automated dependency scanning in CI/CD
  • Critical vulnerabilities block the build
  • SBOM generated for every release
  • Lockfile integrity verified
  • Transitive dependencies are not invisible — they are scanned
  • Monthly dependency update cycle with security-focused review

Pitfall 8: Logging Sensitive Data

The mistake: Logging request bodies, including passwords, tokens, credit card numbers, or PII. "For debugging."

Why it happens: Developers need to debug production issues. Structured logging captures request/response pairs. Nobody remembers to filter sensitive fields.

The consequence: Logs become an unprotected copy of sensitive data, accessible to anyone with log access, retained indefinitely, and often shipped to third-party log aggregation services.

GE prevention:

  • Logging middleware redacts known sensitive fields
  • Allowlist approach: log only specified fields, not "everything"
  • Log review in security checklist
  • PII in logs violates GDPR — it is a compliance issue, not just a security issue

Pitfall 9: Trusting Client-Side Validation

The mistake: Validating input in the browser and assuming the server will receive valid data.

Why it happens: Client-side validation is visible and testable. Developers see it working and assume it is sufficient.

The reality: An attacker bypasses client-side validation in seconds using browser dev tools, curl, or a proxy like Burp Suite. Client-side validation is a UX feature, not a security control.

GE prevention:

  • Server-side validation is mandatory on all inputs
  • Client-side validation is for user experience only
  • Zod schemas (or equivalent) validate at the API boundary
  • Never trust: Content-Type headers, file extensions, Content-Length, referrer headers, or any client-provided metadata

Pitfall 10: Security by Obscurity

The mistake: Relying on attackers not knowing the URL, not finding the admin panel, not guessing the API key format, or not understanding the internal architecture.

Why it happens: It feels like a layer of defense. "They would have to know where to look."

The reality: Obscurity is not a control. It is a delay at best, and a false sense of security at worst. Automated scanners find hidden endpoints in minutes.

GE prevention:

  • Every endpoint is secured as if its location is public knowledge
  • Admin panels require authentication, not just hidden URLs
  • API documentation assumes the attacker has full knowledge
  • Security controls work even with complete system transparency

Pitfall 11: Ignoring Error Handling Security

The mistake: Returning detailed error messages in production, including stack traces, database query text, internal paths, or framework version numbers.

OWASP A10:2025 — Mishandling of Exceptional Conditions is a new entry in the 2025 Top 10, reflecting how often this is overlooked.

GE prevention:

  • Production error responses contain only a correlation ID
  • Detailed errors go to structured logs, not to the client
  • Fail-closed: errors default to deny, not to allow
  • Exception handlers cover all code paths
  • Resource exhaustion returns 503, not a crash dump

Quick Reference: Agent Checklist

Before submitting code for review, every agent verifies:

  • [ ] No hardcoded secrets in code or config
  • [ ] All inputs validated server-side
  • [ ] All outputs encoded for their context
  • [ ] Error messages reveal no internal state
  • [ ] Dependencies scanned and clean
  • [ ] CORS configured for specific origins
  • [ ] Authentication required on all non-public endpoints
  • [ ] Authorization checked at resource level, not just route level
  • [ ] Logging contains no sensitive data
  • [ ] Cryptographic operations use standard library functions

Further Reading