An application can load quickly, pass a normal click-through test, and still be unready for production.
That is not a contradiction. Functional testing and security testing answer different questions.
A functional test asks whether a user can complete the intended journey. A security review asks what else the application, domain, browser, server, and deployment will allow.
An anonymized review of one AI-built web application made that difference clear. The app scored 100 out of 100 for performance, yet the broader review found 35 open issues:
- 1 critical
- 6 high severity
- 19 medium severity
- 9 low severity
The application was not visibly broken. It loaded fast, rendered correctly, and supported its main workflow. Most of the problems existed outside the path a builder would normally test in the browser.
What the review measured
The application was assessed across four areas:
- Performance: 100 out of 100, with no findings
- Security: 70 out of 100, with 16 findings
- Infrastructure: 54 out of 100, with 10 findings
- Search visibility: 46 out of 100, with 9 findings
The combined score was 67 out of 100.
The perfect performance result was valid. The app handled loading speed, caching, asset delivery, and rendering well. Modern frameworks and AI app builders often provide good defaults for these areas.
The security and infrastructure findings were also valid. They did not affect the normal user experience, so manual testing had not exposed them.
This is a common weakness in fast AI-assisted development. The builder checks whether the requested feature works. Nobody checks the surrounding controls unless the release process requires it.
Missing DMARC left the domain easier to impersonate
The domain had no DMARC policy.
DMARC works with SPF and DKIM to help receiving mail systems evaluate messages that claim to come from a domain. It also lets the domain owner specify what should happen when authentication checks fail.
Without an appropriate policy, attackers have more room to send email that appears connected to the company. That can support phishing against customers, employees, or partners.
Nothing about this problem appears in the app interface. A registration form, dashboard, or payment flow can work perfectly while the email domain remains poorly protected.
Teams should review email authentication whenever a new domain is prepared for production, even if the application itself does not send much email yet.
The browser had no Content Security Policy
The application did not send a Content Security Policy header.
CSP tells the browser which sources may provide scripts, styles, frames, images, and other resources. A well-designed policy can limit what malicious code is allowed to execute if an injection weakness or compromised third-party script reaches a page.
CSP is not a substitute for fixing cross-site scripting. It is an extra restriction that can reduce impact.
Adding it carelessly can break legitimate application behavior. Start by listing the resources the app needs, test the policy in a non-production environment, and review browser reports before enforcing it.
The important point is ownership. If nobody is responsible for response headers, the control may never enter the release checklist.
HTTPS was present, but HSTS was missing
The application used HTTPS but did not send a Strict-Transport-Security header.
HSTS tells compatible browsers to use HTTPS for future requests to the domain. It reduces the chance that a visitor's first connection will be downgraded to HTTP on an untrusted network.
A browser padlock confirms the current page uses HTTPS. It does not confirm that HSTS is configured correctly.
Before enabling HSTS, confirm that the domain and required subdomains work over HTTPS. A long duration or an includeSubDomains directive can create an outage if part of the domain still depends on HTTP.
This is a small configuration change with real consequences, so teams should test it instead of copying a header value without understanding its scope.
The app could be framed by another site
The review also found no effective clickjacking protection.
Without a framing restriction, another website may be able to load the application inside an invisible or misleading frame. An attacker can then try to persuade a user to click a real application control while believing they are interacting with something else.
The preferred modern control is the frame-ancestors directive in CSP. Some teams also retain X-Frame-Options for older browser support.
Applications that intentionally support embedding need a more precise policy. Blocking every frame is not appropriate when approved partner domains must embed the application.
Again, the correct setting depends on the product. The AI builder cannot infer that business rule from a generic request to create a dashboard.
Infrastructure findings sat outside the main code path
The review found several other gaps:
- no CAA record restricting certificate issuance
- no DKIM signature for outgoing email
- server information exposed in responses
- no
robots.txtfile for crawler guidance
These findings did not have equal security impact. A missing crawler file should not receive the same response as exposed credentials or broken authorization.
Their shared cause was a missing review step. The visible product had received attention. Domain, email, server, and deployment configuration had not.
This distinction matters because teams can waste time if they treat every automated finding as urgent. Severity is a starting point, not the complete decision.
Why vibe coding creates this blind spot
AI coding tools respond to the requirements in the prompt and the context available to them.
If someone requests a login page, dashboard, database integration, and billing flow, the tool focuses on those capabilities. It may not know the organization's email setup, deployment architecture, data classification, threat model, or access policies.
Many missing controls do not cause a build failure:
- a missing security header does not stop the page from rendering
- weak email authentication does not break a dashboard
- excessive cloud permissions do not affect the happy path
- a vulnerable package may continue to work normally
- an exposed secret may remain unused by an attacker for weeks
- a broken database policy may go unnoticed when testing with one account
This is why "the app works" cannot be used as evidence that the app is secure.
The issue is not that AI-generated code is automatically unsafe. The issue is that fast generation often removes the independent review that used to happen between implementation and release.
Teams need to put that review back into the workflow.
A public deployment review cannot inspect everything
A review of a live URL can examine publicly visible behavior and configuration, including:
- TLS configuration
- DNS and email authentication records
- HTTP response headers
- public files and browser assets
- exposed server information
- cross-origin behavior
It cannot inspect a private repository without authorized access.
Repository analysis answers different questions. It can look for insecure code patterns, secrets committed to Git history, vulnerable dependency versions, and code that is difficult to review safely.
Both views matter.
A source repository can appear clean while the deployed environment has weak headers or incorrect DNS records. A live site can appear well configured while its code contains an injection flaw, an outdated dependency, or a key committed in an older revision.
Treat repository checks and deployment checks as separate release controls.
Prioritize findings instead of chasing the total count
The number 35 sounds serious, but the total does not tell a team what to fix first.
Prioritization should consider at least five factors:
- What an attacker could do
- Whether the affected path is publicly reachable
- Whether sensitive data or privileged actions are involved
- How widely the issue affects the application
- Whether the proposed fix can be tested and rolled back safely
Leaked production credentials, public database access, broken authorization, and reachable injection flaws normally take priority over low-impact information disclosure or missing search metadata.
Easy fixes can still be worth doing early when they reduce meaningful risk. The reviewed application could address several high-severity configuration gaps without rewriting application logic. That did not make every fix risk-free. Header and DNS changes still needed testing and verification.
A practical pre-release checklist
Before publishing an AI-built web application, verify the following:
- Store production secrets outside source control.
- Scan the complete Git history for previously committed credentials.
- Rotate any exposed secret instead of only deleting the file.
- Test authorization with multiple users and roles.
- Confirm database policies prevent cross-account access.
- Review direct and transitive dependencies for known vulnerabilities.
- Restrict CORS to the origins, methods, and headers the application needs.
- Configure relevant security headers and test them in staging.
- Set up SPF, DKIM, and DMARC for domains that send email.
- Remove unnecessary server and framework disclosures.
- Review repository, CI/CD, cloud, and deployment permissions.
- Scan a representative staging deployment before release.
- Check the production URL after deployment.
- Assign an owner and review date to every accepted risk.
Adjust the checklist to the application. A public portfolio has a different risk profile from a multi-tenant product that stores financial, health, or customer information.
Recheck after deployment
Security review is not complete when a developer merges a fix.
Confirm that the corrected configuration reached production. A reverse proxy, hosting platform, content delivery network, or environment variable can make the deployed result different from the local version.
Run checks again after changes to:
- hosting providers
- domains or DNS
- authentication systems
- database policies
- third-party scripts
- dependencies
- deployment workflows
- major application routes
Certificates expire, package vulnerabilities are disclosed, and configuration changes accumulate. A secure launch does not guarantee a secure application six months later.
The main lesson
The reviewed application was fast. It was functional. It also missed controls that mattered.
Those facts can all be true at the same time.
AI-assisted development reduces the time required to turn an idea into a working application. It does not remove the need to review code, dependencies, permissions, domain settings, deployment configuration, and the final production result.
Keep the speed advantage. Add a security checkpoint before launch, then verify the application again after it reaches production.
Top comments (0)