Open every managed service’s dashboard, Supabase or Firebase included, and write down 5 settings: who can read each table, who can read each storage bucket, where the privileged key lives, who can see the project, and what the plan tier backs up. That list answers what are insecure defaults on your stack: managed platforms ship permissive defaults so that prototypes work.

What are insecure defaults: the settings that ship open so the prototype works

Insecure defaults are values a product ships with that are meant to be changed by whoever installs, administers or maintains it but are not secure as shipped; that is how MITRE’s CWE-1188 defines the weakness. On a managed platform they are dashboard settings: who can read tables and files, where the privileged key lives, and who can see the project.

The CWE entry is CWE-1188, “Initialization of a Resource with an Insecure Default”, and on an app built on hosted services it sits inside secrets management best practices, covering the settings around the keys as well as the keys. The first paragraph already gave the reason platforms ship them open; the work is finding which default settings were left open in production on your app.

The same words get used for two other things. The code-level kind is CWE-453, “Insecure Default Variable Initialization”: “The product, by default, initializes an internal variable with an insecure or less secure value than is possible.” That is the meaning Snyk Learn’s tutorial teaches. The credential kind is CWE-1392, “Use of Default Credentials”: “The product uses default credentials (such as passwords or cryptographic keys) for potentially critical functionality.” This page is about the third kind, the setting a managed platform picks for you.

Kind of defaultWhy a platform ships it open (my reading)What it exposes in production
Data access (tables)A tutorial whose first query returns nothing loses the user on step twoRows of any table the public key can reach with no row check
File access (storage buckets)An uploaded image should display the moment it landsAny file to anyone who has its URL
Privileged keyThe first server call should work before anyone has thought about rolesEvery row, past every policy, once the key reaches a browser
Sharing and visibilityA demo link should open for whoever it is sent toThe live app, to anyone with the link
Plan tierThe free tier gets the first project running at no costA lost table with no copy to restore it from

An AI builder adds its own pressure: it optimizes for the preview rendering, and an open setting renders first (my reading). The builder was a fine choice; the settings it picked still need a second look.

A framework shows the same pattern in miniature. The Apache Isis advisory for CVE-2022-42467, severity low, says that when running in prototype mode, the h2 web console module was automatically made available with the ability to directly query the database. “It was felt that it is safer to require the developer to explicitly enable this capability.” As of 2.0.0-M8 that is done with a remote-access configuration property, and the web console is unavailable without it; as an additional safeguard, a new parameter, enabled by default, requires the administrator to use a randomly generated password printed to the log. The advisory notes that the h2 web console is never available in production mode, so these safeguards are only to ensure it is secured by default also in prototype mode. The NVD record maps it to CWE-1188, and CWE-1188’s page lists it among its observed examples.

The lesson I take from it: a capability that was never available in production mode was still made unavailable by default in prototype mode, and an app that goes live on its builder’s starter settings deserves the same list of what is open and why. That is my reading, not the advisory’s.

OWASP ranks the class second: A02 in the Top 10:2025, moving up from fifth in the previous edition. OWASP’s Security Misconfiguration entry defines it as a system, application, or cloud service “set up incorrectly from a security perspective, creating vulnerabilities”, and one of its example scenarios is a cloud provider that “defaults to having sharing permissions open to the Internet.”

Not every default is insecure, and platforms tighten theirs over time, so every row in the table further down carries the date its source was read.

In the Production Hardening Sprint, this is deliverable 2.9, managed-platform security settings, where we review and harden the settings of every managed service in the stack: auth policies, storage access rules, privileged keys kept server-side, and a plan tier adequate for backups and recovery.

Secure configuration and the baseline: the words a reviewer uses

Secure configuration means setting each system to a known safe state and keeping it there. The baseline is the reviewed and agreed list of settings and their values, changed only through a controlled change. For a small SaaS that is one dated table, one row per service and setting, re-read whenever a service or plan changes.

The terms come from NIST. NIST’s definition of security configuration management is “The management and control of configurations for an information system to enable security and facilitate the management of risk.” Its baseline configuration is “A set of specifications for a system, or Configuration Item (CI) within a system, that has been formally reviewed and agreed on at a given point in time, and which can be changed only through change control procedures.” Secure configuration management is that pair over time: reach the baseline once, then keep the system on it.

For an app on hosted services, the secure configuration baseline is the before-and-after table in the verify section below (my reading). Mapped to one app, the work has four stages: list the services, fill the table, re-check it whenever a service is added or a plan changes, and fix whatever moved (my mapping). Nobody has to configure security settings from scratch here; the job is reading what shipped and changing what is wrong.

