How to protect VIP, beta and test places in your universe

Clients can teleport to any place in the universe, and content replicates before a kick runs. How to use Secure within universe only and fail closed.

warningLuaudit check: kick-gated-places

What it looks like

A place in the experience is meant for some players only: a VIP lounge, a late-game world, a test place or an unreleased event. Players are only meant to arrive through the game's own teleport, and a server script kicks anyone who joins without the right pass, badge, level or role.

Luau
Players.PlayerAdded:Connect(function(player)
	if not hasVip(player) then
		player:Kick("VIP only.")
	end
end)

How to detect it

  • Look for server scripts that check a player on join and kick them if they don't qualify. These usually mark a place that isn't meant to be open to everyone.
  • Roblox's access control guide says a client can teleport itself to any place in the same universe, whatever the game's own teleports allow, and that turning off **Direct Access** only hides the Join button. Content replicates as soon as the player joins, before a kick runs, so the kick doesn't keep the place's content private.
  • Check whether the audit can tell how **Access Control for Places** is set in the Creator Dashboard. **Secure within universe only** blocks client-started teleports to non-start places. If it isn't visible, say it needs checking.
  • Check the kick fails closed. A pass, badge or group check that errors and lets the player stay, or doesn't run until data loads, leaves a window where they can play.
  • Check what the place gives that matters outside it. Rewards earned there and saved to the shared profile can be collected by anyone who gets in.
  • Test or staging places in the same universe as the live game are the worst case, since their content is unreleased.

What an exploiter could do

They teleport straight into the restricted place. Even if they're kicked, everything in the place has already replicated to them, so unreleased maps, items and scripts can be copied and leaked. If the kick can fail open or arrive late, they also play there and keep what they earn.

How to fix it

  • Set **Access Control for Places** to **Secure within universe only**, so only server-started teleports can reach non-start places.
  • Keep test and unreleased places in a separate, private universe.
  • In the place itself, treat every player as not allowed until a check succeeds, and kick when the check errors as well as when it fails.

Vulnerable example

Vulnerable
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")

local vipPass = 9100002

Players.PlayerAdded:Connect(function(player)
	local ok, owned = pcall(MarketplaceService.UserOwnsGamePassAsync, MarketplaceService, player.UserId, vipPass)
	if ok and not owned then
		player:Kick("The VIP lounge is for VIP members.")
	end
end)

Fixed example

Fixed
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")

local vipPass = 9100002

Players.PlayerAdded:Connect(function(player)
	local ok, owned = pcall(MarketplaceService.UserOwnsGamePassAsync, MarketplaceService, player.UserId, vipPass)
	if not ok or not owned then
		player:Kick("The VIP lounge is for VIP members.")
	end
end)

This only makes the kick fail closed. The place's content can still reach the client before the kick runs, so set **Secure within universe only** as well.

Common false positives

  • A kick for a reason unrelated to protecting a place, such as a full or locked server, a ban or failed data loading, isn't this check.
  • A place where the content isn't secret and the kick just enforces a rule, with **Secure within universe only** set, is fine.
  • The start place is meant to be joined directly, so access checks there protect gameplay, not content. Judge them by the rule they enforce.