# CheckVibe > CheckVibe is an all-in-one security, SEO, and AEO scanner for any website — production SaaS, marketing sites, e-commerce, and AI-/vibe-coded apps alike. Enter a URL and get 100+ security checks (including live Supabase RLS testing), 68 SEO checks, and 46 AEO checks — plus uptime monitoring with public status pages, Core Web Vitals performance monitoring, accessibility checks, and email deliverability monitoring. From $0. CheckVibe scans websites for security vulnerabilities in under 60 seconds. It runs 100+ security checks in parallel — with site crawling — to detect issues before attackers do. It also audits how visible a site is to Google and AI answer engines (ChatGPT, Perplexity, Claude, Gemini) with 113 SEO/AEO checks, and watches site health continuously: uptime (60-second external checks with public status pages), real-user Core Web Vitals with regression alerts, WCAG accessibility signals, email deliverability (SPF/DKIM/DMARC), and domain hygiene (expiry, DNS drift, certificates). ## What CheckVibe Does CheckVibe is a SaaS security scanning platform for web developers, indie hackers, and teams who ship fast. Enter a URL, click scan, and get a comprehensive security audit covering: - SQL injection detection (error-based, time-based, blind) - Cross-site scripting (XSS) detection (reflected, stored, DOM-based) - Exposed API key scanning (100+ provider patterns including AWS, Stripe, Supabase, Firebase, GitHub, Twilio) - Security header analysis (CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy) - SSL/TLS certificate and cipher auditing - CORS misconfiguration detection - CSRF vulnerability testing - Cookie security analysis (Secure, HttpOnly, SameSite) - DNS configuration checks (DNSSEC, SPF, DKIM, DMARC) - Open redirect detection - File upload vulnerability scanning - DDoS protection analysis (WAF, CDN, rate limiting) - Domain hijacking risk assessment - Dependency vulnerability scanning (npm CVEs) - GitHub secret leak detection - GraphQL introspection leak detection - JWT weakness analysis - Input validation flaw detection - Debug endpoint exposure scanning - Authentication bypass testing - Backend-specific security checks (Supabase RLS, storage buckets, auth settings) - Hosting provider audits (Vercel, Netlify, Cloudflare) - Audit logging and monitoring assessment - Mobile API security checks - Site crawling and endpoint discovery ## Site Crawling CheckVibe crawls your entire site before scanning — discovering pages via robots.txt, sitemap.xml, HTML links, and JavaScript route extraction. Multi-URL scanners then test each discovered endpoint individually, so nothing is missed. ## SEO & AEO Visibility Scanning Beyond security, CheckVibe audits search and AI-answer-engine visibility: - SEO scanner (68 checks): indexability, canonicals, sitemaps, structured data depth, Core Web Vitals (CrUX field data), meta tags, internal linking, response times - AEO scanner (45 checks): llms.txt, AI-crawler access (GPTBot, ClaudeBot, PerplexityBot), answer-ready content structure, entity grounding, schema for answer engines, per-engine readiness matrix - Results live in a dedicated SEO & AEO dashboard tab, separate from the security score Learn more: https://checkvibe.dev/products/seo-aeo ## Site Health Monitoring CheckVibe also watches the layers under and around the app — availability, speed, accessibility, and the infrastructure record: - Uptime monitoring: external checks every 60 seconds (HEAD with GET fallback, 10s timeout), incident tracking with consecutive-failure thresholds and error classes (DNS, TLS, refused, timeout, 5xx), down + recovery email alerts, and a public status page per project with live state, 90-day daily history, and uptime percentages - Performance: lab diagnostics (TTFB, compression, HTTP/2/3, redirects, page weight, render-blocking resources, image optimization) fused with real-user Core Web Vitals from the Chrome UX Report (28-day p75 LCP/INP/CLS, phone-first, 40 weeks of history) plus an optional RUM snippet; daily regression watch alerts when a vital regresses materially or crosses Google's thresholds - Accessibility: 27 WCAG 2.x Level AA signals across structure, forms, navigation/focus, and media — EAA-relevant, on the homepage plus sampled interior pages - Email deliverability: SPF (with recursive 10-lookup-limit counting), DKIM selector discovery, DMARC policy grading, MX/null-MX, MTA-STS, TLS-RPT, BIMI readiness, and a managed DMARC aggregate-report inbox - Domain Watchtower: RDAP expiry runway and transfer locks, nameserver drift, DNSSEC, CAA records, certificate expiry via Certificate Transparency logs, apex/www/IPv6 hygiene - SSL/TLS grade: A+ to F from protocol versions, cipher strength, forward secrecy, certificate health, HSTS, and mixed content Learn more: https://checkvibe.dev/products/monitors ## MCP Server Integration CheckVibe provides a native MCP (Model Context Protocol) server at `@checkvibe/mcp-server` on npm. Compatible developer tools can run security scans, SEO/AEO visibility audits, get results, and manage projects directly from the local workflow. 13 tools available: run_scan, run_seo_aeo_scan, get_scan_results, get_visibility_results, list_scans, list_projects, get_project, update_project, delete_project, delete_scan, dismiss_finding, list_dismissals, restore_finding. ## Remediation Guidance Every finding includes remediation guidance that explain the vulnerability and provide code-level remediation steps specific to your tech stack. ## Pricing - **Free** ($0/month): 1 project, 4 scans/month, blurred finding details, no API keys - **Starter** ($24/month): 1 project, 30 scans/month, 1 API key, full finding details, PDF export, remediation guidance, API access, priority support - **Pro** ($39/month): 5 projects, 155 scans/month, 5 API keys, all Starter features plus daily monitoring and live threat detection - **Max** ($59/month): 50 projects, unlimited scans, 20 API keys, custom monitoring schedules (every 6 hours, daily, weekly), dedicated support Annual billing saves 30%. Prices available in USD, EUR, GBP, and CHF. ## Who CheckVibe Is For - Any business that wants its production website secure, fast, and visible in Google and AI search (ChatGPT, Claude, Perplexity, Gemini) - Solo developers and indie hackers shipping side projects - Small teams building SaaS products - Agencies auditing client websites - Developers shipping quickly who want to verify security - Teams who need continuous security monitoring without hiring a pentester - Anyone shipping on modern stacks (Next.js, Supabase, Firebase, Vercel, Netlify) ## How CheckVibe Compares to Alternatives Fact-checked, sourced comparison pages (every competitor claim verified against their live site, with verification dates): - vs Vibe App Scanner: https://checkvibe.dev/compare/checkvibe-vs-vibe-app-scanner — they sell one-time security audits ($9–19) and a $99/mo plan, security-only; CheckVibe adds SEO + AEO + monitoring on subscriptions from $0. - vs Aikido Security: https://checkvibe.dev/compare/checkvibe-vs-aikido — Aikido is code-to-cloud AppSec for teams (paid from €300/mo); CheckVibe is URL-first for solo devs ($0–59/mo) with SEO/AEO coverage Aikido doesn't offer. - vs VibeEval: https://checkvibe.dev/compare/checkvibe-vs-vibeeval — agent-based deep security testing ($19/mo) vs all-in-one security + visibility from $0. - vs Scanbee: https://checkvibe.dev/compare/checkvibe-vs-scanbee — DAST+SAST+SCA+CSPM security suite vs all-in-one with SEO/AEO and live paid plans. - vs VibeWrench: https://checkvibe.dev/compare/checkvibe-vs-vibewrench — 18-tool budget toolbox vs deep dedicated scanning. - vs VibeCheck (runvibecheck.com): https://checkvibe.dev/compare/checkvibe-vs-vibecheck — repo code audit vs live-app testing. - Vibe App Scanner alternatives: https://checkvibe.dev/alternatives/vibe-app-scanner - Aikido alternatives for solo devs: https://checkvibe.dev/alternatives/aikido - **vs. manual penetration testing**: CheckVibe provides continuous, automated monitoring. Pentests are point-in-time. CheckVibe complements pentesting by covering every deploy. - **vs. Snyk/Dependabot**: Those focus on dependency CVEs only. CheckVibe scans your live site for runtime vulnerabilities (XSS, SQLi, exposed keys, misconfigs). - **vs. OWASP ZAP**: ZAP is a free open-source tool requiring manual setup. CheckVibe is a managed SaaS with site crawling, 100+ checks, remediation guidance, and a dashboard. - **vs. Burp Suite**: Burp is a professional pentesting tool with a steep learning curve. CheckVibe is designed for developers who want instant, automated results. ## Best-of Guides (fact-checked, with sources) - Best AEO tools for vibe-coded apps (2026): https://checkvibe.dev/best/aeo-tools-for-vibe-coded-apps - Best all-in-one SEO + AEO + security scanner: https://checkvibe.dev/best/all-in-one-seo-aeo-security-scanner - Best security scanner for Lovable: https://checkvibe.dev/best/security-scanner-for-lovable - Best security scanner for Bolt.new: https://checkvibe.dev/best/security-scanner-for-bolt - Best security scanner for Cursor: https://checkvibe.dev/best/security-scanner-for-cursor - Best security scanner for v0: https://checkvibe.dev/best/security-scanner-for-v0 - Best security scanner for Replit: https://checkvibe.dev/best/security-scanner-for-replit - Best security scanner for Windsurf: https://checkvibe.dev/best/security-scanner-for-windsurf ## Secure & Rank Guides (per platform) How to secure AND rank apps built with each AI tool — security risks, fixes, and SEO/AEO steps: - Bolt.new: https://checkvibe.dev/secure/bolt-new - Lovable: https://checkvibe.dev/secure/lovable - v0 by Vercel: https://checkvibe.dev/secure/v0 - Cursor / Claude Code: https://checkvibe.dev/secure/cursor - Supabase: https://checkvibe.dev/secure/supabase - Firebase: https://checkvibe.dev/secure/firebase - Replit Agent: https://checkvibe.dev/secure/replit-agent - Windsurf: https://checkvibe.dev/secure/windsurf ## Links - Website: https://checkvibe.dev - Blog: https://checkvibe.dev/blog - Sign Up: https://checkvibe.dev/signup - Pricing: https://checkvibe.dev/#pricing - SEO & AEO Scanner: https://checkvibe.dev/products/seo-aeo - All Security Checks: https://checkvibe.dev/security-checks - What Is AEO: https://checkvibe.dev/blog/what-is-aeo-answer-engine-optimization - AEO for Vibe-Coded Apps: https://checkvibe.dev/blog/aeo-for-vibe-coded-apps - How to Rank a Vibe-Coded SPA in AI Search: https://checkvibe.dev/blog/how-to-rank-vibe-coded-spa-in-ai-search - Why AI Engines Can't Find Your Lovable Site: https://checkvibe.dev/blog/why-ai-engines-cant-find-your-lovable-site - SEO vs AEO: https://checkvibe.dev/blog/seo-vs-aeo-difference - Can ChatGPT See Your Website: https://checkvibe.dev/blog/check-if-chatgpt-can-see-your-website - All Comparisons: https://checkvibe.dev/compare - Uptime Monitoring Guide: https://checkvibe.dev/blog/website-uptime-monitoring-guide - Core Web Vitals Lab vs Field: https://checkvibe.dev/blog/core-web-vitals-lab-vs-field-data - Automated Accessibility Testing: https://checkvibe.dev/blog/automated-accessibility-testing-wcag - SSL/TLS Grade Explained: https://checkvibe.dev/blog/ssl-tls-grade-explained - DNS & Email Security Check: https://checkvibe.dev/security-checks/dns-email-security - RSS Feed: https://checkvibe.dev/feed.xml - Full Documentation: https://checkvibe.dev/llms-full.txt - Contact: support@checkvibe.dev --- # Detailed Scanner Descriptions ## Security Headers Scanner Checks for the presence and configuration of critical HTTP security headers: Content-Security-Policy (CSP), Strict-Transport-Security (HSTS), X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy. Flags missing, weak, or misconfigured headers. Multi-URL: tests each discovered page individually. ## SQL Injection Scanner Tests all accessible input vectors (URL parameters, form fields, headers) with error-based, time-based, and blind SQL injection payloads. Detects both classic and modern injection patterns. Multi-URL: tests each discovered endpoint. ## XSS Scanner Injects hundreds of cross-site scripting payloads across reflected, stored, and DOM-based attack vectors. Tests various encoding bypasses and context-aware payloads. Multi-URL: tests each discovered page. ## API Key Scanner Pattern-matches against 100+ known API key formats (AWS, Stripe, Supabase, Firebase, GitHub, Twilio, SendGrid, OpenAI, Anthropic, etc.) in page source, JavaScript bundles, and network requests. Performs entropy analysis for unknown key formats. Multi-URL: scans each page's source. ## SSL/TLS Scanner Validates certificate chain, expiration, protocol versions (TLS 1.2+), cipher suite strength, and HSTS configuration. Flags deprecated protocols and weak ciphers. ## CORS Scanner Tests Cross-Origin Resource Sharing configuration for overly permissive policies (wildcard origins, credential sharing, preflight bypasses, null origin, origin reflection). Multi-URL: tests each endpoint. ## CSRF Scanner Checks for Cross-Site Request Forgery protections: token presence, SameSite cookie attributes, and custom header requirements on state-changing endpoints. Multi-URL. ## Cookie Scanner Audits all cookies for Secure flag, HttpOnly flag, SameSite attribute, proper expiration, and path/domain restrictions. Multi-URL. ## DNS Scanner Checks DNSSEC configuration, SPF records, DKIM signing, DMARC policy, and identifies potential DNS-related attack vectors. ## DDoS Protection Scanner Detects WAF presence (Cloudflare, AWS WAF, etc.), CDN usage, rate limiting implementation, and basic DDoS mitigation measures. ## Domain Hijacking Scanner Assesses domain registration security via RDAP, nameserver integrity and diversity, typosquatting risk, zone exposure, and NS security configuration. ## GraphQL Introspection Scanner Detects exposed GraphQL endpoints and tests for introspection query availability, which can reveal your entire API schema to attackers. Multi-URL. ## JWT Audit Scanner Analyzes JSON Web Tokens for weak algorithms (none, HS256 with weak keys), missing expiration, improper signature validation, and information disclosure in payloads. ## Input Validation Scanner Tests form inputs and API parameters for missing or weak validation — detecting potential for injection, overflow, and type confusion attacks. Multi-URL. ## Debug Endpoint Scanner Discovers exposed debug endpoints, stack traces, error pages with sensitive information, and development tools left in production. Multi-URL. ## Authentication Scanner Tests authentication flows for common weaknesses: user enumeration, brute force vulnerability, insecure password policies, and session management issues. Multi-URL. ## Open Redirect Scanner Detects URL parameters that can redirect users to attacker-controlled sites — used in phishing and OAuth token theft. Multi-URL. ## File Upload Scanner Tests file upload functionality for dangerous file type acceptance, missing validation, path traversal, and unrestricted upload sizes. Multi-URL. ## Dependency Vulnerability Scanner Scans detected JavaScript dependencies for known CVEs using the npm advisory database. ## GitHub Security Scanner Checks connected GitHub repositories for exposed secrets, security alerts, branch protection rules, and security policy files. ## Supabase Security Scanner Audits Supabase projects for exposed service role keys, tables with RLS disabled, missing policies, and misconfigured auth settings. ## Vercel Security Scanner Checks Vercel deployments for exposed environment variables, preview deployment leaks, and security header configuration. ## Netlify Security Scanner Audits Netlify deployments for exposed build logs, environment variables, and redirect misconfigurations. ## Cloudflare Security Scanner Checks Cloudflare configuration for DNS leaks, WAF bypass potential, and SSL/TLS settings. ## Threat Intelligence Scanner (Pro only) Monitors for active threats targeting your domain: phishing campaigns, domain spoofing, brand impersonation, and dark web mentions. ## Scorecard Scanner Calculates an overall security score based on all scanner results, weighted by severity and impact. ## Mobile API Scanner Tests mobile-facing API endpoints for platform-specific vulnerabilities and insecure data handling. ## Audit & Legal Scanner Checks for presence of privacy policy, terms of service, cookie consent, and compliance indicators. ## Tech Stack Scanner Identifies the technology stack (frameworks, libraries, CDN, hosting) to contextualize security findings. ## Site Crawler BFS-based site crawler that discovers pages via robots.txt, sitemap.xml, HTML link extraction, and JavaScript route detection. Respects crawl limits per plan. Provides discovered URLs to all multi-URL scanners. --- # Frequently Asked Questions Q: What is CheckVibe? A: CheckVibe is an always-on security monitoring platform that crawls your entire site and runs 100+ automated checks to detect vulnerabilities like SQL injection, XSS, exposed API keys, misconfigured headers, GraphQL introspection leaks, JWT weaknesses, and more. Q: How does CheckVibe work? A: Enter your URL, click scan. CheckVibe crawls your site to discover every page and endpoint, then runs 100+ security checks in parallel. Results are ready in under 60 seconds with severity ratings and remediation guidance. Q: What vulnerabilities does CheckVibe detect? A: SQL injection, XSS, exposed API keys (100+ patterns), CORS misconfigurations, missing security headers, weak SSL/TLS, CSRF, open redirects, GraphQL introspection, JWT weaknesses, input validation flaws, debug endpoints, dependency CVEs, DNS issues, and BaaS misconfigurations (Supabase). Q: How much does CheckVibe cost? A: Paid plans unlock the full report with every finding and fix. Starter unlocks AI fix prompts, more scans, and API access. Pro adds more projects, more scans, and threat detection. Custom plans available for teams. Annual billing saves 30%. Prices shown in USD, EUR, GBP, or CHF based on visitor location — see checkvibe.dev/pricing for current rates. Q: How does CheckVibe compare to OWASP ZAP? A: OWASP ZAP is a free, manual tool for security researchers. CheckVibe is a managed SaaS designed for developers — 100+ automated checks, site crawling, remediation guidance, BaaS auditing, and MCP integration, all with zero configuration. Q: Does CheckVibe support CI/CD integration? A: Yes. CheckVibe provides a REST API (trigger scans and fetch results from any pipeline), webhooks, and MCP server support for compatible developer tools. --- # Blog Articles ## An AI Coding Assistant Policy Your Engineers Will Actually Follow *A short, enforceable policy for Copilot, Cursor and Claude Code on a real codebase: what to allow, what to gate in review, and which rules to skip.* Published: 2026-08-31 | Reading time: 9 min read URL: https://checkvibe.dev/blog/ai-coding-assistant-policy-for-teams Your engineers are already using AI coding assistants. The only decision left is whether you have a policy, and whether that policy is one they will follow or one they will route around. Most published AI coding policies fail for the same reason: they are written as prohibitions nobody can verify. "Do not paste proprietary code into external tools" is unenforceable on a laptop with an IDE extension. A policy that cannot be checked is not a control — it is a document you will show an auditor and quietly know is fiction. Here is a shorter policy that holds up, built around the observation that **the risk is not that AI writes bad code. It is that AI writes plausible code, quickly, in volume, and review capacity does not scale with it.** ## What actually goes wrong Not "AI hallucinates." The recurring, boring failure modes: **Security defaults get skipped, not broken.** An assistant asked for "an API route that returns a user's orders" produces a working route. It does not produce an authorisation check, because you did not ask for one and the code works without it. Nothing is *wrong* in the generated code — something is *absent*, and absence does not look like a bug in review. **Configuration gets copied out of tutorials.** Permissive CORS, a Supabase table without row-level security, `NEXT_PUBLIC_` on something that should never reach a browser, a header set to a value that appears in a blog post. These come from the training distribution, where tutorial code massively outnumbers production code. **Volume outruns review.** A generated 400-line diff gets the same fifteen minutes of attention a hand-written 40-line diff would. This is the real multiplier and no amount of prompt discipline fixes it. **Dependencies arrive without a decision.** An assistant reaches for a package. It gets installed. Nobody evaluated it, and sometimes nobody checked it exists — a suggested-but-nonexistent package name is an opening for someone to register it. ## The policy: six rules, all checkable Short enough to read, and every rule has a mechanical check behind it. That second property is what separates this from a document. ### 1. Assistants are allowed. Generated code is reviewed like any other code. State the permission explicitly. A policy that starts by restricting tools everyone already uses gets ignored in full, including the parts that matter. *Check:* branch protection requiring review. Already in place for most teams. ### 2. No secrets in the repository, generated or written. Assistants inline example credentials and sometimes real ones from context. This is the single highest-value rule because a secret in git history costs rotation plus history rewriting, not deletion. *Check:* secret scanning that blocks the merge. Not a comment — a block. See [security review in pull requests](/blog/pull-request-security-review). ### 3. New routes and new database access get an authorisation reviewer. The most common real gap. Make it a named requirement so it survives a busy week: any PR adding an endpoint or a new query path needs someone to explicitly say "I checked the authorisation." *Check:* a required checklist item or a path-based CODEOWNERS rule on your routes and data-access directories. ### 4. New dependencies get a line in the PR description. One sentence: why this package, and what it replaces. Not a committee — just enough friction that nobody installs something an assistant mentioned without reading its name. *Check:* a lockfile diff in CI that fails when dependencies changed and the PR body has no dependency note. ### 5. Generated diffs over 300 lines get split or paired. The rule engineers will push back on, and the one that catches the most. A large generated diff is not reviewable at normal attention; either split it into reviewable commits or review it live with the author. *Check:* a CI warning on diff size. Advisory, not blocking — this needs judgement. ### 6. The deployed application is scanned on a schedule, not just the code. Static review cannot see what only exists at runtime: the headers the server actually sends, whether that Supabase table is readable with the anon key, whether a key reached the shipped JavaScript bundle. Assistants generate configuration as readily as code, and configuration mistakes are runtime-visible only. *Check:* a scheduled scan of the deployed app, with findings landing in a queue with an owner and a deadline. ## The rules to leave out Equally important, because every unenforceable rule discounts the ones next to it. **"Do not paste proprietary code into AI tools."** Unenforceable with IDE extensions and unverifiable on a personal machine. If the concern is real, address it at the tool-selection layer: choose assistants with a business tier that contractually excludes training on your input, and configure them centrally. That is a procurement control, not an engineering rule. **"Disclose AI-generated code in commit messages."** Nobody complies consistently, the boundary is meaningless once autocomplete is involved, and the disclosure changes nothing about how the code is reviewed. If generated code needs different review, encode that in the review rule, not in a label. **"Only use approved models."** Approve the *tool*, not the model. Model versions change weekly and any list is stale on arrival. **"AI may not write security-relevant code."** Everything touching a request is security-relevant. This rule reads as caution and functions as a prohibition on the work, so it gets ignored, and its neighbours lose credibility with it. ## Choosing tools: the questions worth asking Before the engineering policy, three procurement questions that actually change your exposure: 1. **Is your code used for training?** All major assistants offer a business or enterprise tier that says no. Get the tier and get it in writing; the free tier's terms are usually different. 2. **Where is the context sent and retained?** Ask for the retention period and the region. This lands on your subprocessor list, which lands in your next [security questionnaire](/blog/security-questionnaire-answers). 3. **Can settings be enforced centrally?** An assistant configured per-laptop is configured differently on every laptop. Central policy enforcement is the difference between a control and a suggestion. ## The measurement that tells you whether it is working One number: **new findings per merged pull request, tracked monthly.** If assistant adoption rises and this holds flat, review is keeping up. If it climbs, review capacity is the bottleneck and rules 3 and 5 need tightening. It is a leading indicator, it does not require anyone to self-report, and it survives a change of tools. Pair it with **median time to remediate**, so you can see whether the queue is absorbing the new volume or just accumulating it. ## What CheckVibe covers here Concretely, for the checks above: - **Secret detection** across the deployed JavaScript bundle and connected repositories, matching provider key formats with their real prefixes plus entropy analysis — pattern-based and deterministic, so the same diff produces the same answer every time. - **PR review** with inline, committable suggestions scoped to the diff, and new-versus-closed counts against the base branch, so the comment reflects what the branch introduced. - **Runtime checks** on the deployed application: security headers, CORS as the server actually answers it, live Supabase row-level-security probing with the public anon key, TLS configuration, and publicly reachable debug or admin routes. - **Shared triage with SLAs** on both team tiers, so scheduled-scan findings get an owner and a materialised deadline rather than a dashboard number. - **An append-only audit log** — 180 days on Team Basic, a year on Team Advanced — which is what turns "we review generated code" into something evidenceable. Team plans are $25 per seat per month, five-seat minimum, with Jira/Linear sync and compliance reporting on Team Advanced at $50. [The pricing page](/pricing) has the detail, and [auditing Cursor and Copilot output](/blog/cursor-copilot-security-audit) goes deeper on the code-level checks. ## Frequently Asked Questions ### Should we ban AI coding assistants? No, and a ban is the least enforceable option available — engineers will use them on personal machines where you have no visibility at all. Permit them explicitly and put the controls where they are checkable: secret scanning that blocks merges, an authorisation reviewer on new routes and data access, a size limit on generated diffs, and scheduled scanning of the deployed application. ### What is the biggest security risk of AI-generated code? Omission rather than error. Asked for an endpoint, an assistant produces one that works, and working code does not require an authorisation check — so the check is simply absent. Absence is much harder to spot in review than a bug, because there is no wrong line to point at. Second is volume: generated diffs are larger and get the same review attention as hand-written ones. ### Do we need a written AI coding policy for SOC 2? No control in the Trust Services Criteria names AI tools. What auditors ask is whether code changes are reviewed and approved before production, which your existing change-management control already covers. A short AI policy is still worth having for enterprise security questionnaires, where the question is now common, and it is easier to answer with a one-page document than with a paragraph written under deadline. ### How do you review a 500-line AI-generated pull request? You do not, meaningfully — not in one pass. Either split it into commits that each do one thing, or review it live with the author, who can explain the intent that the diff does not carry. A CI warning on diff size makes the choice visible before review starts. Treating a large generated diff as reviewable at normal attention is how omitted authorisation checks reach production. ### Which AI coding tools are safe for proprietary code? The question is contractual, not technical: every major assistant offers a business or enterprise tier that excludes your input from training, and the free tiers generally do not. Get the paid tier, get the exclusion in writing, ask for the retention period and region, and add the vendor to your subprocessor list. Then enforce the configuration centrally, because per-laptop settings are not a control. ### Does static code analysis catch AI-generated security problems? Partly. It catches injection patterns, hardcoded secrets and unsafe API usage in the code itself. It cannot see the configuration mistakes assistants produce just as readily — permissive CORS as the server actually answers, a database table readable with the public key, a secret that reached the browser bundle, a missing security header. Those are only visible against the running deployment, which is why scheduled runtime scanning belongs in the policy alongside code review. --- *CheckVibe scans the deployed app and the repository, comments on pull requests, and puts what it finds in a shared queue with an owner and a deadline. [See what teams get](/pricing), or [run a free scan](https://checkvibe.dev).* --- ## Automated Security Review in Pull Requests: What Works and What Just Adds Noise *How to put security checks inside code review without teaching your team to ignore the bot: what to block on, what to comment on, what to leave out.* Published: 2026-08-31 | Reading time: 10 min read URL: https://checkvibe.dev/blog/pull-request-security-review The cheapest security fix is the one that happens before merge, while the author still has the change in their head. The most expensive one is the same fix six weeks later, in a backlog, assigned to whoever has capacity. That is the entire case for security review inside the pull request. It is also, in practice, the fastest way to build a bot every engineer dismisses, because most implementations comment on everything and block on nothing useful. This is how to get the first outcome instead of the second. ## The rule: block on the diff, report on the repository Almost every noisy PR security bot fails the same way — it reports the *repository's* problems on a *change's* review. Draw the line here: - **In the PR:** only what this diff introduced or changed. A new endpoint without an auth check. A secret added to a committed file. A dependency bumped to a version with a known CVE. Roughly: could the author fix it in this branch, right now, with the context they already have? - **Outside the PR:** everything the repository already had. Pre-existing findings, headers that were never set, an old dependency nobody touched. That belongs in a queue with an owner and a deadline — see [remediation SLAs](/blog/vulnerability-remediation-sla) — not on the review of an unrelated typo fix. Get this wrong and a two-line change collects fourteen comments about things the author did not do. The team learns to scroll past the bot within a week, and after that the tool is worse than nothing: it is a control you will report to an auditor that nobody reads. ## What is worth blocking a merge on A failing check that cannot be overridden is a strong statement. Spend it on findings that are (a) almost never false positives and (b) genuinely worse after merge than before. **Block on:** - **A live credential in the diff.** Once it is in git history, remediation is rotation plus history rewriting, not deletion. This is the strongest possible case for a hard block. - **A secret-shaped value under a public-by-design prefix.** `NEXT_PUBLIC_`, `VITE_`, `REACT_APP_` — anything so prefixed is compiled into the browser bundle. A token-shaped value behind one of those prefixes is a shipped secret. - **A new dependency with a known critical CVE.** Cheap to check, cheap to fix at the moment of adding, expensive to unpick later. **Comment, do not block:** - A new route with no visible authorisation check. Frequently correct, occasionally a public endpoint on purpose. Worth a question, not a wall. - SQL assembled by string interpolation. Usually a real problem, sometimes a migration script the reviewer knows is fine. - A new `dangerouslySetInnerHTML`, `eval`, or an unsanitised redirect target. - CORS or cookie configuration loosened in the diff. **Neither — put it in the queue:** - Anything the repository already had before this branch existed. - Anything requiring a running deployment to confirm: TLS grade, live headers, uptime. - Style and maintainability. Real, but not this bot's job. ## Comments engineers act on The difference between a comment that gets fixed and one that gets resolved-without-reading is almost always specificity. A weak comment: > ⚠️ **Potential security issue detected.** Possible hardcoded secret. Severity: HIGH. Confidence: MEDIUM. See documentation for remediation guidance. A comment that gets fixed: > `src/lib/mail.ts:14` — this is a live SendGrid key (`SG.` prefix, 69 chars). It is in the diff, so it will be in git history after merge; rotate it as well as removing it. Suggested change below moves it to an environment variable. > > ```suggestion > const apiKey = process.env.SENDGRID_API_KEY; > ``` Four things make the second one work: 1. **Exact location.** File and line, not "somewhere in this PR". 2. **Why it is true.** The `SG.` prefix and the length are the evidence. An engineer can verify the claim in two seconds instead of taking it on faith. 3. **The consequence they might not know.** Removing the line does not un-leak the key. 4. **A committable suggestion.** GitHub and GitLab both render a `suggestion` block as a one-click commit. The gap between "understands the fix" and "has applied the fix" is where most findings die. That last point is worth more than any detection improvement. A finding with a one-click fix gets fixed at a completely different rate from one with a paragraph of advice. ## Deterministic checks beat a language model here There is a strong pull toward putting an LLM in the review loop. In a pull request specifically, it is usually the wrong trade. A PR check runs on every push from every engineer, several dozen times a day. It needs to be: - **Fast.** Seconds. A check that takes two minutes gets merged around. - **Deterministic.** The same diff must produce the same comments. A bot that flags something on Tuesday and stays quiet on Wednesday for the same code destroys its own credibility, and it cannot be evidenced as a control that "operated consistently". - **Cheap.** It runs constantly. Pattern-based detection — secret formats with their real prefixes and entropy, unsafe API usage, dependency versions against an advisory database — is fast, deterministic, and free. Save the model for the parts where judgement genuinely helps: writing the explanation, or drafting a fix for a finding that is already confirmed. ## Reporting what changed, not what exists The most useful number on a PR comment is not "23 issues". It is: > **2 new · 1 fixed** since `main` That framing does three things. It tells the author what *they* introduced. It gives credit for what the branch cleaned up, which is the only mechanism that makes anyone volunteer to fix an old finding. And it makes the comment shrink to nothing on the majority of PRs that introduce no new issues — which is the honest outcome, and the thing that keeps the team reading the comment when it does say something. ## Rolling it out without a revolt **Week 1 — observe only.** Run the checks, post the comment, block nothing. Read what it produces yourself before anyone else has to. **Week 2 — cut the noise.** Turn off every rule that produced a false positive. Do this ruthlessly and before the team's opinion sets. One wrong block costs more trust than ten correct comments earn. **Week 3 — turn on the hard block, for secrets only.** One rule, the one nobody argues with. Let the team experience the bot being right. **Week 4 — widen carefully.** Add blocking rules one at a time, each with a visible override path. An override that requires a comment saying why is a control; an override that requires a Slack message to whoever owns the config is a bottleneck people route around. ## What CheckVibe does in a pull request Specifically, so this is checkable: - **Inline review comments** on the changed lines, with committable ```` ```suggestion ```` blocks where the fix is mechanical. - **New and closed counts** relative to the base branch, so the comment reflects the diff rather than the repository. - **Deterministic checks** — the AutoFix path is pattern-based by design, not model-generated, so the same diff produces the same output every time. - **Per-repository options**, so a monorepo and a marketing site do not have to share a policy. - **Write access is opt-in.** Posting review comments needs an explicitly granted write scope; connect read-only and it will still scan and report, it just will not comment. - **A patch export** you can `git apply` locally when you would rather not let a tool commit to your branch at all. - Findings that are *not* diff-scoped land in the shared queue with an owner and an SLA rather than on the review. PR review is on both team tiers, from $25 per seat per month with a five-seat minimum. [The pricing page](/pricing) has the rest. ## Frequently Asked Questions ### Should a security check block a merge? For a small number of near-certain findings, yes — a live credential in the diff is the clearest case, because after merge the fix is rotation plus history rewriting rather than deletion. For judgement calls like a route with no visible auth check, comment instead. Every blocking rule you add that produces one false positive costs more team trust than several correct comments earn back. ### How do you stop a PR security bot becoming noise? Scope it to the diff. Report only what this branch introduced or changed, and route everything the repository already had into a tracked queue with an owner and a deadline. A bot that comments on pre-existing findings during an unrelated review teaches the team to scroll past it, and a control nobody reads is worse than no control, because you will still report it as one. ### Is SAST in CI enough, or do you need scanning of the deployed app too? They find different things. Static analysis reads code paths and catches injection patterns, hardcoded secrets and unsafe API usage before merge. Scanning the deployed app catches what only exists at runtime: missing security headers, live TLS configuration, CORS as the server actually answers it, publicly readable database tables, and secrets that reached the shipped JavaScript bundle regardless of how they got there. Teams that run only one of the two have a predictable blind spot. ### Should an LLM review pull requests for security? Not as the detection layer. A PR check runs dozens of times a day and needs to be fast, cheap, and identical on identical input — a bot whose findings vary between runs cannot be trusted by engineers or evidenced as a control that operated consistently. Pattern-based detection gives you that. A model is better spent on explaining a confirmed finding or drafting a fix than on deciding what counts as one. ### What should a PR security comment actually contain? File and line, the evidence for the claim, the consequence the author might not know, and a committable suggestion where the fix is mechanical. The evidence matters most: "this is a live SendGrid key, `SG.` prefix, 69 characters" can be verified in seconds, while "possible hardcoded secret, confidence medium" asks the reader to take it on trust — and they will not. ### Does scanning pull requests require giving a tool write access to the repository? Only if you want it to comment. Read access is enough to clone, scan and report findings in your own dashboard. Posting review comments or opening fix branches needs an explicitly granted write scope, which is worth treating as a separate decision — and a patch you apply locally with `git apply` is a reasonable middle ground for teams that would rather no external tool committed to their branches. --- *CheckVibe posts inline, committable security suggestions on pull requests, scoped to the diff, on both team tiers. [See what teams get](/pricing), or [scan your deployed app free](https://checkvibe.dev) to see what runtime checks add on top.* --- ## How to Answer a Security Questionnaire Without Stalling the Deal *The questions enterprise buyers actually send small vendors, how to answer honestly when the answer is no, and what to prepare before the first one.* Published: 2026-08-31 | Reading time: 10 min read URL: https://checkvibe.dev/blog/security-questionnaire-answers The first enterprise security questionnaire arrives about a week after the deal starts looking real, it has between 80 and 300 questions, and it is due in five business days. The instinct is to answer everything "yes" and move on. Do not. Security questionnaires get read by people who compare your answers to your documentation, and a yes you cannot evidence turns a procurement step into a trust problem. The teams that clear these fastest are not the most secure ones — they are the ones who prepared five artefacts in advance and are comfortable writing "no, and here is the compensating control." ## What is actually being asked Strip the formatting and nearly every questionnaire — SIG Lite, CAIQ, a bank's bespoke spreadsheet, a one-page startup version — is asking the same six things. **1. Who can reach our data, and how do you know?** Access control, offboarding, least privilege, and whether anyone reviews the list. The follow-up is always "how often do you review it", and the honest answer for most small teams is "never", which is why this is the first thing to fix. **2. What happens when you are breached?** An incident response plan, a notification commitment with a number of hours in it, and who the contact is. Buyers care less about your plan being sophisticated than about it existing and having a name attached. **3. How do you find and fix vulnerabilities?** What you scan, how often, and your remediation windows by severity. Increasingly they ask for the *numbers*, not the policy — your on-time closure rate. See [remediation SLAs](/blog/vulnerability-remediation-sla). **4. How does code get to production?** Review requirements, branch protection, separation of environments, whether anyone can push straight to main. **5. Where does the data live and who else touches it?** Hosting regions, encryption at rest and in transit, your subprocessor list, and your data processing agreement. **6. Do you have a certification?** SOC 2 Type II, ISO 27001, or a credible date by which you will. This one question routes the rest: a valid report often collapses a 250-question spreadsheet into "please send the report." ## The five artefacts to prepare before the first one arrives Build these once and most questionnaires become an afternoon rather than a week. **A trust page.** One public URL listing hosting, subprocessors, encryption, certifications and status. Half of what a buyer asks is already public information about your stack — let them self-serve it. This also gets read by the *next* buyer, who never files a ticket at all. **A subprocessor list with a change policy.** Every third party that touches customer data, what they process, and where. Keep it in version control so its history is the evidence for "how do you notify us of changes." **A four-document policy set.** Information security, access control, vulnerability management (with the severity table in it), incident response. Two pages each. The set answers perhaps 40% of a typical questionnaire on its own. **A current access list.** Every human with production access, per system — including the ones nobody thinks of as production: the error tracker, the analytics tool, the CI provider, the DNS registrar. **A dated vulnerability record.** For a sample of findings: when detected, who owned it, when closed. Not a screenshot of a dashboard — a record with dates in it. This is the artefact almost nobody has, and the one that turns a soft "yes we scan regularly" into something a reviewer can verify. ## How to answer "no" Most questionnaires have a comment field next to every question. It exists precisely so you can answer honestly, and reviewers read it. The structure that works: **no, here is what we do instead, here is when that changes.** > **Do you enforce SSO with SAML for all workforce applications?** > > No. We are a seven-person team on Google Workspace with mandatory 2FA and hardware keys for anyone with production access. Application access is provisioned individually and reviewed quarterly; the current list is maintained in version control. SAML SSO is on our roadmap for Q2 2027, driven by headcount rather than by this review. That answer will pass at most companies. "Yes" — from a seven-person team that plainly does not run an identity provider — will not, because the reviewer's next question is for evidence. Two rules: **Never claim a certification you do not hold.** "SOC 2 compliant" means nothing; "SOC 2 Type II report, observation window January–June 2026, available under NDA" means something. Reviewers know the difference and treat the first as a warning sign. **Never claim a control you cannot evidence.** If a question asks whether you scan for vulnerabilities and you cannot produce dated detection and closure records, the honest answer is what you actually do and when it started. ## The eight questions that most often stall a small vendor From what small teams get stuck on, roughly in order: | Question | The realistic answer | | --- | --- | | Do you have SOC 2 Type II? | If not: name the target window and what you have already collected. A credible date beats a vague yes | | Do you perform annual penetration testing? | Most small teams do not. Say so, and describe continuous automated scanning plus your remediation windows as the compensating control | | Do you enforce SSO/SAML? | Usually no below ~20 people. Describe 2FA enforcement, hardware keys for production access, and quarterly reviews | | Do you have a documented incident response plan? | Write it — two pages. There is no acceptable substitute and it is a day of work | | What is your breach notification timeline? | Commit to a number. 72 hours is the common contractual standard; do not promise 24 unless you have on-call | | Do you encrypt data at rest? | Almost certainly yes via your database provider. Name the provider and the mechanism rather than just ticking the box | | Do you maintain an audit log of administrative actions? | Say whether it is append-only. A log an admin can edit is a log a reviewer will discount | | Do you review access quarterly? | If you have never done one, do one this week, then answer yes with a date | ## Turn the answers into a reusable answer bank The compounding move is to keep every answer you have ever written, keyed by the question's meaning rather than its wording. The same six themes come back phrased forty different ways; a bank of 60–80 canonical answers covers most of a new 200-question spreadsheet by search-and-adapt. Two disciplines keep it from rotting: - **Date every answer.** An answer written eighteen months ago about a team that has doubled is a liability, not a shortcut. - **Attach the evidence path.** Next to each answer, where the proof lives. When a reviewer asks — and on the questions that matter they will — you are not re-deriving it under time pressure. ## Where a scanner genuinely helps, and where it does not Being precise, because the honest scope here is narrower than most vendors imply. **It helps with:** the vulnerability-management questions, which are the ones where reviewers increasingly ask for numbers rather than prose. Dated detection and closure records, remediation windows by severity, an on-time rate you can state. Also the "do you monitor your external attack surface" family — TLS configuration, security headers, exposed credentials, publicly readable data stores. **It does not help with:** access reviews, incident response, HR controls, vendor management, business continuity, or your risk register. Those are writing and process. Any tool implying otherwise is selling you a checklist with a logo on it. For the part it does cover, what CheckVibe gives a team is the record rather than the dashboard: SLA policies with due dates materialised at first detection, shared triage with assignment and an activity trail, and an append-only audit log the database refuses to update — 180 days on Team Basic, a year on Team Advanced. Team Advanced adds SOC 2 and ISO 27001 evidence reporting, with reports frozen and hashed at generation, and controls it cannot evidence marked as unsupported rather than quietly omitted. Team plans start at $25 per seat per month with a five-seat minimum. [The pricing page](/pricing) has the split, and [SOC 2 evidence for small teams](/blog/soc-2-evidence-for-small-teams) covers what an auditor asks for in more detail. ## Frequently Asked Questions ### How long does a security questionnaire take to complete? The first one takes three to five working days for a small team, because you are writing the policies as you go. With a trust page, a four-document policy set, an access list and an answer bank prepared, subsequent ones take two to four hours. That gap is the entire argument for preparing the artefacts before a deal depends on them. ### Can you answer "no" to a security questionnaire question? Yes, and it is usually the right move when it is true. Use the comment field: no, here is the compensating control we run instead, here is what would change that. A documented no with a real alternative passes review at most companies; an unevidenced yes fails it, because the reviewer's next step is to ask for proof. ### Do you need SOC 2 to sell to enterprises? Not always, but it shortens everything. Without a report you get the long questionnaire and a security review call; with one, many buyers accept the report plus a short supplemental set. Below roughly $50k annual contract value, buyers are often willing to accept a credible target date and a strong questionnaire. Above it, the report usually becomes a hard requirement. ### What is the difference between SIG and CAIQ? SIG (Standardized Information Gathering) is a Shared Assessments questionnaire, widely used in financial services, with a shorter SIG Lite variant. CAIQ (Consensus Assessments Initiative Questionnaire) comes from the Cloud Security Alliance and maps to their Cloud Controls Matrix; a completed CAIQ can be published to the CSA STAR registry. Both ask the same underlying six things, so an answer bank organised by theme serves either. ### What should a trust page contain? Hosting provider and regions, encryption at rest and in transit, your subprocessor list, certifications and their status, your security contact and disclosure policy, and a link to a live status page. Keep it public and current. It answers a meaningful share of most questionnaires before anyone files one, and the buyers who read it and never ask are the point. ### How do you answer questions about penetration testing when you have never had one? State it plainly, then describe what you do instead: continuous automated scanning of the deployed application with a stated frequency, remediation windows by severity, and your on-time closure rate. Add whether a pen test is planned and when. Reviewers accept compensating controls far more readily than they accept a yes that unravels when they ask for the report. --- *The vulnerability-management section of a questionnaire is the one you can answer with a number. CheckVibe records detection and closure dates, SLA windows and an append-only audit trail on both team tiers. [See what teams get](/pricing), or [scan your app free](https://checkvibe.dev).* --- ## A Security Triage Workflow for Teams Without a Security Engineer *How a small team turns a scanner's output into owned, deadlined work: who triages, what gets closed on sight, and the queue design that stops backlogs.* Published: 2026-08-31 | Reading time: 10 min read URL: https://checkvibe.dev/blog/security-triage-workflow-for-teams Nobody abandons a security backlog on purpose. It happens because the queue has no owner, every item looks equally urgent, and there is nowhere to put "we are not fixing this." Fix those three things and triage takes twenty minutes a week. Leave them and you get the familiar shape: a dashboard with a four-figure number on it that everyone has agreed not to look at. This is a workflow for a team of three to fifteen engineers with no dedicated security person. ## Rotate one triage owner per week Not a committee, not "whoever notices". One name, one week, in a rotation everyone takes a turn in. The rotation matters more than the role. A permanent security owner on a small team becomes a bottleneck, then a single point of knowledge, then a leaver. A rotation spreads the context, and — this is the underrated part — it makes everyone briefly responsible for the noise they would otherwise ignore, which is the fastest route to tuning the scanner properly. The triage owner's job is not to fix anything. It is to make sure every new finding leaves the queue in one of four states within the week: - **Assigned**, with a name and a deadline. - **Excepted**, with a reason, an approver and a review date. - **Duplicate** of something already tracked. - **False positive**, with the rule tuned so it does not come back. That last state is the one teams skip, and it is why queues grow. Closing a false positive without changing the rule guarantees you will triage the same thing next month. ## Sort by exposure first, severity second Severity alone is a bad sort order for a small team, because it answers "how bad if exploited" and ignores "how reachable is it." Sort on two axes: | | Publicly reachable | Behind auth | Internal only | | --- | --- | --- | --- | | **Critical / High** | Today | This week | This sprint | | **Medium** | This week | This sprint | Backlog | | **Low** | This sprint | Backlog | Close or except | A medium-severity issue on an unauthenticated production endpoint outranks a high-severity one behind an admin login four people hold. Every experienced responder does this intuitively; writing it down is what lets a rotating owner do it without the experience. Two findings jump the table entirely: - **A live exposed credential.** Rotate now, measured in hours. Not a queue item. - **Publicly readable customer data.** A database table answering to the public key, a storage bucket listing, an unauthenticated endpoint returning records. Same urgency. ## Give every finding one of five states More states than these and the board becomes an argument about process. 1. **New** — seen, not yet decided. The triage owner's inbox. 2. **Accepted** — real, has an owner, has a deadline. 3. **Excepted** — real, deliberately not scheduled. Reason, approver, review date. 4. **Fixed** — remediated and confirmed gone by a subsequent scan. 5. **Not applicable** — false positive, with the rule tuned. The distinction that carries weight is **Excepted** versus overdue. A queue with fifteen documented exceptions and zero undocumented overdue items is a functioning process. A queue with zero exceptions and forty overdue items is the same team, worse informed — and it is the version that produces audit findings, because the overdue count has stopped meaning anything and nobody reads it. An exception needs four fields: why, who approved, when, and when it is reviewed again. Always a date, never "indefinitely". A quarterly pass over expired exceptions takes ten minutes and stops the exception list becoming its own graveyard. ## Where the queue should live Findings belong where the work already is. If your team plans in Linear and triages security in a separate dashboard, one of the two will be abandoned within a month, and it will be the one that is not attached to anyone's sprint. Two ways to do that honestly: **Sync to the tracker.** Findings become issues in Jira or Linear, statuses flow both ways, and closing the issue closes the finding. The detail that decides whether this works: map on the status *category* — to do, in progress, done — never on the status name, because names are per-project free text and two teams in the same company will not match. Also give the sync an echo guard, or your own push comes back as a foreign change and the two systems fight. **Keep one queue and link out.** Triage in the security tool, link the tracker issue on the finding, and let the deadline live in one place. Simpler, and better if only a subset of findings ever become sprint work. What does not work is maintaining both by hand. One of them is always lying, and it is usually the one you would show a buyer. ## Start the clock at detection The measurement that decides whether any of this is real: **the deadline runs from when the finding was first detected, not from when someone triaged it.** If triage starts the clock, a week of ignoring the queue is free, and your on-time rate measures your triage habits rather than your remediation. Materialise the due date on first sight and never recompute it — a deadline that moves when you edit the policy silently rewrites every number you have already reported. [Remediation SLAs](/blog/vulnerability-remediation-sla) goes through the mechanics. ## The weekly twenty minutes A shape that survives a busy sprint: 1. **New findings since last week** (10 min). Each one leaves as assigned, excepted, duplicate or false positive. 2. **Overdue, excluding exceptions** (5 min). Two questions per item: is it still real, and does it need a different owner. 3. **Exceptions past their review date** (3 min). Renew with a new date, or move to accepted. 4. **Reopens** (2 min). Findings marked fixed that came back. A high reopen rate means "fixed" is being used to mean "closed the ticket", which is worth catching early. Then post the four numbers where the team sees them: on-time closure rate by severity, median time to remediate, count overdue excluding exceptions, and mean time to triage. That last one is the leading indicator — when it climbs, breaches follow. ## Cut the noise before you scale the process A team drowning in triage usually has a tuning problem, not a capacity problem. Before adding process: - **Turn off rules that have never produced a real finding.** Ruthlessly. A rule with a 100% false-positive rate over three months is not conservative, it is a tax. - **Deduplicate by fingerprint, not by title.** Findings whose identity includes a version number produce a fresh row on every patch bump, and a single misconfiguration across forty crawled pages should be one item, not forty. - **Separate the deployed-app queue from the repository queue.** They have different owners, different fix shapes and different cadences. - **Route pre-existing findings out of pull requests.** A PR bot commenting on the repository's history rather than the branch's diff teaches everyone to scroll past it. See [security review in pull requests](/blog/pull-request-security-review). ## What CheckVibe provides For the parts of this that are product rather than process: - **Shared triage** on both team tiers — assignment, comments and an activity trail, with every row resolving through the account rather than the acting user. (An early version of ours got this wrong in an instructive way: rows were keyed to whoever was looking, so a five-seat team had five private queues that each looked empty to everyone else.) - **`client_viewer`** as a read-only seat, for a stakeholder who should see the queue and change nothing in it. - **SLA policies** with due dates materialised at first detection and never recomputed. - **Slack, Microsoft Teams and signed webhooks** for assignment and breach alerts, addressed to a person rather than a room. - **Two-way Jira and Linear sync** on Team Advanced, mapping on status category with an echo guard. - **An append-only audit log** the database refuses to update — 180 days on Team Basic, a year on Team Advanced. Team plans start at $25 per seat per month with a five-seat minimum. [The pricing page](/pricing) has the full split. ## Frequently Asked Questions ### Who should triage security findings on a team with no security engineer? A rotating weekly owner, one engineer at a time, taken from the whole team. A permanent owner on a small team becomes a bottleneck and then a single point of knowledge; a rotation spreads context and makes everyone briefly responsible for the noise they would otherwise ignore, which is what gets the scanner tuned. The owner decides and assigns — they do not do the fixing. ### How do you stop a security backlog from growing? Three things, in order: give the queue one named owner per week, sort by exposure before severity so the list has a real top, and provide a documented exception path so items you have deliberately chosen not to fix leave the overdue count. Backlogs grow when every item looks equally urgent and there is nowhere to record a decision not to act. ### Should security findings live in Jira or in a separate tool? Wherever the team already plans, or synced to it. A separate dashboard that is not attached to anyone's sprint gets abandoned inside a month. If you sync, map on the status category — to do, in progress, done — rather than the status name, because names are per-project free text, and add an echo guard so your own writes do not come back as foreign changes. ### What is the difference between an exception and an overdue finding? An exception is a recorded decision — why it is accepted, who approved it, when, and when it gets reviewed again. An overdue finding is an absence of a decision. Auditors and enterprise buyers read a queue with documented exceptions and no undocumented overdue items as a working process; the reverse pattern is what generates findings, because the overdue count has stopped carrying information. ### How often should a small team triage security findings? Weekly, for about twenty minutes: new findings, overdue items excluding exceptions, exceptions past their review date, and reopens. Daily is unnecessary for anything except live exposed credentials and publicly readable customer data, which should page immediately rather than wait for a queue. Monthly is too slow — the backlog gets large enough between sessions that triage stops feeling finishable. ### What does a high reopen rate mean? That findings are being closed rather than fixed. If a subsequent scan finds the same issue again, either the fix did not address the cause, it was reverted, or someone marked it done to clear the board. Track it as its own number: it is the cheapest available check on whether your remediation metrics describe reality. --- *CheckVibe gives a team one shared queue with assignment, SLA deadlines from first detection, and an append-only audit trail. [See what teams get](/pricing), or [run a free scan](https://checkvibe.dev) to see what would land in it today.* --- ## SOC 2 Evidence for Small Engineering Teams: What Auditors Actually Ask For *What a SOC 2 auditor actually asks a five-person engineering team for, which controls you can evidence automatically, and which ones need a human.* Published: 2026-08-31 | Reading time: 11 min read URL: https://checkvibe.dev/blog/soc-2-evidence-for-small-teams A SOC 2 auditor does not want your security tooling. They want proof that a control operated, continuously, over a window of time — and the proof has to be dated, attributable, and impossible to have edited after the fact. That single sentence is the whole difference between "we are secure" and "we passed SOC 2". Most small engineering teams have the first and none of the second, and they discover the gap about four weeks into a Type II observation window, when someone asks them to produce evidence for a period that has already ended. This is what auditors ask for, what you can evidence automatically, and what still needs a person. ## Type I vs Type II: the distinction that decides your workload - **SOC 2 Type I** is a point-in-time report. It says a control was *designed* correctly on one date. You can get one in weeks, and it is worth roughly what that sounds like to a buyer who has read a few. - **SOC 2 Type II** covers an *observation window*, typically 3 to 12 months, and says the control actually *operated* throughout it. This is the one enterprise procurement asks for. The practical consequence: Type II evidence cannot be manufactured at the end. If your window starts in January and you begin collecting in October, you have a nine-month hole nothing will fill. Start the collection *before* the window, not during it. ## The five evidence categories a small team gets asked about Every framework has its own control numbering, and every auditor has their own request list. Underneath, small engineering teams get asked for the same five things. ### 1. Vulnerability management The request sounds like: *"Show us that identified vulnerabilities are tracked to resolution within defined timeframes."* What satisfies it: - A written policy that states the remediation deadline per severity (critical in N days, high in N days, and so on). - A record showing, for a sample of findings in the window, when each was **first detected**, when it was triaged, who owned it, and when it was closed. - Evidence that the deadline came from the policy and was not backfilled. The detail that trips teams up is *first detected*. Auditors sample findings and check the clock started when the issue became known, not when someone got around to triaging it. If your tracker records "created" as the day an engineer manually filed a ticket, every SLA in your report is measured from a date you chose. That is the finding. We wrote up how to define those windows in [vulnerability remediation SLAs](/blog/vulnerability-remediation-sla). ### 2. Change management The request: *"Show us that code changes are reviewed and approved before reaching production."* For most small teams this is the easiest one, because GitHub or GitLab already keeps it: branch protection requiring a review, the PR record itself, and the merge commit. What auditors add is *evidence the rule could not be bypassed* — so export the branch protection settings, not just the PRs. A screenshot of a setting on the day of the audit does not prove it was on in March. If you can also show that security review happened *inside* the PR rather than in a separate quarterly sweep, this control and the vulnerability-management one start sharing evidence. See [security review in pull requests](/blog/pull-request-security-review). ### 3. Access management The request: *"Show us who had access to production, that access was authorised, and that it was removed on offboarding."* Evidence: - A current list of every human with production access, per system. - A dated record of each grant and each revocation in the window. - Proof of a periodic review — usually quarterly — where someone looked at the list and confirmed it. Small teams fail this one on offboarding, and on the systems nobody thinks of as production: the error tracker, the analytics tool, the CI provider, the DNS registrar. Write the list once. Keep it in version control so its history *is* the evidence. ### 4. Monitoring and alerting The request: *"Show us that you would detect a security-relevant event, and that someone responded."* Evidence: alert configuration, plus a sample of actual alerts and what happened next. An empty incident log is not automatically good news — auditors read it as "no detection" as easily as "no incidents". A handful of real alerts, triaged and closed with a note, is stronger evidence than silence. ### 5. Audit trail The request: *"Show us a record of security-relevant administrative actions, and that the record cannot be altered."* This one is binary. Either your system writes an append-only log or it does not. A table an admin can `UPDATE` is not an audit trail, and an auditor who asks the right question will find that out. ## What can be evidenced automatically, and what cannot Here is the honest split. Roughly half of a small team's SOC 2 evidence can come out of tooling. The rest is writing, and no product removes that. | Control area | Automatable | Needs a human | | --- | --- | --- | | Vulnerability management | Detection dates, severity, owner, closure dates, SLA breaches | The policy that defines the deadlines | | Change management | PR records, review approvals, branch protection export | The written change policy and exception process | | Access management | Current access lists, grant and revoke events | Authorisation records, quarterly review sign-off | | Monitoring | Alert config, alert history, response timestamps | The incident response plan and post-incident notes | | Audit trail | The log itself | Retention policy, who may read it | | Risk assessment | Nothing | All of it — the register, the ratings, the decisions | | Vendor management | Nothing | The vendor list, reviews, and DPAs | | HR controls | Nothing | Background checks, security training records, policy acknowledgements | The bottom three rows are why "compliance automation" platforms cost what they cost: they are mostly a document workflow with a checklist attached. If you have a five-person team, you can write those documents yourself in a week. What you cannot do yourself, cheaply, is reconstruct nine months of detection and remediation dates you never recorded. **So the priority is obvious: start recording the dated, machine-generated evidence today. Write the policies later — you can always write a policy retroactively, and you can never backfill a timestamp honestly.** ## Freeze your evidence, or it is not evidence An evidence report that regenerates from live data every time you open it is a dashboard, not evidence. When an auditor asks for the vulnerability report covering March, and the report re-queries today's database, you have handed them something that will look different tomorrow. What a defensible report looks like: 1. **Generated for a fixed window** and stored as generated — not recomputed on view. 2. **Hashed.** A SHA-256 of the report content, recorded at generation time, so both sides can prove the file was not edited afterwards. 3. **Attributable.** Who generated it, and when. 4. **Honest about gaps.** A control catalogue that silently omits what it cannot evidence is worse than useless; it teaches you the gap does not exist until an auditor finds it. That last point matters more than it sounds. When we built compliance reporting at CheckVibe, the catalogue explicitly marks controls it *cannot* evidence as unsupported rather than quietly dropping them. Knowing that four of your controls have no automated evidence is the useful output. A green checkmark you did not earn is a liability you will discover in the audit. ## A 30-day starting plan for a five-person team **Week 1 — stop the bleeding.** Turn on whatever records dates. Get a scanner running on a schedule so findings have a first-detected timestamp. Turn on your provider's audit log. Export your current access list to a repo. **Week 2 — write the four documents that unblock everything.** An information security policy, an access control policy, a vulnerability management policy with the SLA table in it, and an incident response plan. Two pages each. They will be imperfect. Imperfect and dated beats perfect and absent. **Week 3 — close the change-management loop.** Branch protection on, reviews required, security checks running in the PR rather than on a quarterly cadence. Export the settings. **Week 4 — pick the window and dry-run it.** Choose the Type II observation window start date. Generate every report you would hand an auditor, for the previous month, as a rehearsal. You will find the holes now, when they cost a week, rather than in month nine. ## What this looks like in CheckVibe To be precise about what is and is not covered, because vague compliance claims are exactly the problem: - **Both team tiers** carry shared triage with assignment and an activity trail, SLA policies with due dates materialised at first detection, notification destinations (Slack, Microsoft Teams, signed webhooks), and an append-only audit log enforced at the database level — the write is refused even by the service role, and the only deletion path refuses anything inside 30 days. - **Team Advanced** adds two-way Jira and Linear sync, and SOC 2 / ISO 27001 evidence reporting: frozen reports with a SHA-256 over the content, exported as HTML, with unevidenceable controls marked as such. Audit retention runs a full year on Advanced, matching a 12-month Type II observation window. Team plans start at $25 per seat per month with a five-seat minimum; the compliance reporting sits on Team Advanced at $50 per seat. [The pricing page](/pricing) has the full split. None of that writes your risk register, your vendor reviews, or your training records. Nothing does. ## Frequently Asked Questions ### How long does SOC 2 take for a five-person team? Type I is realistically 6 to 10 weeks from a standing start, most of which is writing policies and closing obvious gaps. Type II adds the observation window itself — a minimum of three months, though enterprise buyers increasingly ask for six or twelve. The window is wall-clock time you cannot compress, which is why the date you start *collecting evidence* matters more than the date you start the project. ### Do I need a compliance platform for SOC 2? No, but you need somewhere the dated evidence lands. A five-person team can maintain the policy documents in a repository and pull evidence from the tools it already runs. Compliance platforms mostly sell the document workflow plus integrations that collect the same evidence; they are worth it when the coordination cost exceeds the licence cost, which usually happens somewhere north of 20 engineers. ### What is the difference between SOC 2 and ISO 27001? SOC 2 is an attestation report from a US CPA firm against the AICPA Trust Services Criteria; you receive a report describing your controls and the auditor's opinion. ISO 27001 is an international certification against a standard, focused on having an information security management system. The underlying evidence overlaps heavily — access reviews, vulnerability management, change control — so teams that do one can usually reach the other without starting over. ### Can a vulnerability scanner satisfy SOC 2 on its own? No. A scanner produces detection evidence, which covers part of one control area. SOC 2 asks about access management, change management, incident response, risk assessment, vendor management and HR controls as well. What a scanner can do — and what nothing else does as well — is prove *when* something was found, which is the timestamp every remediation SLA in your report is measured from. ### What does an auditor mean by "operating effectiveness"? That the control did its job throughout the window, not that it existed. For vulnerability management, design effectiveness is having a policy that says criticals get fixed in seven days. Operating effectiveness is a sample of actual critical findings from the window, each showing detection, ownership and closure inside seven days — or a documented exception explaining why not. ### Is an exception the same as a failure? No, and teams over-correct on this. A documented risk exception — this finding is accepted, here is why, here is who approved it, here is the review date — is a functioning control. An undocumented overdue finding is a failure. Auditors are looking for a process that handles reality, not for a report with no red in it. --- *Running a team on CheckVibe? Shared triage, SLA policies and an append-only audit log ship on both team tiers, with SOC 2 and ISO 27001 evidence reporting on Team Advanced. [See what teams get](/pricing), or [scan your app free](https://checkvibe.dev) to see what a first evidence run would find.* --- ## Vulnerability Remediation SLAs: Setting Deadlines a Small Team Can Actually Hit *How to set remediation deadlines by severity, when the clock should start, and why measuring from triage instead of detection inflates every number.* Published: 2026-08-31 | Reading time: 10 min read URL: https://checkvibe.dev/blog/vulnerability-remediation-sla A remediation SLA is two decisions: how long each severity gets, and when the clock starts. Teams argue endlessly about the first and get the second wrong, which is what actually breaks the numbers. If the clock starts when someone triages a finding, then a team that ignores its queue for three weeks reports the same on-time percentage as a team that fixes everything the day it appears. The metric measures your triage habits, not your remediation. Auditors know this, buyers' security questionnaires increasingly ask about it, and it is the first thing worth fixing. ## Start the clock at first detection, not at triage **The clock starts the moment the finding became knowable to you.** For a scanner, that is the scan that first surfaced it. For a dependency advisory, the moment the advisory matched your lockfile. For a report from outside, the moment it arrived in your inbox. Three consequences follow, and all three are the point: 1. **Ignoring the queue costs you.** Time spent not looking at a finding is time on the clock. That is the incentive you want. 2. **Your numbers become comparable** between quarters, and between you and the SLA you promised a customer. 3. **The date is machine-generated**, so it survives an auditor asking where it came from. The counter-argument is real: a team returning from a long backlog will breach a lot of SLAs at once. That is not a reason to move the clock. It is a reason to declare a starting baseline — everything open on the day the policy takes effect gets a one-time exception with an agreed catch-up date — and to measure honestly from there. ## Materialise the due date; never recompute it The second implementation detail that decides whether your history is worth anything: **write the due date to the row the first time you see the finding, and never derive it again.** If the due date is computed on read from the current policy, then editing the policy rewrites history. Loosen "critical" from 7 days to 14 and every past breach silently becomes compliant. Every report you already sent a customer is now inconsistent with the system that produced it. This is not hypothetical — it is the default behaviour of most homegrown trackers, because computing on read is the obvious way to write it. Materialising the deadline means a policy change applies to findings discovered *after* the change, which is also the only version an auditor will accept. ## A severity table that survives contact with a five-person team Published frameworks tend to assume a security function exists. These are the windows small engineering teams actually hit, and the reasoning behind each. | Severity | Remediate within | Why this number | | --- | --- | --- | | Critical | 7 days | Exploitable remotely with no auth, or an exposed live credential. This is a drop-everything item; a week is generous and exists only so a weekend does not breach it | | High | 30 days | Real impact but needs a precondition — a valid session, a specific configuration. Fits inside one sprint plus one carry-over | | Medium | 90 days | Worth fixing, defensible to schedule. A quarter is long enough to batch into planned work | | Low | Best effort, reviewed quarterly | Setting a deadline you will miss on purpose teaches the team the whole table is decorative | | Informational | No deadline | Track it, do not schedule it | Two rules make this table work in practice: **Exposed credentials get their own row, outside the severity ladder.** A live API key in a client bundle is not "critical, 7 days" — it is *rotate now*. Detection to rotation should be hours. Keep it as its own class or your critical bucket fills with things that are urgent in genuinely different ways. **Publicly-reachable beats theoretically-severe.** A medium-severity issue on an unauthenticated production endpoint deserves attention before a high-severity one behind an admin login used by four people. If your tracker cannot express that, add an "exposure" field and sort on both. ## Exceptions are a feature, not a failure The single biggest reason SLA programmes collapse is that there is nowhere to put "we are not fixing this, and that is fine." Some findings genuinely should not be fixed on schedule: a dependency CVE in a code path you do not call, a header missing on an endpoint that serves one static file, a finding whose fix costs a fortnight and whose impact is a paragraph. Without a documented exception path, those items sit permanently overdue, the overdue count becomes noise, and the team stops reading it. A usable exception needs four fields and no more: - **Why** it is accepted, in one sentence a non-engineer can follow. - **Who** approved it. - **When** it was approved. - **When it gets reviewed again** — always a date, never "indefinitely". An auditor reading a report with twelve documented exceptions and zero undocumented overdue items sees a working process. A report with zero exceptions and forty overdue items is the one that generates findings. ## The four numbers worth reporting Most vulnerability dashboards report open counts, which mostly tell you how loud your scanner is. These four tell you whether the process works: 1. **On-time closure rate, by severity.** The percentage of findings closed inside their materialised deadline. Split by severity or the critical signal drowns in low-severity volume. 2. **Median time to remediate, by severity.** Median rather than mean — one nine-month straggler should not swing the number. 3. **Currently overdue, excluding documented exceptions.** The single number for a weekly standup. 4. **Mean time to triage.** Detection to first human decision. If this is climbing while closure rate holds, you are about to breach in volume, and this is the leading indicator. A fifth, if you can get it: **reopen rate**. Findings marked fixed that the next scan finds again. A high reopen rate means "fixed" is being used to mean "closed the ticket." ## Wiring it into the work, not beside it An SLA nobody sees is an SLA nobody hits. Three integration points, in order of impact: **Into the tracker.** Findings should arrive in Jira or Linear where the work already is, with the due date on the issue, and status should sync both ways. If closing the Jira issue does not close the finding, someone is maintaining two systems and one of them is lying. (Two-way sync needs care: map on the status *category* — to do, in progress, done — never on the status name, because those are per-project free text and will differ across two teams in the same company.) **Into the pull request.** The cheapest possible remediation is the one that happens before merge, where the author still has the context. A finding raised in review never enters the SLA queue at all. See [security review in pull requests](/blog/pull-request-security-review). **Into a channel with a name on it.** Breaching alerts to Slack or Teams, addressed to the assignee rather than to a room. "Someone should look at this" reliably means nobody will. ## What CheckVibe does with this Because a post about honest measurement should be specific about its own product: - **SLA policies** on both team tiers. Due dates are **materialised at first detection** and never recomputed, exactly for the reason in the second section — a deadline that moves when the policy is edited invalidates every historical number. - **The clock starts when we first saw it**, not when someone triaged it, so ignoring the queue cannot reset a deadline. - **Shared triage** with assignment, comments and an activity trail, so the answer to "who owns this" is a name, not a guess. - **Slack, Microsoft Teams and signed webhook** destinations for breach and status alerts. - **Two-way Jira and Linear sync** on Team Advanced, mapping on status category rather than status name. - **An append-only audit log** — 180 days on Team Basic, a year on Team Advanced — that the database refuses to update, so the remediation history holds up when someone asks where the dates came from. Team plans are $25 per seat per month, minimum five seats, with Jira/Linear sync and compliance reporting on Team Advanced at $50. Details on [the pricing page](/pricing). ## Frequently Asked Questions ### When should the remediation clock start? At first detection — the scan, advisory match, or report that first made the finding knowable — not at triage and not at ticket creation. Starting at triage means a team that ignores its backlog reports the same on-time rate as one that fixes everything immediately, because the delay happens before the clock starts. Detection is also machine-generated, which is what makes it defensible in an audit. ### What are reasonable remediation SLAs for a small team? Seven days for critical, 30 for high, 90 for medium, best-effort with a quarterly review for low, and no deadline for informational. Keep exposed credentials outside the ladder entirely, measured in hours to rotation. These windows are achievable for a five-person team without a dedicated security engineer, which matters more than matching a stricter published standard you will miss every month. ### Should the due date be stored or calculated? Stored, written once when the finding is first seen. A due date calculated from the current policy on every read means editing the policy silently rewrites your entire remediation history — past breaches become compliant, and every report you already sent disagrees with the system. Materialising it means policy changes apply going forward only, which is the only interpretation an auditor accepts. ### How do you handle findings you have decided not to fix? Record an exception with four fields: the reason, the approver, the approval date, and a review date. Never "indefinitely". A documented exception is a functioning control; an undocumented finding sitting permanently overdue is a failure, and worse, it makes the overdue count meaningless so the team stops reading it. ### What is a good on-time closure rate? Above 90% for critical and high, measured from detection, is a healthy programme for a small team. The absolute number matters less than the trend and the split: 95% overall can hide 60% on criticals if low-severity volume dominates. Always report by severity, and always alongside the count of undocumented overdue items. ### Do vulnerability SLAs matter outside compliance? Yes — they are increasingly a line item in enterprise security questionnaires and in the security addendum of B2B contracts. Buyers ask for your severity table and your on-time rate. A team that can answer with a number from a system, rather than a paragraph of reassurance, closes those reviews measurably faster. --- *CheckVibe ships SLA policies with due dates materialised at first detection, shared triage, and an append-only audit log on both team tiers. [See what teams get](/pricing), or [run a free scan](https://checkvibe.dev) to see what would land in the queue today.* --- ## How to Tell If a Website Is Vibe Coded: 7 Signals to Check *Seven signals that reveal whether a website was built with AI coding tools, plus the exact browser and DNS checks to confirm each one.* Published: 2026-08-07 | Reading time: 9 min read URL: https://checkvibe.dev/blog/how-to-tell-if-a-website-is-vibe-coded **The fastest way to tell if a website is vibe coded: check the URL for a default platform subdomain like `.lovable.app` or `.vercel.app`, view the page source for an unchanged template title such as `Vite + React`, and check the response headers for missing security headers. Three checks, under a minute.** None of those signals is proof on its own. Vibe coding — building software by describing it to an AI assistant rather than writing every line — leaves fingerprints, but plenty of hand-written sites sit on Vercel with a default favicon, and plenty of AI-assisted codebases have been reviewed line by line before shipping. What you are really detecting is a *pattern*: polished product surface, zero production hardening underneath. Here are the seven signals, ordered from fastest to most conclusive, with the exact check for each. ## The 7 Signals ### 1. Hosting Fingerprints The single fastest tell is the domain itself. AI app builders deploy to a default subdomain, and a large share of projects never move off it. Watch for: - `*.lovable.app` — Lovable - `*.vercel.app` — Vercel (the default target for v0, Cursor, and most Next.js output) - `*.netlify.app` — Netlify - `*.replit.app` / `*.repl.co` — Replit - `*.bolt.host` — Bolt - `*.web.app` / `*.firebaseapp.com` — Firebase Hosting - `*.pages.dev` — Cloudflare Pages **How to check:** look at the URL bar. If the site sits on a custom domain, resolve where it actually points: ```bash dig +short CNAME app.example.com # cname.vercel-dns.com. -> Vercel # apex-loadbalancer.netlify.com. -> Netlify ``` Response headers work too, and they survive custom domains: ```bash curl -sI https://example.com | grep -iE 'server|x-vercel|x-nf-request-id|x-powered-by' ``` A custom domain that CNAMEs to a builder platform is a strong hint. A custom domain on a generic CDN tells you nothing either way. ### 2. Platform Badges and Template Defaults Builder platforms brand their free output, and template metadata is the last thing anyone remembers to change. Look for a floating "Edit with Lovable" badge, a "Made in Bolt" chip, or a Replit ribbon — usually pinned bottom-right. Then check the details nobody edits: - The `` still reads `Vite + React`, `Create Next App`, or `My App` - The favicon is the framework's own — Vite's lightning bolt, Next.js's triangle, or the generic React atom - `og:image` is missing entirely, so link previews render as a blank card - The meta description is the scaffold's placeholder text **How to check:** press `Cmd+Option+U` (macOS) or `Ctrl+U` (Windows/Linux) to view source, then search the raw HTML for `title`, `og:image`, `lovable`, and `bolt`. A production-grade site has a written title, a real description, and a custom OG image. A vibe-coded one usually has at most one of the three. ### 3. Bundle and Source Signals The JavaScript bundle carries the build toolchain's signature. **How to check**, step by step: 1. Open DevTools (`F12` or `Cmd+Option+I`) 2. Go to the **Network** tab and reload the page 3. Filter to **JS** Then read the filenames. Vite ships hashed chunks like `assets/index-a1b2c3d4.js`. Next.js serves everything under `/_next/static/chunks/`. Create React App uses `static/js/main.<hash>.js`. Unchanged defaults mean nobody customized the build. Next, search the loaded source: 1. Open the **Sources** tab 2. Press `Cmd+Option+F` / `Ctrl+Shift+F` to search across all loaded files 3. Search for `supabase.co`, `firebaseio.com`, and `apiKey` Finding a Supabase project URL and an anon key in the bundle is normal and expected — the anon key is designed to be public, and Row Level Security is what actually protects the data. What it tells you is the stack. The genuinely alarming variants are a `service_role` key, a `sk_live_` Stripe key, or an OpenAI key in client-side JavaScript, all of which show up in AI-generated code far more often than they should. In the DOM itself, wall-to-wall Tailwind utility classes on every element is another builder-default tell. ### 4. AI Copy Patterns Read the page as a reader, not a developer. AI-drafted marketing sites converge on a recognizable shape: - A hero headline built from an abstract verb plus a buzzword: "Transform your workflow with AI-powered insights" - Em-dash-heavy body copy with a consistent rhythm and no specifics - The same section order every time: hero, three feature cards with matching icons, a testimonial row, pricing, closing CTA - Testimonials from invented people with placeholder-service avatars - Leftover `lorem ipsum`, "John Doe", or "Company Name" in a footer or secondary page This is the weakest signal here. Human marketers have shipped from the same template for a decade, and good writers use em dashes. Treat it as corroboration, never as evidence on its own. ### 5. Missing Production Basics This is where the pattern gets diagnostic. AI assistants generate features because features are what you asked for. They do not generate the invisible operational layer you did not ask for. **Security headers.** In DevTools, open the **Network** tab, click the top-level document request, and read **Response Headers**. Check for `Content-Security-Policy`, `Strict-Transport-Security`, `X-Content-Type-Options`, `X-Frame-Options`, and `Referrer-Policy`. All five missing on a live product is a meaningful signal. `securityheaders.com` gives the same answer with a letter grade, or from a terminal: ```bash curl -sI https://example.com | grep -iE 'content-security-policy|strict-transport|x-frame-options' ``` **Default 404.** Visit a URL that cannot exist — `example.com/definitely-not-a-real-page`. A branded 404 means someone thought about it. Vercel's stock "404: NOT_FOUND" page or a blank white screen means nobody did. **Crawl files.** Fetch `example.com/robots.txt` and `example.com/sitemap.xml`. Missing or scaffold-default versions of both are routine on AI-generated sites, which is also why so many of them are invisible to search and AI answer engines. One boundary worth respecting: passive checks on public pages are fine. Actively probing for `/.env` or config files on a site you do not own or have written permission to test can cross into unauthorized access. Keep the aggressive checks for your own properties. ### 6. Commit-to-Ship Speed A fully-featured product on a domain registered days ago is a timeline that used to be impossible. **How to check:** ```bash whois example.com | grep -i 'creation date' ``` Cross-reference two free sources: `crt.sh` shows the first TLS certificate issued for the domain, and the Wayback Machine shows the first crawled snapshot. A domain created last week, fronting a dashboard with auth, billing, and six feature pages, did not go through a traditional build cycle. The caveat matters here: rebrands, domain migrations, and staging-to-production moves all produce young domains for old products. Use this to raise or lower confidence, not to conclude. ### 7. The Definitive Check — Scan It Individually, every signal above has an innocent explanation. What does not have an innocent explanation is the *combination*, and a security scan is what surfaces it in one pass. The characteristic vibe-code gap profile looks like this: - Secrets or privileged keys reachable from the client bundle - A Supabase or Firebase backend with tables readable without authentication — RLS never enabled, or rules left at `allow read, write: if true` - No security headers at all - No rate limiting on auth or form endpoints - Permissive CORS, wide open to any origin - Cookies without `HttpOnly`, `Secure`, or `SameSite` Any one of those appears on hand-written sites. All of them at once, on a product that looks finished, is the fingerprint of code that shipped without a review pass. We break down why AI assistants produce each of these defaults in [Vibe Coding Security Risks](/blog/vibe-coding-security-risks). ## What These Signals Actually Prove Not much, individually — and that is the honest framing. A `.vercel.app` URL proves someone used Vercel. A missing CSP proves nobody configured one. Neither proves an AI wrote the code, and neither means the site is bad. Vibe coding is a legitimate, extremely productive way to build — plenty of strong products were drafted by an assistant and then hardened properly. The risk is not AI-generated code. The risk is **unreviewed** AI-generated code reaching production. That distinction is the whole point of this list: signals 1 through 6 tell you *how* something was probably built, and signal 7 tells you whether it matters. A vibe-coded site with security headers, RLS enabled, and no keys in the bundle is fine. A hand-written site missing all three is not. If the site in question is yours, the useful next step is not detection — it is [hardening it](/blog/how-to-secure-vibe-coded-app). ## How CheckVibe Helps CheckVibe's [vibe coding security scanner](/vibe-coding-security-scanner) runs the signal-7 checks from the outside, the same way an attacker would, and reports the gap pattern in one place: - **Exposed keys and secrets** — scans the client bundle for API keys, service-role tokens, and credentials that should never leave the server - **Open backends** — probes Supabase and Firebase endpoints for tables and buckets that answer unauthenticated requests - **Security headers** — checks every header a production site should send, with the exact config to add - **Platform and stack detection** — identifies the hosting platform, framework, and backend so you know what you are actually looking at - **SEO and AEO basics** — flags the missing `robots.txt`, sitemap, and metadata that keep AI-generated sites invisible to search engines Each finding comes with a severity rating and a remediation step you can hand straight to your editor. [Run a free scan](https://checkvibe.dev) to see what a site exposes — results in under 60 seconds. ## FAQ ### Can you always tell if a site was vibe coded? No. The signals in this guide are probabilistic, not definitive. A developer who moves off the default subdomain, replaces the favicon and title, writes original copy, and configures security headers leaves almost nothing detectable from the outside. Conversely, a hand-written site on `vercel.app` with a stock 404 will trip several checks. Treat the signals as confidence adjusters that stack, and never conclude from one alone. ### Is a vibe coded website less secure? Not inherently — but unreviewed AI output usually is. AI assistants optimize for working code, so they ship the defaults that reduce friction: wildcard CORS, no rate limiting, secrets in client code, database rules left wide open. None of that is caused by the AI being careless; it is caused by nobody asking for the security layer. A vibe-coded site that has been scanned and hardened is as secure as any other. ### What is the fastest way to check if a site is vibe coded? Look at the URL, then view the page source. A default platform subdomain such as `.lovable.app` or `.vercel.app`, combined with an unchanged template `<title>` or a builder badge in the corner, gets you a confident answer in about thirty seconds. If you need certainty rather than a guess, run a security scan and look for the gap pattern: exposed keys, an open backend, and missing security headers together. --- ## AEO for Vibe-Coded Apps: Why AI-Built Sites Are Invisible to AI (and How to Fix It) *AEO for vibe-coded apps means making AI-generated sites readable and citable. Why they are disproportionately invisible — and the exact fixes.* Published: 2026-06-12 | Reading time: 6 min read URL: https://checkvibe.dev/blog/aeo-for-vibe-coded-apps **AEO for vibe-coded apps is the practice of making AI-generated websites readable, quotable, and citable by AI answer engines like ChatGPT, Claude, and Perplexity.** It matters because vibe-coded apps are disproportionately invisible to those engines: the same AI tools that build your app ship it in a form AI crawlers cannot read. There's a real irony here, and it's worth sitting with: **apps built *by* AI are the apps least visible *to* AI.** **TL;DR** - AI crawlers (GPTBot, ClaudeBot, PerplexityBot) don't execute JavaScript at scale — a client-rendered SPA serves them an empty HTML shell. - Lovable, Bolt, and most AI builders default to exactly that architecture, so vibe-coded apps start invisible. - The fix stack, in order: server-rendered or prerendered HTML → AI-crawler-friendly robots.txt → llms.txt → JSON-LD structured data → answer-first content. - Verify instead of hoping: an [AEO scan](/products/seo-aeo) tests your site the way each engine's crawler does and scores readiness per engine. ## Why are vibe-coded apps invisible to AI engines? If you ask "what is AEO" in general, [we have a full primer](/blog/what-is-aeo-answer-engine-optimization). This post is about the specific, structural problem with AI-built apps. Four defaults conspire against you: ### 1. Client-only rendering Lovable and Bolt scaffold Vite/React single-page applications. The HTML document those apps serve is essentially: ```html <!doctype html> <html> <head><title>My App
``` Everything users see is assembled by JavaScript in the browser. But AI crawlers fetch pages the cheap way — HTTP request, parse the HTML, move on. **GPTBot, ClaudeBot, and PerplexityBot do not run your JavaScript.** What they index is the empty shell above. Your content, for their purposes, does not exist. ### 2. No crawler signals AI builders don't generate robots.txt entries for AI crawlers, don't create sitemaps for multi-route SPAs, and have never heard of llms.txt. The engines that *would* cite you can't even find the front door. ### 3. No structured data Schema.org JSON-LD is how engines resolve *what your product is* — name, category, pricing, FAQs. AI-generated apps ship none of it unless you explicitly prompt for it. ### 4. Vibe-shaped content AI builders write interface copy, not answers. AI engines lift short, self-contained, factual passages. A hero that says "Supercharge your workflow ✨" gives an answer engine nothing to quote. ## What does AEO actually require for a vibe-coded app? Work through these five layers in order — each one depends on the previous. ### Layer 1: Serve real HTML to crawlers This is the hard prerequisite. Options by situation: - **Next.js (v0 output, or anything App Router):** you already server-render. Done. - **Vite/React SPA (Lovable, Bolt):** add prerendering — generate static HTML per route at build time (`vite-plugin-prerender` and similar), or put a prerendering proxy in front for bot user-agents. - **Migration is sometimes cheapest:** if your app is mostly marketing pages plus an app shell, moving the public pages to a server-rendered framework and keeping the app client-side is often less work than retrofitting prerendering. Test it the way a crawler experiences it: ```bash curl -s https://yourapp.com | grep -i "your actual content" ``` If your content isn't in that response, no AI engine has ever read it. ### Layer 2: Open the door in robots.txt Explicitly allow the AI crawlers and point at your sitemap: ``` User-agent: GPTBot Allow: / User-agent: OAI-SearchBot Allow: / User-agent: ClaudeBot Allow: / User-agent: PerplexityBot Allow: / User-agent: Google-Extended Allow: / Sitemap: https://yourapp.com/sitemap.xml ``` ### Layer 3: Add llms.txt A plain-text file at `/llms.txt` that tells AI engines what your product is, what it does, and where the important pages are. Think of it as a README for answer engines. Keep it factual and current — one consistent product description, your pricing, your key URLs. ### Layer 4: Structured data Minimum viable JSON-LD for a product site: `Organization` + `WebSite` sitewide, `SoftwareApplication` (with offers) on the homepage, `FAQPage` wherever you answer questions. AI editors generate valid JSON-LD reliably when asked — then validate with Google's Rich Results Test. ### Layer 5: Answer-first content Every public page should open with a direct answer (≤50 words) to the question the page targets, carry a visible FAQ, and show when it was last updated. Engines lift passages that are already shaped like answers. ## How do you verify any of this worked? Don't guess — measure twice: 1. **Readability (can they read you?):** CheckVibe's [AEO scanner](/products/seo-aeo) runs 46 checks — crawler permissions, JavaScript-free extractability, llms.txt, schema depth — and scores readiness per engine across ChatGPT, Claude, Perplexity, Google AI, Copilot, Meta AI, and Mistral. Pair it with the 68-check SEO scan, because classic indexability still feeds several engines. 2. **Citations (do they cite you?):** ask the engines your target questions and watch for your domain ([here's the manual method](/blog/check-if-chatgpt-can-see-your-website)), or use a mention tracker — [we compared the honest options](/best/aeo-tools-for-vibe-coded-apps). Readability comes first. Tracking mentions of a site engines can't read just measures zero with extra steps. ## FAQ ### What is AEO for vibe-coded apps? It's Answer Engine Optimization applied to AI-generated apps: making a Lovable, Bolt, v0, or Cursor-built site technically readable (rendered HTML, crawler access, llms.txt, structured data) and content-wise quotable for AI answer engines, so ChatGPT, Claude, and Perplexity can cite it. ### Why are vibe-coded apps worse off than normal sites for AEO? Because AI builders default to client-only rendering, which serves AI crawlers an empty HTML shell, and they generate none of the crawler signals (robots rules, sitemaps, llms.txt, schema) engines rely on. A WordPress site from 2015 is more AI-readable than most 2026 vibe-coded apps. ### Does fixing AEO hurt my regular SEO? No — it's the same direction. Server-rendered HTML, structured data, fast pages, and answer-shaped content improve classic Google rankings and AI citability simultaneously. The work pays twice. ### How long until AI engines cite my site after fixing it? Crawlers typically re-fetch within days to weeks; citation depends on whether your content actually answers questions people ask. Freshness signals (visible updated dates, accurate dateModified) and entity consistency speed up trust. Expect weeks, not hours — and verify with a re-scan immediately rather than waiting. ### Can I do AEO without rewriting my whole app? Usually, yes. Prerendering public routes, adding robots.txt + llms.txt, and injecting JSON-LD are all additive changes. The only deep change is rendering architecture, and even that can be scoped to public pages while your app stays an SPA behind login. --- ## How to Rank a Vibe-Coded SPA in AI Search (ChatGPT, Perplexity, Claude) *Client-only SPAs are invisible to AI crawlers. The exact steps to make a vibe-coded React app rank in ChatGPT, Perplexity and Claude.* Published: 2026-06-12 | Reading time: 6 min read URL: https://checkvibe.dev/blog/how-to-rank-vibe-coded-spa-in-ai-search **To rank a vibe-coded SPA in AI search: serve real HTML to crawlers (SSR, SSG, or prerendering), allow AI bots in robots.txt, publish llms.txt, add JSON-LD structured data, restructure pages answer-first — then verify with an AEO scan.** The rendering fix comes first; without it, nothing else registers. AI engines can't execute JavaScript at scale. Your single-page app assembles everything client-side. Those two facts are the entire problem — and every step below exists to route around them. **TL;DR — the 6 steps** 1. Make crawlers receive rendered HTML (prerender or SSR your public routes). 2. Allow GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, Google-Extended in robots.txt + reference your sitemap. 3. Publish `/llms.txt` describing your product in plain text. 4. Add JSON-LD: Organization, WebSite, SoftwareApplication, FAQPage. 5. Rewrite key pages answer-first: direct ≤50-word answers, FAQs, visible update dates. 6. Verify per engine with an [AEO scan](/products/seo-aeo) — then re-check monthly. ## Step 1: Why doesn't my SPA show up in AI search at all? Run this and look at what comes back: ```bash curl -s -A "GPTBot" https://yourapp.com ``` For a typical Lovable or Bolt app you'll see a `
` and a script tag. That's the *entire site* as far as ChatGPT, Claude, and Perplexity are concerned. They fetch HTML over HTTP and parse what's there; they do not boot a browser for your bundle. Fix options, ranked by effort: - **Prerender at build time** — for Vite SPAs, plugins like `vite-plugin-prerender` walk your routes and emit static HTML per route. Best effort-to-impact ratio for marketing pages. - **Prerendering proxy** — a service in front of your app renders pages headlessly and serves the snapshot to bot user-agents. No app changes, ongoing dependency. - **Move public pages to SSR** — Next.js/Remix/SvelteKit for the pages you want cited (landing, pricing, docs, blog), SPA for the logged-in app. The clean long-term shape. Whichever you choose, re-run the curl test. Your actual copy must appear in the raw response. This single step is the difference between "optimizing" and "existing." ## Step 2: Which crawlers should robots.txt allow? The big engines crawl with named user-agents. Allow them explicitly and point at your sitemap: ``` User-agent: GPTBot Allow: / User-agent: OAI-SearchBot Allow: / User-agent: ClaudeBot Allow: / User-agent: PerplexityBot Allow: / User-agent: Google-Extended Allow: / User-agent: Bingbot Allow: / Sitemap: https://yourapp.com/sitemap.xml ``` Two notes vibe coders hit constantly: hosting templates and "bot protection" presets sometimes block these bots at the WAF/CDN layer even when robots.txt allows them (check your Cloudflare/Vercel settings), and an SPA usually has no sitemap at all — generate one listing every public route. ## Step 3: What is llms.txt and do I need it? `/llms.txt` is a plain-text map written for AI engines: what your product is, what it does, key pages, pricing. It costs twenty minutes and removes every ambiguity about your entity: ``` # YourApp > One-sentence factual description of what YourApp does and who it's for. ## Key pages - Pricing: https://yourapp.com/pricing - Docs: https://yourapp.com/docs ## Pricing - Free: ... - Pro ($X/month): ... ``` Keep it synchronized with reality — engines that read a stale llms.txt will repeat stale facts to your prospects. ## Step 4: Which schema matters for AI search? JSON-LD tells engines what they're looking at without inference. The minimum set for a product SPA: - `Organization` + `WebSite` — sitewide, in the document head, ideally as one linked `@graph`. - `SoftwareApplication` with `offers` — homepage and product pages: your name, category, and prices become machine-checkable facts. - `FAQPage` — every page with a Q&A block. AI engines lift these wholesale. Your AI editor will generate all of this correctly from one prompt; validate the output with Google's Rich Results Test. ## Step 5: What content do AI engines actually cite? Engines compose answers from passages that already look like answers: - **Open with the answer.** First paragraph, ≤50 words, directly resolving the page's question. Then elaborate. - **Phrase H2s as questions** — the questions users actually type. - **Add a real FAQ** (3–6 questions) wired to FAQPage schema. - **Show freshness**: a visible "Updated June 2026" plus accurate `dateModified` in schema. - **Tables for comparisons** — semantic HTML tables, not styled divs; engines parse them into facts. One page that answers one question completely beats five pages of brand copy. ## Step 6: How do I know it worked? Test, don't vibe: 1. **Scan readability**: a [free CheckVibe scan](/) runs 46 AEO checks — crawler access, JS-free extractability, llms.txt, schema depth — and shows per-engine readiness for ChatGPT, Claude, Perplexity, Google AI, Copilot, Meta AI, and Mistral, alongside 68 classic SEO checks. 2. **Ask the engines**: query ChatGPT/Perplexity with the questions your pages target and watch for your domain in citations — [full method here](/blog/check-if-chatgpt-can-see-your-website). 3. **Re-scan after every significant deploy.** SPAs regress easily — one refactor can silently restore the empty shell. For continuous mention-tracking once readability passes, see the [best AEO tools comparison](/best/aeo-tools-for-vibe-coded-apps). ## FAQ ### Can a pure client-side SPA rank in AI search without prerendering? Effectively no. AI crawlers parse served HTML; if your content only exists after JavaScript runs, they index an empty shell. Prerendering, SSG, or SSR for public routes is the non-negotiable first step. ### Do AI engines use Google's index or their own crawlers? Both exist in the wild: ChatGPT Search and Claude use their own fetchers (GPTBot/OAI-SearchBot, ClaudeBot), Perplexity runs PerplexityBot, and several engines also lean on Bing's index — which is why allowing Bingbot and submitting your sitemap to Bing still matters for AI visibility. ### How is ranking in AI search different from ranking in Google? Google ranks pages; answer engines cite sources inside a composed answer. Citation favors machine-readable, answer-shaped, factually-consistent content over backlink authority alone — which is why a small site that's perfectly readable can out-cite a big site that isn't. ### How often should I re-check AI readability? After every significant deploy, and monthly at minimum. Client-side regressions are silent: the page looks identical in your browser while serving an empty shell to crawlers. Automated re-scans catch what eyeballs can't. --- ## Why Don't AI Engines Find My Lovable Site? (Diagnosis + Fixes) *ChatGPT, Claude and Perplexity can't read most Lovable sites — they ship client-rendered React. The 60-second diagnosis, then the exact fixes.* Published: 2026-06-12 | Reading time: 6 min read URL: https://checkvibe.dev/blog/why-ai-engines-cant-find-your-lovable-site **AI engines can't find your Lovable site because Lovable publishes client-rendered React apps: crawlers like GPTBot, ClaudeBot, and PerplexityBot receive a nearly empty HTML shell, not your content.** The fixes: serve prerendered HTML on public routes, allow AI crawlers in robots.txt, add llms.txt and structured data — then verify with a scan. You built something good. People who see it like it. But ask ChatGPT about your product category and you're never in the answer — while sites far worse than yours get cited. This is almost never a quality judgment. It's a rendering problem, and it's diagnosable in 60 seconds. **TL;DR** - Lovable apps render in the browser; AI crawlers don't run JavaScript — they index the empty shell Lovable serves. - Diagnose with one command: `curl -s https://yoursite.lovable.app | grep "any phrase from your page"` — no match means no AI engine has ever read your content. - Fix order: prerendered/server-rendered HTML → robots.txt allowing AI bots → llms.txt → JSON-LD → answer-first copy. - Custom domain + consistent product description everywhere helps engines resolve you as an entity. - Verify per engine with a [free AEO scan](/) instead of waiting and wondering. ## How do I confirm this is my problem? Run the diagnosis against your live site (swap in a phrase that's visible on your homepage): ```bash curl -s https://yoursite.com | grep -i "a phrase from your homepage" ``` No output? Then your content lives only in JavaScript. Every AI crawler that has ever visited got this instead: ```html
``` That's what ChatGPT knows about you: nothing. Three follow-up checks while you're at it: 1. **robots.txt** — `curl https://yoursite.com/robots.txt`. Missing file is survivable; a blanket `Disallow: /` (some templates ship one) is fatal. 2. **Sitemap** — does `https://yoursite.com/sitemap.xml` exist? Lovable doesn't generate one. 3. **WAF settings** — if you've enabled aggressive bot protection on Cloudflare or your host, AI crawlers may be blocked before robots.txt is even consulted. ## What exactly do I fix, in what order? ### 1. Serve real HTML on public routes This is the fix that matters; everything else is decoration without it. - **Prerender the public routes** of your Lovable app — landing, pricing, about, blog — so each serves complete static HTML. In Lovable, prompt it directly: *"Add build-time prerendering so all public routes serve full static HTML without JavaScript execution."* - **Or split the site**: public pages on a server-rendered framework (Next.js on Vercel takes an afternoon), the Lovable app behind login where crawlers don't matter. - Re-run the curl test after deploying. Content in the response = fixed. ### 2. Open robots.txt to AI crawlers Add a `public/robots.txt` that explicitly allows GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, Google-Extended, and Bingbot, and references your sitemap. ([Template in our SPA ranking guide.](/blog/how-to-rank-vibe-coded-spa-in-ai-search)) ### 3. Add llms.txt A plain-text `/llms.txt` describing what your product is, what it costs, and where the key pages are. Lovable will generate it from one prompt — just verify the facts before deploying, because engines will repeat whatever it says. ### 4. Add structured data Organization + WebSite + SoftwareApplication JSON-LD (with your real pricing in `offers`), FAQPage on any page with questions. One Lovable prompt, then validate with Google's Rich Results Test. ### 5. Make the content quotable AI engines lift self-contained answers. Open pages with a direct ≤50-word answer, use question-phrased headings, add a real FAQ, and show "Updated [month year]" visibly. "Supercharge your workflow ✨" is not citable; "X is a [category] that does [specific thing] for [audience], from $0" is. ### 6. Claim your entity Use a custom domain (a `*.lovable.app` subdomain dilutes you), and one identical product description across your site, llms.txt, schema, and social profiles. Engines cite entities they can resolve confidently. ## What about my Supabase backend — does it affect AI visibility? Indirectly, in two ways worth knowing. Content fetched client-side from Supabase after page load is invisible to crawlers even with prerendering — public content you want cited should be rendered into the HTML at build/request time. And while you're fixing visibility, check security too: most Lovable apps we scan have at least one Supabase table without Row Level Security, which is a much worse kind of "publicly readable." [The Lovable security + ranking guide covers both.](/secure/lovable) ## How do I verify each engine can now read me? A [free CheckVibe scan](/) runs 46 AEO checks against your live site — crawler permissions, JavaScript-free extractability, llms.txt, schema depth — and returns a per-engine readiness matrix for ChatGPT, Claude, Perplexity, Google AI, Copilot, Meta AI, and Mistral, plus 68 SEO checks and a security audit in the same pass. Findings come as fix prompts you can paste straight back into Lovable. Then close the loop from the demand side: [ask the engines directly](/blog/check-if-chatgpt-can-see-your-website) and consider a mention tracker once readability passes ([honest tool comparison here](/best/aeo-tools-for-vibe-coded-apps)). ## FAQ ### Why does ChatGPT say it can't access my Lovable site? Either the content is client-rendered (the usual cause — crawlers get an empty shell), or a robots.txt/WAF rule blocks OpenAI's crawlers. The curl test distinguishes them: empty-but-200 response means rendering; a 403/blocked response means access rules. ### Does Lovable support server-side rendering? Lovable publishes client-rendered React apps. You can prompt Lovable to add build-time prerendering for public routes, which produces static HTML crawlers can read — functionally equivalent for AEO purposes. Verify the result with curl rather than trusting the prompt succeeded. ### Will fixing AI visibility also fix my Google ranking? Largely, yes. Google handles JavaScript better than AI crawlers but still rewards server-rendered HTML, structured data, and fast pages. Every fix in this post helps both; none hurts either. ### How long after fixing will ChatGPT cite my site? Crawlers re-visit within days to weeks. Citation then depends on whether your pages answer questions people actually ask — that's the content layer. Re-scan immediately to confirm readability, then give the engines a few weeks while you improve answer-shaped content. ### Is this a Lovable-specific problem? No — Bolt, and most AI app builders default to the same client-rendered architecture. Lovable sites just hit it most visibly because Lovable is so often used for public-facing products. [The general SPA fix guide is here.](/blog/how-to-rank-vibe-coded-spa-in-ai-search) --- ## Automated Accessibility Testing: What a WCAG Scan Catches (and What It Can't) *The European Accessibility Act is enforced and most teams still ship unlabeled forms. What automated WCAG checks catch, what needs a human, where to start.* Published: 2026-06-10 | Reading time: 15 min read URL: https://checkvibe.dev/blog/automated-accessibility-testing-wcag **Automated accessibility testing** uses tools like axe-core, Lighthouse, or Pa11y to check a rendered page against machine-verifiable WCAG rules — missing alt text, unlabeled inputs, low contrast, invalid ARIA — and report the offending element. It runs in CI or on a schedule, and per industry research catches roughly half of accessibility issues. The rest needs a human. Around 16% of the world's population lives with a significant disability. Meanwhile WebAIM's annual survey of the top million homepages keeps finding the same thing: the overwhelming majority have detectable WCAG failures, and the typical homepage has dozens. The gap between "we care about accessibility" and "our signup form has labels" has never been wider — or more expensive. Expensive, because the legal landscape moved. The **European Accessibility Act (EAA)** has applied since June 28, 2025: e-commerce and many digital services sold into the EU must be accessible, with member states attaching real fines. In the US, ADA lawsuits over inaccessible websites continue at thousands per year, and they disproportionately target small and mid-size businesses — the ones without an accessibility team. This post is about the automation layer: what a scanner can genuinely catch, what it can't, and why "it's automated, so it's partial" is an argument for running it on every deploy rather than skipping it. ## What WCAG actually asks for The Web Content Accessibility Guidelines (WCAG) 2.x organize requirements under four principles — content must be **perceivable, operable, understandable, and robust**. Conformance comes in levels; **Level AA** is the standard contracts, laws (including the EAA's underlying EN 301 549), and procurement checklists mean when they say "accessible." In practice, AA translates into things like: every image conveys its information in text, every form field has a name, the page has a sane heading structure, keyboard users can reach and operate everything, nothing relies on color alone, and assistive technologies can parse the markup. None of this is exotic — most of it is HTML used the way HTML was designed. ### WCAG levels: A, AA, and AAA Three conformance levels stack. **Level A** is the floor — the failures that make content outright unusable (no keyboard access, no alt text, autoplaying audio you can't stop). Nobody targets A on purpose; you pass it on the way to AA. **Level AA is the target that matters.** It's what EN 301 549 (the European standard the EAA leans on) points at, what US ADA settlements and consent decrees routinely name, what Section 508 procurement requires, and what your enterprise customer's security questionnaire or VPAT will ask you to attest to. If a contract, law, or RFP says "accessible" without qualifying it, assume WCAG 2.1 (or 2.2) Level AA. **Level AAA** adds stricter criteria — 7:1 contrast, sign-language interpretation for prerecorded audio, no more than three-word-per-line justification quirks. The W3C explicitly says AAA is not achievable for all content, so it isn't a sane site-wide goal. Cherry-pick AAA criteria where they're cheap (`7:1` contrast on body text costs nothing at design time) and target AA everywhere. When you configure a tool, this maps directly to a tag filter: axe-core's `wcag2a`, `wcag2aa`, `wcag21aa` tags, or Pa11y's `WCAG2AA` standard. Pick AA and stop arguing about it. ## What automated checks reliably catch Deque's research — the most-cited number in this space — found that automated testing can detect issues accounting for roughly 57% of accessibility problems. Call it "about half," and note that the half automation owns is the half that's objective, repeatable, and cheap to fix. That's the automation surface, and it covers the failures that are both most common and most embarrassing: ### Structure and semantics - **Missing `lang` attribute** — screen readers guess the pronunciation language without it - **Missing or multiple `

`s, skipped heading levels** (`h2` → `h4`) — headings are how many screen reader users navigate a long page, so a broken outline breaks their primary wayfinding - **No `
` landmark**, duplicate `id`s, invalid ARIA roles - **`aria-hidden` on focusable elements** — keyboard focus lands on something screen readers are told doesn't exist - **Data tables without header cells** (``/`scope`) ### Forms — the highest-stakes category - **Inputs without labels** — the single most consequential common failure: an unlabeled email field reads as "edit text, blank" to a screen reader. WebAIM's annual survey finds missing form labels on a large share of the pages that have forms at all. - **Missing `autocomplete` on identity fields** — WCAG 1.3.5; also what lets password managers and users with motor or cognitive disabilities fill forms reliably - **Radio groups without `
`/``** — options with no audible question - **`