Configuration enforcement at this size is a re-read of the table about once a quarter plus each platform’s own advisor, not a product (my working rule). Security configuration management software is built for fleets of devices and servers, which a small SaaS on hosted services does not have (my reading). My working rule for SaaS configuration management best practices at this size is three lines: one owner, one table, a date on every row. A security baseline configuration checklist for this kind of app is the table’s rows plus the five outside checks further down.

What goes wrong without it

Each open default gives an outsider something specific. The table routes each one to the article that tells its full story.

The defaultWhat an outsider can doWhere the full story lives
A data table the public key can reach with no row checkOn Supabase, anyone holding the project’s publishable key can read and write every row in itthe three ways a ‘safe’ Supabase app is still open; Firebase’s test mode in the platform section below
A file store set publicOpen any file whose URL they possessThe storage rows of the master table below
A privileged key where the browser can read itEverything the key reaches: current secret and legacy service_role keys are elevated server credentials that bypass RLSwhere AI builders leave the API open by default and API keys exposed on frontend code
A project, preview or share link open to anyoneCan visit the published app with nothing but the URLThe platform rows of the master table below
A plan tier that keeps no automatic backupNothing directly; a bad delete has no copy to come back from (my reading)The plan-tier section below

Two numbers from the 21 third-party apps I audited in June and July 2026 sit close to this list: 7 of the 21 had confirmed cross-user or cross-tenant authorization failures, where a logged-in user could read or write another customer’s data, and 6 of the 21 shipped a real secret. The 21 are the 11 public third-party apps plus the 10 held-out apps audited blind, a selected set of audited apps, not a random sample or a rate for AI-built apps in general. In the same audits, the Authorization pillar averages 42.1 out of 100 across the 14 third-party apps scored on it.

How to do it: the table of defaults, platform by platform

The table of defaults has one row per setting: the platform, the setting, the risky default or common state, the safe value, where to change it, and the date it was checked. Read each row in the platform’s own dashboard, change what differs, and keep the old value in the record.

The values below come from each platform’s documentation on the date shown, not from a test of your project; the storage rows, for example, are from Supabase’s storage bucket docs.

PlatformSettingRisky default or common stateSafe valueWhere to change itChecked
SupabaseRow level security on a new tableThe Table Editor enables it for a table created in the Dashboard; for a table created with SQL, you enable it yourselfEnabled, with a policy on every tableTable Editor, or alter table ... enable row level security;2026-09-28
SupabaseGrants on new tables in publicOn existing projects, new tables receive SELECT, INSERT, UPDATE and DELETE for anon, authenticated and service_roleEach role granted only the privileges it needsSQL: alter default privileges (Revoke default privileges)2026-09-28
SupabaseStorage bucket accessBuckets are private by default; a public bucket serves any file to anyone who possesses its URLPrivate, with RLS policies; a signed URL, which can be accessed for a limited time, where a file must be sharedThe bucket’s public or private setting2026-09-28
SupabaseStorage uploadsBy default, no uploads to buckets without RLS policiesUpload policies only for the users who should uploadRLS policies on storage.objects2026-09-28
SupabaseRealtime channel authorizationOpt-in: needs RLS policies on realtime.messages plus private: true in the client channel config, separate from data-table policiesPrivate channels with policies on realtime.messagesSQL policies and the client channel config2026-09-28
SupabaseSecret and service_role keys”provide full access to your project’s data, bypassing Row Level Security”; the legacy anon and service_role keys are being deprecated by the end of 2026Server side only; never “a browser, even on localhost”Settings > API Keys2026-09-28
SupabaseSecurity AdvisorRuns automatically in Studio; after a fix, you rerun the advisor to confirm the finding is goneNo open finding for RLS disabled in public schemas, RLS enabled with no policies, policies written as USING (true), or SECURITY DEFINER functions callable without authenticationStudio: Security Advisor, or supabase db advisors2026-09-28
FirebaseSecurity Rules at creationYou “choose to either deny access to all users (Locked mode) or grant access to all users (Test mode)“Rules configured for your data before you deployConsole: Realtime Database, Cloud Firestore or Storage, then Rules2026-09-28
FirebaseApp Check enforcementRequests without a valid attestation are rejected once you enable enforcement; a default state is not stated on Firebase’s App Check overviewEnforcement enabled for each service the app callsApp Check’s “Enable enforcement” steps2026-09-28
LovableData accessRLS policies control which users can access or modify data; the Quick scan runs on every publish, and its findings do not block publishing by defaultEvery policy reviewed; no open scan findingMore → Cloud → Database → RLS policies2026-09-28
LovableProject access (the editor)Workspace, the default for all plans; invited-users-only access is on Business and Enterprise; public projects removed as of April 22, 2026Workspace, or invited users only where the plan allows itWorkspace settings → Privacy & security → Default project access2026-09-28
LovableWebsite access (the live app)Free and Pro: anyone with the link can visit, and you cannot restrict website access on these plansPublic only for an app meant for the publicThe publish dialog; Default website access in workspace settings2026-09-28
Base44App visibilitySmart app visibility sets apps that act like public sites to Public without requiring loginPrivate or Workspace for anything not meant for the public; Private apps are on paid plans onlyDashboard → Overview → App Visibility2026-09-28
Base44Per-entity accessBase44 automatically sets up data permissions as you build; a rule set to All Users lets anyone perform that action, even without signing inRules on each entity so data is only available to authorized peopleDashboard → Security2026-09-28
ReplitPublished app accessPersonal workspace: Public; organization workspace: a private optionWorkspace only or Invite only for anything internalPublishing → Who can access your app (unpublish first to change it)2026-09-28

