175 guides, grouped by severity. Each one explains what the rule means, why it matters, and the exact steps to fix it. Linked from every vibecheck scan report.
.env file accessible at your public rootA request to `/.env` (or `/.env.local`, `/.env.production`) returned 200 with what appeared to be environment variable definitions.
Server reflects arbitrary Origin AND sets Allow-Credentials: truevibecheck sent a request with `Origin: https://attacker.example`. Your server echoed it back in `Access-Control-Allow-Origin` AND set `Access-Control-Allow-Credentials: true`. Any malicious site can now make authenticated requests to your API as a logged-in victim and read the responses.
Firebase Realtime Database root readable without authenticationA GET to `https://<project>.firebaseio.com/.json` returned data without an auth token. Your RTDB security rules grant `.read: true` at the root — every node in the database is enumerable by anyone with the project ID (which is in your client bundle).
GitHub webhook signing secret in client codeA string assigned to `GITHUB_WEBHOOK_SECRET` (or similar) was found in your deployed JavaScript. With this secret, an attacker can forge any webhook event GitHub would normally send — pull requests, pushes, comments, releases — and your webhook handler will validate the forged HMAC and process it as legitimate.
Slack signing secret in client codeA 32-character hex string assigned to `SLACK_SIGNING_SECRET` was found in your deployed JavaScript. The signing secret is what proves an inbound Slack request (slash command, event, interactive payload) is real — leak it and any attacker can forge requests to your Slack handler endpoints.
JWT in client bundle uses alg=noneA JWT in your client JavaScript declares `alg: "none"` in its header. Tokens with `alg=none` are unsigned — anyone reading the token can forge a copy with arbitrary claims, and any backend that accepts `alg=none` will treat the forgery as valid.
OAuth client_secret embedded in client bundleAn OAuth `client_secret` was found inside your deployed JavaScript. Anyone who views your bundle can now impersonate your application against the OAuth provider.
.htpasswd file exposed — password hashes leakedYour `/.htpasswd` file is publicly reachable. It contains usernames and bcrypt / SHA-1 / crypt password hashes. The hashes are CRACKABLE OFFLINE — attackers run hashcat against them and recover the passwords at their leisure.
Rails config/database.yml exposedYour Rails `config/database.yml` is publicly reachable. It contains the DB hostname, username, and (in most configs) the password in plaintext.
Rails config/secrets.yml exposedYour Rails `config/secrets.yml` is publicly reachable. It contains `secret_key_base` — the key Rails uses to sign session cookies. With this key, an attacker forges any user's session and impersonates them.
Service Worker registered from a third-party hostYour page registers a Service Worker whose source is on a different origin. The third party can intercept every fetch your page makes — including auth headers, CSRF tokens, and response bodies — and reroute or modify the responses.
High high
Supabase tables readable without authenticationYour Supabase tables responded 200 to an unauthenticated request with the anon key. Row-Level Security is either disabled or set to a permissive policy.
JavaScript source map deployed to productionvibecheck found a `.map` file referenced by your bundled JavaScript and reachable at the public URL. Source maps de-minify your bundle into the original TypeScript / TSX / JSX with comments, file structure, and developer notes intact.
Auth token stored in localStorage or sessionStorageYour code calls `localStorage.setItem("<auth-shaped-key>", token)` (or sessionStorage). Any XSS that lands on your page can read the token directly. Move auth state to in-memory + HttpOnly refresh cookies.
Inline <script> blocked by declared CSPAn inline `<script>` on the served page would be blocked by your declared CSP. The browser refuses to execute it — your page is shipping broken JavaScript that only fails on browsers enforcing the policy.
External <script src=> blocked by declared CSPA `<script src="https://...">` tag in your HTML loads from an origin that your declared CSP doesn't allow under `script-src`. The browser refuses to fetch or execute it.
Password form submits over plain HTTPA `<form>` containing an `<input type="password">` submits to an `http://` action — or the page itself is on `http://` with no explicit action. The password ships in cleartext on every hop between the user and the destination server.
CSP allows 'unsafe-inline' in script-srcYour `Content-Security-Policy` header includes `'unsafe-inline'` in `script-src` (or in `default-src` with no `script-src` override). Any reflected or stored XSS executes immediately — the CSP provides essentially no protection against script injection.
CSP allows 'unsafe-eval' in script-srcYour `Content-Security-Policy` header includes `'unsafe-eval'` in `script-src`. JavaScript's string-as-code APIs (`eval()`, `Function()`, `setTimeout('code', n)`, `setInterval('code', n)`) are permitted. Often left over from a build tool that needed it during development.
CSP script-src includes a wildcard or full-protocol schemeYour CSP `script-src` includes `*`, `https:`, or `http:` — the policy permits scripts from anywhere. An attacker who can host JS on any domain (or via a compromised CDN) gets full code execution against your origin.
CSP allows data: in script-srcYour CSP `script-src` includes `data:`. An attacker who can inject markup into your page can include `<script src="data:text/javascript,malicious_code()">` and execute arbitrary code without ever loading a remote resource.
Server reflects arbitrary Origin in Access-Control-Allow-Originvibecheck sent a request with `Origin: https://attacker.example` and your server echoed that exact value back in the `Access-Control-Allow-Origin` response header. The CORS allowlist isn't actually filtering — every origin is accepted.
Server allows Origin: nullvibecheck sent a request with `Origin: null` (the literal string `null`) and your server returned `Access-Control-Allow-Origin: null`. Sandboxed iframes, `data:` URLs, and `file://` URLs all send `Origin: null` — an attacker who can host a sandboxed iframe gets whatever this CORS policy grants.
Convex query/mutation returns data without authenticationA Convex function (extracted from your client bundle) returned a successful response when called without an auth header. Anonymous callers can read whatever this function returns.
Appwrite collection readable without authenticationAn Appwrite collection's documents endpoint returned 200 with documents when called without a session. The collection's read permission is set to `any` (or unset).
Pocketbase collection records readable without authenticationYour Pocketbase collection's `/api/collections/<name>/records` endpoint returned records when called without a session header. The collection's List rule is blank — which in Pocketbase means open, not closed.
Firestore collection readable without authenticationA GET to `https://firestore.googleapis.com/v1/projects/<project>/databases/(default)/documents/<collection>` returned documents without an auth header. Your Firestore security rules permit anonymous reads on this collection.
Firebase Storage bucket allows anonymous listA GET to `https://firebasestorage.googleapis.com/v0/b/<bucket>/o` returned an object listing without an auth token. Your Storage rules permit anonymous reads on the default bucket — which means every file path is enumerable.
Generic webhook secret in client codeA string assigned to a variable named `WEBHOOK_SECRET`, `HOOK_SECRET`, or similar was found in your deployed JavaScript. The variable name is generic — this could be the signing secret for any provider that uses HMAC-signed webhooks.
JWT in client bundle has no exp claimA JWT was found in your client JavaScript with no `exp` (expiration) claim. The token is valid forever as long as the signing secret stays valid. If the secret leaks or the token is exfiltrated, you have no time-based recovery.
Hardcoded JWT with privileged claims in client bundleA JWT containing privileged claims (`role: "admin"`, `is_admin: true`, `service_role`, etc.) is hardcoded in your client JavaScript. Every visitor can extract this token and present it to your backend to impersonate an admin or service identity.
OAuth redirect_uri uses http:// (not HTTPS)The OAuth authorize URL in your bundle redirects to an http:// callback. The authorization code travels in cleartext on the redirect leg — anyone on the network path captures it.
OAuth redirect_uri built from user input or templateYour OAuth authorize URL builds `redirect_uri` dynamically — using template-literal interpolation, `window.location`, or query-param substitution. If the OAuth provider's allowlist is permissive, an attacker can redirect the auth code to a domain they control.
Auth token passed in URL query stringAn auth-shaped query parameter (`access_token=`, `session_id=`, `jwt=`, etc.) was found in the bundle. Tokens in URLs leak through server logs, browser history, Referer headers, and analytics — every system in the request path gets a copy.
.env.staging file deployed to productionA `/.env.staging` file is reachable at your production root. It contains environment variables your staging environment uses — often a subset of production creds, but frequently reusable against staging surface or revealing internal service names.
ASP.NET web.config exposedYour `/web.config` is publicly reachable and contains either a `<connectionStrings>` block (database creds), an `<appSettings>` block (custom secrets), or a `<machineKey>` (cookie/session signing key). Each of those is a critical credential.
window.postMessage() called with target origin '*'Code in your bundle calls `postMessage(data, '*')`. The wildcard target means the browser will deliver the message to whatever origin currently owns the receiving window — including attacker-controlled origins if the receiver navigated away mid-flow.
window 'message' listener doesn't validate event.originYour code registers a `message` event listener that doesn't check `event.origin`. The handler will accept messages from any sender — including attacker-controlled iframes, popups, or browser extensions.
Auth token embedded in WebSocket connection URLA WebSocket URL in your bundle includes an auth-shaped credential in its query string. Proxies and load balancers log the full WS connection URL the same way they log HTTP URLs — the token leaks to every system in the request path.
Service Worker imports JavaScript from a third-party hostYour Service Worker uses `importScripts()` to load JavaScript from a different origin. Whatever bytes that origin returns get executed with full Service Worker privileges — fetch interception, response rewriting, persistent caching.
Iframe delegates dangerous browser features to a cross-origin frameAn `<iframe>` on your page uses `allow=` to delegate camera, microphone, geolocation, payment, USB, or similar powerful APIs to a third-party origin. The browser permission prompt names YOUR domain, not the third party — so users approve the wrong thing.
GraphQL Playground / GraphiQL UI exposed in productionA GraphQL Playground, GraphiQL, or Apollo Sandbox UI is reachable on a production endpoint. The UI is a full interactive query editor against your live schema — useful for development, dangerous to ship.
CSP has no default-src directiveYour `Content-Security-Policy` header has no `default-src` and no `script-src` directive. Fetch directives that aren't explicitly set fall back to `default-src`; without it, those fetches are unrestricted.
Redux DevTools enabled in productionYour production bundle is wired to the Redux DevTools browser extension, exposing every state mutation, action, and dispatched payload.
LLM system-prompt template shipped in client codeA long string literal containing LLM-shape markers ("you are an AI", "ignore previous instructions", numbered guidelines) was found in your bundle.
HTML comment with developer noteAn HTML comment in your page contains TODO, FIXME, staging password, or other developer-shaped notes.
Pocketbase collections metadata readable without authYour Pocketbase deployment's `/api/collections` endpoint returned the full schema without authentication. Attackers can see every collection name, every field, every type, every validation rule.
JWT in client bundle has multi-month expirationA JWT in your client bundle has an `exp` claim more than 30 days in the future. Access tokens should be short-lived (15m-1h); refresh tokens stay server-side. A long-lived access token is a credential that survives password changes and account compromises.
External script loaded without Subresource IntegrityA `<script src="https://...">` tag pulls JavaScript from a third-party host, but has no `integrity=` attribute. The browser will execute whatever bytes the CDN returns — even if those bytes were swapped by an attacker.
OAuth uses implicit flow (response_type=token) — deprecatedYour authorize URL requests `response_type=token`. The OAuth 2.0 Security Best Current Practice (BCP) explicitly deprecates this — access tokens land in the URL fragment, where they leak via Referer headers, browser history, and analytics.
OAuth authorize URL has no state parameter and no PKCEThe authorize URL in your bundle includes neither a `state` parameter nor a PKCE `code_challenge`. The OAuth callback is vulnerable to CSRF — an attacker can pre-prepare an auth code and trick the user into binding it to their account.
API key passed in URL query stringAn API-key-shaped query parameter (`api_key=`, `apikey=`, etc.) was found in the bundle. URLs ride in too many side channels (logs, history, Referer) for credentials to live there.
.env.development deployed to productionA `/.env.development` file is reachable in production. Usually contains throwaway dev creds — but reveals which services your app depends on and which env-var names are expected.
External stylesheet loaded without Subresource IntegrityA `<link rel="stylesheet" href="https://...">` pulls CSS from a third-party host without an `integrity=` attribute. Compromised stylesheets can hide buttons, fake dialogs, and exfiltrate page state.
Low low
Sentry DSN in client codeA `https://*.ingest.sentry.io/*` DSN was found in your client. This is meant to be public.
Password input has no autocomplete attributeAn `<input type="password">` has no `autocomplete` attribute. Password managers can't reliably identify the field, leading to manual password entry (typo-prone, shoulder-surfable) or users disabling autofill for your site entirely.
Cookie name reveals backend frameworkCookie names like `JSESSIONID`, `PHPSESSID`, `connect.sid`, `laravel_session`, `next-auth.session-token` fingerprint your backend stack.
OAuth redirect_uri points at localhost in a production bundleYour production-deployed bundle includes an OAuth authorize URL whose `redirect_uri` is `http://localhost`. The flow won't work for end users — and it signals that your build pipeline isn't substituting per-environment configs.
PHP composer.lock file exposedYour `/composer.lock` is reachable. It lists every PHP package your app uses, with EXACT version numbers. Useful for attackers cross-referencing against public CVEs.
Ruby Gemfile.lock file exposedYour `/Gemfile.lock` is reachable. It lists every Ruby gem in your app with exact versions. Useful for attackers cross-referencing against public CVEs.
Next.js _buildManifest.js exposedYour `_next/static/chunks/_buildManifest.js` is reachable. The file lists every route in your Next.js build, including admin routes and dynamic-segment routes attackers can probe for IDOR.
Azure AD / Entra app association exposedYour `/.well-known/microsoft-identity-association.json` reveals your Azure AD / Entra tenant ID and registered application IDs. Required for verified-publisher and SSO flows — but worth confirming the tenant and app IDs listed are intentional.
Apple App Site Association file exposedYour `/.well-known/apple-app-site-association` reveals your iOS team ID, bundle ID, and the deep-link paths your iOS app handles. Required for Universal Links — but the path list can accidentally publish internal routes.
Android Asset Links file exposedYour `/.well-known/assetlinks.json` reveals your Android package name and APK signing certificate SHA-256 fingerprint. Required for App Links / SmartLock — but worth confirming the package + fingerprint are production-intended.
Service Worker controls the entire origin (scope: '/')A Service Worker registered at the origin root controls every page, every fetch, every cookie-bearing request on the site. It's the standard PWA template — but it widens the blast radius if the worker file is ever compromised.
CSP does not opt in to Trusted TypesYour CSP doesn't include `require-trusted-types-for 'script'`. Adding it instructs Chrome / Edge to refuse innerHTML / document.write / eval-shaped sink writes unless the value passes through a vetted policy — a real defense-in-depth XSS mitigation.
Inline scripts correctly pinned by CSP hash (positive signal)Your CSP includes `'sha256-...'` hash entries that match the inline scripts on the page. This is the recommended pattern for serving inline JSON-LD or small bootstrap code under a strict CSP — surfaced here as a positive confirmation that the build pipeline is doing the right thing.
Password field uses autocomplete="off" — outdated guidanceA password field explicitly sets `autocomplete="off"`. Once considered a hardening practice; modern guidance (NIST SP 800-63B §5.1.1.2, OWASP ASVS 4.0) recommends the opposite — allowing password-manager autofill leads to stronger, unique passwords.
CSP is in Report-Only modeYour server sends `Content-Security-Policy-Report-Only` instead of `Content-Security-Policy`. Browsers will log violations to the report endpoint but will not block them. Effective protection only after switching to enforce mode.
robots.txt blocks AI crawlersYour robots.txt has explicit Disallow rules for GPTBot, ClaudeBot, PerplexityBot, or Google-Extended.
Convex deployment URL exposed in clientYour Convex deployment URL (`https://<name>.convex.cloud`) is reachable from view-source. This is by design — the client needs it to make API calls.
Firebase project ID exposed in clientA Firebase project ID was extracted from your client bundle (via `projectId`, `databaseURL`, or a Firestore REST URL). This is public by design — but it gives attackers a complete target list.
Expired JWT hardcoded in client bundleA JWT in your client bundle has an `exp` claim in the past. The token is currently useless to attackers, but its presence indicates a hardcoded fixture that survived the build — usually a test artefact that points at a live token elsewhere.
OIDC discovery document exposedYour `/.well-known/openid-configuration` is publicly reachable. Required if you are an OpenID Connect provider — this is the document clients fetch to discover your token endpoint, supported scopes, and JWKS URI. Surfaced here as architectural intel so you know what's visible to anyone doing reconnaissance.
OpenID Connect verifiable credentials issuer metadata exposedYour `/.well-known/openid-credential-issuer` is publicly reachable — you're running an OIDC4VCI verifiable-credential issuer. Surface here so you know which credential types you're publicly advertising.