Security Isn’t About Shipping Fast. It’s About Knowing What You’re Releasing

Share
Security Isn’t About Shipping Fast. It’s About Knowing What You’re Releasing

I recently got pulled into a project that was technically “finished.” The app worked, the flows worked, and the subscriptions worked. But the founder still didn’t feel safe releasing it, and honestly… I understood why almost immediately.

The app had been built pretty quickly by a couple of junior engineers heavily assisted by AI tools and vibe coding workflows.

To be clear, this isn’t an anti-AI post. I use AI daily — a lot. It can massively accelerate development, unblock implementation, and help teams move faster.

But there’s something I’ve started noticing more often recently: AI is very good at producing code that looks production-ready. And sometimes that’s exactly the problem.

Because the dangerous part about insecure code is that most of the time… it doesn’t look dangerous.

The app compiles, the architecture looks reasonable, the flows work, QA passes, and the UI looks polished. But underneath that, there can still be hidden production risk.

When I started reviewing the project, I wasn’t looking for movie-style hacking scenarios. I was looking for the quiet stuff — the kinds of issues that slowly become security problems later.

Things like:

  • Secrets hardcoded into the app bundleOne of the most common issues in mobile apps is embedding API keys, service credentials, or internal endpoints directly into the binary because it simplifies development. The challenge is that mobile applications can always be inspected eventually, so anything shipped inside the app should be treated as potentially accessible.A safer approach is separating sensitive configuration from the client whenever possible. From a mobile standpoint, iOS projects can use .xcconfig files, environment-based builds, and Keychain-backed flows where appropriate, while Android projects often rely on Gradle configuration separation, encrypted local storage, and the Android Keystore system. And when credentials truly need to exist on-device, limiting their permissions and scope becomes extremely important.
  • Firebase/Supabase rules that were more permissive than intendedDuring rapid prototyping, teams often relax database rules temporarily just to keep development moving. The problem is that those temporary permissions sometimes survive into production unnoticed.What tends to work better is adopting a least-privilege mindset early, reviewing access rules before release, and treating open-access configurations as short-lived exceptions rather than defaults.
  • Admin-only logic enforced only on the clientFrontend-only authorization is one of those things that can feel secure while still leaving critical gaps underneath. If admin restrictions only exist in UI logic, they’re ultimately just presentation rules.Sensitive permissions are generally much safer when validated server-side as well, regardless of what the client displays, hides, or restricts visually.
  • Tokens stored in places they probably shouldn’t beAuthentication tokens and session data sometimes end up stored in plain persistence layers simply because it’s convenient during implementation. Over time, those shortcuts can become unnecessary risk.From the mobile side, iOS apps generally benefit from storing sensitive credentials in Keychain instead of UserDefaults, while Android apps can rely on the Android Keystore system together with encrypted shared preferences or encrypted storage APIs depending on the application requirements and threat model.
  • Temporary debug configurations that quietly became production behaviorDebug bypasses, verbose logging, mock authentication flows, and feature flags are all useful during development. The issue appears when those temporary configurations accidentally become part of the production environment.One practice that helps significantly is performing explicit production configuration reviews before release, especially on fast-moving teams shipping frequently.
  • API keys assumed to be “safe” because they live in a mobile appThere’s still a common misconception that compiled apps somehow hide embedded keys. In reality, if a key ships with the application, it should be assumed discoverable.When a credential could be abused, additional protections like scoped permissions, server-side validation, rate limiting, or domain restrictions usually provide a much safer architecture.
  • Excessive logging or analytics exposing sensitive informationLogging is incredibly valuable operationally, but it can quietly become a liability when sensitive information starts appearing in analytics events or debug traces.A good habit is treating logs as potentially exposable systems and minimizing sensitive payloads whenever practical — especially emails, tokens, identifiers, or personal user data.
  • Client-side validation trusted more than it should beClient-side validation is excellent for user experience, but it should never be confused with actual security enforcement.Anything critical — permissions, ownership checks, pricing logic, quotas, or access restrictions — is generally safer when validated server-side too, even if the frontend already performs validation for UX purposes.

None of these issues came from bad intentions. Most came from completely understandable decisions made under pressure: ship faster, unblock testing, get the feature working, clean it later.

And honestly, AI can amplify that dynamic even more. Not because it generates “bad” code, but because it generates plausible code. Code that looks clean, feels reasonable, and works well enough that teams stop questioning some of the assumptions underneath it.

That’s where experience still matters a lot. Not because senior engineers magically know every security rule, but because after enough production systems, you start recognizing patterns that tend to become dangerous later. You develop a sense for hidden blast radius and start asking different kinds of questions:

  • “What happens if this token leaks?”
  • “Can this actually be enforced server-side?”
  • “Are these permissions too open?”
  • “Would I still trust this if someone inspected the app bundle?”
  • “Is this secure… or does it just feel secure?”

I honestly think this is becoming one of the biggest shifts in modern software engineering.

Funny enough, we actually wrote a post about this recently: The Bottleneck Is No Longer Writing Code

AI can accelerate implementation, but production readiness still depends heavily on engineering judgment.

Read more