Read the first two Supabase rows together. A table with RLS disabled is not automatically reachable unless the role also has the necessary privilege and the object is in an exposed schema, and on existing projects the default grants supply that privilege. A migration is SQL too, so a table a migration created is the one to check first (my reading). Supabase says it is changing the platform default so that exposure becomes opt-in; until your project shows that, the row stays on the list.

Supabase Edge Functions: the default secrets and the service role key

Supabase Edge Functions start with default secrets you never set yourself: SUPABASE_URL, SUPABASE_DB_URL, the publishable and secret key dictionaries, the JWKS, and the legacy SUPABASE_ANON_KEY and SUPABASE_SERVICE_ROLE_KEY. Supabase’s docs call the secret keys safe to use in Edge Functions but never in a browser.

The page for Supabase’s Edge Function secrets, titled “Environment variables” in Supabase’s docs, lists them under “Default secrets” in this order, from the Supabase URL to the legacy service role key:

VariableWhat Supabase’s docs say it is
SUPABASE_URLThe API gateway for your Supabase project
SUPABASE_DB_URLThe URL for your Postgres database. Use it to connect directly to your database
SUPABASE_PUBLISHABLE_KEYSThe publishable keys JSON dictionary for your Supabase API. This is safe to use in a browser when you have Row Level Security enabled
SUPABASE_SECRET_KEYSThe secret keys JSON dictionary for your Supabase API. This is safe to use in Edge Functions, but never use it in a browser. These keys bypass Row Level Security
SUPABASE_JWKSThe JSON Web Key Set used to verify user JWTs
SUPABASE_ANON_KEY (legacy)“The anon key for your Supabase API”, with the same browser note as the publishable keys
SUPABASE_SERVICE_ROLE_KEY (legacy)“The service_role key for your Supabase API”, with the same Edge Functions and browser note as the secret keys. “This key bypasses Row Level Security”

Every function has the key within reach by default, so the insecure-default question for this list is which functions read the secret or service_role key, and whether each one needs to (my reading). Supabase’s API keys page goes a step further: “Don’t read the key from the environment inside an Edge Function. Use the @supabase/server SDK instead.”

The environment variables explainer on this blog names the same list in one sentence; this table adds each variable’s description. What a function holding that key can expose, and the verify_jwt setting, are covered in the Supabase safety article’s section “The surfaces RLS does not cover on its own”. The policies themselves are in Supabase RLS best practices, and replacing a key that has already leaked is how to rotate API keys safely.

Firebase, Lovable, Base44 and Replit: the rows, and where each platform’s full story lives

Firebase asks its question once, at creation: the Locked mode or Test mode choice quoted in the table, which Firebase’s guide to insecure rules follows with a request to configure your rules and secure your data before deploying your app. App Check is the second row: enforcement rejects clients without a valid attestation once you turn it on. What test mode means over time, App Check and the config the browser sees are in is Firebase secure; rule patterns are in Firebase security rules examples.

Lovable’s built-in backend runs on Supabase’s open-source foundation, and Lovable apps enforce data access through Supabase row level security policies, which you can review at the path in the table, so the Supabase rows apply to a Lovable app as well. Project access and website access are independent settings in Lovable’s project visibility docs: one decides who opens the editor, the other who visits the live URL. Whether a Lovable or Base44 app is open out of the box is answered in whether your app is public by default. What Lovable secures for you is is Lovable safe, and the five tests are the Lovable app security checklist.

Base44 names two layers: app visibility, which decides who can open the app, and RLS rules and permissions on each data entity, which decide who reads and writes its records. Its plans and permissions are covered in is Base44 safe.

Replit sets the default by where you build: apps in your personal workspace default to Public, and apps in an organization workspace default to a private option. The full answer is is Replit safe. Keeping development and production data apart, on any of these platforms, is environment variables security risk.

Least privilege in the cloud account, and AWS IAM privilege escalation

AWS IAM privilege escalation happens when an identity uses a permission it holds to gain more, for example by passing a role that has more permissions than the identity itself. The defense is a role per job with named actions, no wildcard permissions, and no long-lived administrator keys in a deployment variable.

