Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Introducing PermPilot: audit who can view and edit every Confluence page

Confluence Cloud has no report that answers "who can access this?" across a space. Premium lets you inspect one user at a time. On Data Center you could query the database directly. On Cloud that option is gone.

I built PermPilot to close that gap. This post covers what it does, the specific problem it catches, and two design decisions that mattered more than I expected.

The problem it exists for

In Confluence, view restrictions inherit down the page tree. Edit restrictions do not.

So a page can be correctly hidden from most of the company, while everyone who can still see it is also able to edit it. There is a padlock. It looks locked down. It is not.

Handbook (view restricted to: HR group)
 └── Compensation Bands        <- inherits the view restriction, no edit restriction
      └── 2026 Salary Review    <- same

Everyone in HR can read those pages, which is intended. Everyone in HR can also quietly rewrite the salary bands, which usually is not. Nothing in Confluence surfaces this. You would only find it by opening Restrictions on every page and comparing the view list against the edit list by hand.

I wrote up the native ways to find this, and where they run out, in How to audit who can view and edit every page in Confluence Cloud.

What PermPilot does

One click, for a single space or the whole site:

  • Every page, with the path showing where it sits
  • Who can view it and who can edit it, side by side
  • Findings graded by severity
  • CSV export for your audit file

What it flags

  • Critical — pages hidden from view with no edit lock. The case above, and the one most access reviews miss.
  • High — guest or external accounts with access to restricted content.
  • Medium — restrictions that still name people who have left. These pile up quietly and make a review look thorough when it is not.
  • Low — pages locked for editing but readable by everyone.

Two design decisions worth explaining

1. It reads as you, not as itself

An app can read Confluence in one of two ways: as the app, or on behalf of the person using it. That sounds like a detail. It is not.

An app reading as itself is not on anyone's restriction list. So restricted pages are simply invisible to it. It would scan a space full of locked-down pages, never see the locked-down ones, and report that everything looks fine.

In other words, an auditing tool built the obvious way would skip exactly the pages you most need audited.

PermPilot always reads on behalf of the admin running the audit. It sees precisely what you would see if you opened every page yourself, and nothing you are not already entitled to see.

For developers: this is asUser() rather than asApp(), and it is the single most important implementation detail in the app.

2. Nothing leaves your site

PermPilot makes no outside connections at all. No page content and no permission data is sent anywhere. It qualifies for Atlassian's Runs on Atlassian programme.

For a security tool that matters more than it might sound. It means the app can usually clear a customer's security review without a data processing agreement to negotiate, and that negotiation is normally what stalls anything touching permissions.

The trade-off is real: no email alerts, no outside processing, no integrations with anything. For this kind of tool it is worth it.

Read only, always

PermPilot never changes permissions. It cannot: it has no write access at all. It shows you what to fix and leaves the fixing to you, which is the right split for a tool whose entire job is telling you the truth about who can reach what.

Availability

PermPilot is available now for Confluence Cloud.

Try PermPilot on the Atlassian Marketplace

If you audit Confluence permissions and there is a case it does not catch, I would like to hear it. That feedback is the most useful thing I can get right now.

1 comment

Peter Hallander _Stackedboost_
Atlassian Partner
July 26, 2026

Here is the shape I would use, since I offered.

Pick two pages that do not matter: one child of a view-restricted parent, and
one page that already has its own edit restriction. Record the before state of
both, either by opening Restrictions on each or by reading:

/wiki/rest/api/content/{id}/restriction/byOperation?expand=read.restrictions.user,
read.restrictions.group,update.restrictions.user,update.restrictions.group

The expand path matters more than it looks. The shorter restrictions.user form
silently returns nothing, which will have you believing a page is unrestricted
when it is not.

Apply your change to the first page only, then re-read both. The second page is
your control: if anything moved on it, your selection logic is wrong, and it is
much better to learn that on two pages than on fifty.

Two failure modes worth watching for specifically. There is no ETag on that
endpoint, so nothing stops you overwriting a restriction someone changed after
you built your list, which is the argument for re-reading each page immediately
before writing it. And where a page needs several principals added, a partial
failure leaves it looking locked while only half applied, which is worse than
never having started.

PermPilot does this, so if you would rather not script it, that option exists.
https://marketplace.atlassian.com/apps/941628983/permpilot

Either way, the two-page control test above is the part I would not skip.

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events