The field_access() function only checks field permissions - not entity permissions. So, field_access('edit', ...) can return TRUE even if the user doesn't have access to edit the entity.

This means that contrib modules are supposed to check entity access (for example with the Entity API contrib module's entity_access()) before checking field_access(), however, this is very easy to overlook (and most users assume it isn't necessary) leading to at least one highly critical security vulnerability in contrib.

Proposed solution: improve the API docs of the field_access() function to clearly state that it will not take entity access into account. The caller must make sure beforehand that entity access is respected.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

klausi’s picture

Title: Document that field_access() does not entity access checks » Document that field_access() does no entity access checks
David_Rothstein’s picture

Version: 7.x-dev » 8.x-dev
Component: field system » documentation
Priority: Normal » Major
Status: Active » Needs review
Issue tags: +Needs backport to D7
FileSize
1.4 KB

This should get the issue a little more visibility, and it affects Drupal 8 too so here's a patch.

jhodgdon’s picture

That seems like good documentation.... clear and concise. Can someone verify its accuracy?

Berdir’s picture

Looks good, the main entry point for this is probably something like $entity->field->access(), which is on FieldItemList, which directly implements AccessibleInterface. Should we add this to FieldItemList or so as well, or in a more general way to AcccessibleInterface? Note that that interface is implemented both by entities and by fields.

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Documentation

Yes, if there are methods on those other interfaces that need documentation that people writing classes implementing the interfaces would need to know, it should be added there too. Until that is determined... I guess I'll go ahead and mark this RTBC, since it is a good patch and apparently accurate... If anyone has specific suggestions of where the additional docs should be added to other interfaces, you can either set back to "needs work" and explain, or we can file a separate issue. Thanks!

webchick’s picture

Just to play devil's advocate, is there a reason we don't build in entity access checking so the method works as people would expect..?

Berdir’s picture

Because the 90%+ use case for checking field access is when you already know that the user has access to the entity, and you usually check all the fields, when an entity is viewed/edited/requested on REST or so. Then you loop over all fields and check access and it would be overhead to check access to the entity every time.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 2: document-field-entity-access-2267411-1.patch, failed testing.

jhodgdon’s picture

Issue tags: +Needs reroll

Needs reroll apparently...

JacobSanford’s picture

Issue tags: -Needs reroll

Looks like the patch in #2 has already been committed to 8.x: it doesn't apply in tests because it is there!

jhodgdon’s picture

Version: 8.x-dev » 7.x-dev
Status: Needs work » Patch (to be ported)

It looks like it was committed by webchick:
http://cgit.drupalcode.org/drupal/commit/core/lib/Drupal/Core/Entity/Ent...

For whatever reason, she didn't update the issue and the auto-message didn't either.

er.pushpinderrana’s picture

Status: Patch (to be ported) » Needs review
FileSize
677 bytes

Attached Patch for D7. Please review.

Status: Needs review » Needs work

The last submitted patch, 12: drupal7-document-field-entity-access-2267411-12.patch, failed testing.

Status: Needs work » Needs review
klausi’s picture

Status: Needs review » Needs work
+++ b/modules/field/field.module
@@ -961,6 +961,11 @@ function field_has_data($field) {
+ * This method does not determine whether access is granted to the entity
+ * itself, only the specific field. Callers are responsible for ensuring that
+ * entity access is also respected, for example with the Entity API contributed
+ * module check entity_access() before checking field_access().

The example should be node_access() first for nodes (which is in core) and entity_access() second with the reference to the Entity API module.

er.pushpinderrana’s picture

Status: Needs work » Needs review
FileSize
752 bytes
818 bytes

@klausi, Thanks for your valuable suggestion. Please review updated patch.

jhodgdon’s picture

Status: Needs review » Needs work

Um.... I don't think we should be referring to calling a function in a contrib module here.

Also, the grammar/punctuation here is not quite right:

+ * entity access is also respected, for example with the nodes, check
+ * node_access() before checking field_access() and with the Entity API
+ * contributed module check entity_access() before checking field_access().
+ *

This should say "... respected. For example, when checking field access for nodes, check node_access() before checking field_access()." and then leave off the part about the Entity API module.

Berdir’s picture

I don't see a problem with that as long as it's explicitly mentioned. Entity API is a top 10 module and the standard for almost any entity type and entity integration in contrib and it's the base for what we have in Drupal 8.

jhodgdon’s picture

OK. Please make it into 2 sentences, using grammar like in #17 then.

er.pushpinderrana’s picture

Status: Needs work » Needs review
FileSize
781 bytes
925 bytes

Did changes in this patch as mentioned in #17, #18 and #19. Please review.

amitgoyal’s picture

Minor fix,

For Example -> For example

jhodgdon’s picture

Status: Needs review » Needs work

If we are going to mention a function that is part of the Entity API contrib module (not Drupal Core), like entity_access(), then we absolutely need to mention the Entity API contrib module. So in that second part:

 * nodes, check node_access() before checking field_access() and when checking
+ * field access for entities, check entity_access() before checking
+ * field_access().

should be:
... before checking field_access(), and when checking field access for entities using the Entity API contributed module, check entity_access()...

(also note the comma before "and")

Sorry for the confusion!

amitgoyal’s picture

Status: Needs work » Needs review
FileSize
822 bytes
839 bytes

Please review updated patch with fixes in #22.

jhodgdon’s picture

Status: Needs review » Needs work

Oh, one more thing: At the beginning it says "This method...". It's a function, not a method.

Other than that, looks good, thanks!

er.pushpinderrana’s picture

Status: Needs work » Needs review
FileSize
681 bytes
824 bytes

Fixed! Please review.

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community

That looks fine to me now, thanks!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 25: drupal7-document-field-entity-access-2267411-25.patch, failed testing.

Status: Needs work » Needs review
dcam’s picture

Status: Needs review » Reviewed & tested by the community

Resetting this back to RTBC.

jhodgdon’s picture

Status: Reviewed & tested by the community » Fixed

Thanks again! Committed to 7.x.

  • jhodgdon committed f56b6aa on 7.x
    Issue #2267411 by er.pushpinderrana, amitgoyal, klausi, David_Rothstein...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.