node_access called with $op='update' or 'delete' returns TRUE, even when grant records for that node in the node access table are all zero for fields grant_update and grant_delete, and when no records exist in the node access table with nid=0.

I would expect node_access to return false, prohibiting editing and deleting, when grant_update and grant_delete are 0 (and no node access records with nid=0 override this).

To reproduce: set up node access with the private module (as a convenient way to set the grants). Modify the function private_node_access_records to always set grant_update and grant_delete to false. Install the devel module as a convenient way to check the node access records.

In a test account with just authenticated user privileges, create a page and mark it as "private". (This triggers the code in private_node_access_records that sets the grants.) Under the admin account, load the node and verify that all access records show grant_update and grant_delete as 0.

Go back to the test account, and view, then edit the node. Proper behavior should be to not allow editing.

I checked this by sticking watchdog calls to display the $node->nid and $op in various places in node_access (at the top of the function, just before the call to node_content_access, and just after $sql is set). Sure enough, every time control gets all the way to building the sql statement, $op is always "view" -- not "update". It appears that $op is being reset from 'update' to 'view' along the way, and thus allowing update and delete access regardless of the grant settings.

It looks like node_access is being called repeatedly for every page load, and perhaps recursively, but I can't figure out how $op='update' at the top of node_access gets changed to $op='view' by the time you get down to building the sql statement. If anyone knows this code better than I can figure out and shed light on this, please do.

Since the node module behaves differently than one would expect from grants, I've entered this as a bug. And since it potentially exposes data that people would expect to be protected, I've marked it as "critical".

My environment: Drupal 5.7, MySQL 4.1.22, PHP 4.4.8 running on a linux shared host. Problem also occurs under php 5. Apache/1.3.41 (Unix) mod_fastcgi/2.4.2 PHP/4.4.8 mod_auth_passthrough/1.8 mod_log_bytes/1.2 mod_bwlimited/1.4 mod_gzip/1.3.26.1a FrontPage/5.0.2.2635 mod_ssl/2.8.31 OpenSSL/0.9.7a. No other node access modules installed.

Thanks -- let me know if I can provide any other information.

Comments

drumm’s picture

Status: Active » Closed (works as designed)

I am unable to reproduce this following the instructions above. Clicking Rebuild permissions on admin/content/node-settings should clear up any stale access rules, for example if private module was edited after it was enabled.

If this is verified, or you find another potential security issue, please follow the instructions at http://drupal.org/node/101494, and do not post the issue publicly.