In a cloud account, the insecure default is a role or key with more permission than its job: an access key with administrator rights in a deployment variable, a wildcard action, a role any principal may pass (my reading). AWS’s IAM best practices say to “grant only the permissions required to perform a task”, and note that you “might start with broad permissions while you explore”. AWS’s PassRole page adds: “you should make sure that a user doesn’t pass a role where the role has more permissions than you want the user to have.”

The fix is defensive and short. Give each job its own role with named actions, keep root and administrator keys out of deployment variables, and read the findings of IAM Access Analyzer’s external access analyzer. An external access analyzer “is provided at no additional charge”; an unused access analyzer “is a paid feature”. Create the external one in every Region the app uses, because for external access it “analyzes only policies applied to resources in the same AWS Region where it’s enabled.” The rest of the account review is a cloud application security assessment.

The plan tier is a security setting too

A free tier with no automatic backups, a project that pauses, or no point-in-time recovery is a default like the others: nobody chose it, and it decides what you can recover (my reading). Write the tier, and what it keeps, into the table as its own row. Each provider’s backup facts by plan are in the database backup checklist for startups.

How to verify it

Insecure defaults are verified with a before-and-after table and 5 outside checks: the public key reads no protected table, a private file URL fails when logged out, the client bundle holds no privileged key, the share link is closed, and the platform’s advisor lists no open finding for the settings in the table.

The table is your own record: one row per risky default per service, with the old value, the new value and the date. A filled row looks like the illustrative one here.

ServiceSettingValue beforeValue afterDateWho changed it
SupabaseBucket avatars accessPublicPrivate, signed URLs(the day you change it)(a named person)

Then run the outside checks, each from a browser or terminal that has no admin session.

  1. 01 Request a protected table with only the publishable key (or the legacy anon key): the response is an empty list or a permission error, never rows.
  2. 02 Open a private file's plain object URL in a logged-out browser: the file does not download.
  3. 03 Search the built client bundle for sb_secret_ and find nothing; on legacy keys, search for the service_role key's full string instead of a prefix.
  4. 04 Open the editor link and the share or preview link logged out: each is closed unless the app is meant for the public.
  5. 05 Read each platform's advisor or security scan and confirm none of the table's settings shows an open finding.

For check 1, this request is enough; replace the three placeholders with your own project’s values.

curl 'https://<PROJECT_REF>.supabase.co/rest/v1/<TABLE>?select=*' \
  -H "apikey: <PUBLISHABLE_KEY>"

With RLS on and no policy for that role, Supabase returns no rows; with the grant missing, it returns a 42501 permission error. A signed URL is the exception to check 2: anyone holding one can open the file until it expires. Check 3 names the full string because a prefix search is not enough on legacy keys: both the anon and service_role keys are JWTs that begin eyJ. In check 4, a published app meant for the public stays public, and where the plan cannot restrict access (the Lovable and Base44 plan limits in the master table), the record says so instead of a pass. Lovable’s share preview links expire after 7 days by default, so test a fresh one. Supabase’s list for check 5 is the Security Advisor row in the master table.

Re-run the table when a service is added, a plan changes, or the builder regenerates the backend.

In the sprint, deliverable 2.9 is verified this way: record the before-and-after settings for each managed service, naming each risky default and its new value.

Where the sprint does this

Deliverable 2.9, managed-platform security settings, is the item named in the two sprint paragraphs above. Its result goes into the production readiness report, deliverable 13.1, which delivers the result for every scope item, the work completed, and its verification evidence. Hosting, paid tools, and API usage remain in your accounts, and we explain any required third-party costs before enabling them. Every item is listed in the published scope.

Common questions about platform defaults

What are secure defaults?

Secure defaults are the opposite design rule: the out-of-the-box value is the closed one, and access is opened on purpose by someone who meant to open it. For default credentials, one of CWE-1392’s mitigations is “Force the administrator to change the credential upon installation.”

What are security configurations?

Security configurations are the settings of a system that bear on its security, such as who can read a table or a file. Keeping them in a known, agreed state is what NIST calls security configuration management.

What is an example of a configuration?

A configuration is a named setting and the value chosen for it. One example is a Supabase Storage bucket’s access setting: public, and anyone who possesses a file’s URL can open it; private, which is the default for new buckets, and every download goes through access control. The insecure version is whichever value opens more than the app needs, left in place because nobody listed it (my reading).

What is the primary risk of using default?

The primary risk is that a default ships with the product, so it is likely to be known by a potential attacker who is familiar with the product. For default credentials, CWE-1392 adds that “if admins do not change the defaults, it is easier for attackers to bypass authentication quickly across multiple organizations.” On a managed platform, the risk is the same setting on every new project (my reading).