I ran into a bug where private content leaked even though a node access hook was already in place. Opening the node directly returned 403, exactly as intended. But the same content was sitting in the RSS feed, in search results and on taxonomy term pages, available to anyone.
The hook wasn't broken. It checks permissions when someone visits the node page, and on those pages nobody was visiting the node. The content was only being listed, as if everyone had permission to see it.
Drupal has two separate access systems, and they don't talk to each other. This post shows the difference on a throwaway Drupal 11.4 site you can reproduce in a few minutes, compares the ways to fix it, and ends with a two-minute check for your own site.
Two access systems
Single-entity access. When someone opens /node/123 , Drupal asks hook_node_access() . This is where most of us put rules like "only the author and staff can see this".
Query access.…