We have a huge site with lots of pages and nesting. If you've ever used Sitefinity's permission editor you can appreciate how absolutely painful it is to navigate that UI. It's incredibly slow, and there's absolutely no way you're going through every. single. page.

So I came up with a quick SQL script to audit the custom page permissions. It'll show you basically broken permissions, not inherited on every page... which is what you should be wanting, but you'll also see the parent pages incase pages have the same name somewhere in the structure.

sp_getPagePermissions.sqlView on GitHub
CREATE PROCEDURE [dbo].[sp_getPagePermissions]
AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;

-- Insert statements for procedure here
SELECT        sf_permissions.object_id AS 'page_node_id', sf_permissions.principal_id AS 'user_id',
                     sf_sitefinity_profile.nickname, sf_page_node.title_ as 'title', sf_page_node.url_name_ as 'url_name', sf_page_node_1.title_ AS 'parent_title', sf_page_node_1.url_name_ AS 'parent_url_name',  sf_permissions.grnt, sf_permissions.[deny], sf_permissions.last_modified, sf_permissions.voa_version
FROM            sf_permissions INNER JOIN
						 sf_user_profile_link ON sf_permissions.principal_id = sf_user_profile_link.user_id INNER JOIN
						 sf_sitefinity_profile ON sf_user_profile_link.profile_id = sf_sitefinity_profile.id INNER JOIN
						 sf_page_node ON sf_permissions.object_id = sf_page_node.id INNER JOIN
						 sf_page_node AS sf_page_node_1 ON sf_page_node.parent_id = sf_page_node_1.id
WHERE        (sf_permissions.set_name = 'Pages') AND (sf_user_profile_link.user_profile_type_name = 'Telerik.Sitefinity.Security.Model.SitefinityProfile')
order by sf_page_node_1.url_name_, sf_page_node.url_name_

END GO

There's one change you might need to make, and that's to link it to sf_users instead of through sf_user_profile_link. I have it through there because we're on Ldap and there's nothing in sf_users, but every user has a profile so I can sneak out the nickname through that (nickname is the email).

So from here just call it into SQL, OR expose it through a ServiceStack service, or directly from backend code into a custom widget, it's quite fast to execute.

Enjoy!