Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
The entity reference field was committed to core in Feb 2013 and https://www.drupal.org/node/2140237 was issued in Nov 2013 but it was not forward ported.
SA forward-ports are critical.
This problem was found by @Wim Leers in #1959806-58: Provide a generic 'entity_autocomplete' Form API element.
Comment | File | Size | Author |
---|---|---|---|
#35 | 2419923-35.patch | 13.78 KB | amateescu |
Comments
Comment #1
amateescu CreditAttribution: amateescu commentedER in D8 behaves a bit differently than in D7 contrib so we'll need to discuss what's the best way to handle it in D8.
Let's start with a small test that will demonstrate the problem.
Comment #2
amateescu CreditAttribution: amateescu commentedI'll try to elaborate a bit on the differences:
ER in D7 contrib has a
getLabel()
method on the selection handler, which does this:This method is used in all the places that are handling an entity label:
- in the autocomplete matcher (through
getReferencableEntities()
)- in the widgets
- in the formatters
D8 doesn't check if the user has 'view' access on an entity before returning its label in two of those places
- the autocomplete matcher
- the widgets
The D8 formatters are covered (... yay) by
Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase::getEntitiesToView()
.Comment #4
webchickWe wouldn't want to ship a D8 upgrade path beta without this, so tagging.
Comment #5
xjmSA forward ports are critical, so tagging per discussion with @webchick, @alexpott, @catch, and @effulgentsia.
Comment #6
jibranSo this is the commit for sec issue http://cgit.drupalcode.org/entityreference/commit/?id=92747d9. I'll try to have look at it.
Comment #7
jibranWell this took more then an hour. Talked to @larowlan to find the exact sec issue in D8. Added kill method to EFQ after chx advice.
We can move that to follow up but I just want to show the solution here.
Comment #10
Wim LeersSince the newly added
kill()
method doesn't have a symmetricrevive()
method anyway, wouldn't it be simpler/better/cleaner to add aNullQuery
class that always returns the empty result set, which this could then return?That'd also allow us to move this logic to the top of
\Drupal\node\Plugin\EntityReferenceSelection\NodeSelection::buildEntityQuery()
, so that it becomes an early return, making it very cheap in case the necessary permissions are missing.Also, IMO the fundamental problem here is that the node access/grants system does not match the behavior of calling
Node::access()
. That's not fixed in this patch.Comment #12
jibranLet's try test only patch one more time.
Comment #14
jibranAdded Null\Query class as per #10
Comment #15
chx CreditAttribution: chx commentedSince entity query is sorta work for me (as it is a prerequisite for mongodb) I will chime in: the kill method allows for killing in alters and that feels like a very nice thing to have. The lack revive is a feature not a bug. It shouldn't be added. A comment on kill should perhaps mention that what is dead will remain dead (this is not Game of Thrones).
Comment #16
larowlanFor empty methods I think we write {} on the same line ?
Indents wrong
don't » doesn't and we need a comma after content
Is this still needed?
Can you please elaborate @WimLeers? The fail patch from @amateescu doesn't reference any issues with node-access system. @jibran and I looked in depth at the entity query system and the node_access tag is added - so that implies the alter hook is firing. We were chasing that first, and then realised we'd gone down the wrong path - the issue was the 'access content' permission wasn't being considered.
Comment #17
Wim Leers#15: My comment was far from clear, sorry. First: it feels weird that there is no symmetry, but that is indeed a good thing in this case. Second: that doesn't mean somebody in contrib or in custom code won't add it.
That's why I proposed something like NullQuery: it's always going to return the empty result set, and it contains no query data whatsoever, therefore using it would completely and utterly prevent "reviving a killed query".
#16: indeed, the node_access tag is added. Which means the node grants system is ensuring that the query results only contain those nodes accessible by the current user. Unfortunately, the node grants system does *not* match what the entity access/node access system (i.e. the entity and node access control handlers and hooks) marks as accessible of forbidden. Hence:
- having a list of nodes A, B and C and calling ->access() on them may indicate that only A is accessible
- having a query tagged with node_access may indicate that A and B are accessible
Hence, a mismatch.
Berdir described this to me (IIRC) as "query access" versus "render access", but agreed that they *should* behave identically. He argued that it is up to the implementers of hook_node_grants() to ensure things match up. Yet even without any such implementation in core… things don't match up, because the "access content" permission is not taken into account by the node grants system (and hence node_access-tagged queries).
I am quite likely not expressing myself entirely correctly, but I believe that captures the gist of the problem: we have one access system that we use everywhere… except for in queries, which uses another. We can't use it in queries because the system is based on PHP logic, which obviously can't run inside a query. And we want Views to be able to return results that take access into account. So we've ended up with a system that is:
- highly confusing: actually 2 systems
- but the one for queries (node grants) only works for *one* entity type: nodes
- and hence is (IMHO) extremely prone to security problems in the form of information disclosure.
I hope this is at least a mostly accurate description. I hope Berdir can chime in, he can speak about this authoritatively.
Comment #18
larowlanso I think that means this is need work for #17 but to be honest I'm still not sure.
I guess next step is extend this test to enable node_access_test module and see what we get?
Comment #19
BerdirI had a very long comment where I tried to explain all of this. Will try to write that again, but some very short comments here first, will elaborate on them later if necessary.
1. Create a node.
2. Remove access content for anonymous users
3. Edit the view, remove status = 1 and access content permission.
4. Voila, anonymous users can now view content, but if they click on it, they get access denied. Same for unpublished content.
=> That is exactly the same as you get with ER (except it already checks for status).
The actual issue that was fixed in the SA is something else, that was for cases where entities where displayed that did *not* come from a query, e.g. the default value. If anything, then it solved this problem only indirectly, because it would then display 10 suggestions but every single one would say "- Restricted access -". That's stupid :)
The test that you need for that is editing a node that has a reference to an unpublished node, then you should not be able to see the title of that if you can't view unpublished content.
Core simply assumes that you take care of those two things yourself and never allow the user to execute a query for nodes if he does not have the access content permission.
To summarize: I think the current patches are solving not the wrong but a different problem than the SA was about, I'm not sure if we should mix those two things in the same issue. The problem that Wim Leers found is more or less working as designed (stupid design, but still..) and I'm pretty sure that it exists in 7.x as well.
Comment #20
BerdirAlso, I do not think that any of that is an authoritative answer. That's just my opinion/how I understand it.
Comment #21
amateescu CreditAttribution: amateescu commented@Berdir is correct that there are two problems that we need to fix, I said the same in #2.
The entity reference SA was indeed about the widget/form element part and my test-only patch from #1 was testing the autocomplete matcher part.. sorry for the confusion, I thought that fixing both in the same issue would be easier :/
If we want to keep this issue focused only on the widget, then we need to bring #2418249: Consider improving the DX of #default_value for the entity_autocomplete form element in scope in order to fix it on the right level - the new 'entity_autocomplete' form element.
Comment #22
jibran#19 Nice points and now I am official confused. Can someone please elaborate the next step for the patch? After reading #19 I think #17 and #18 are irrelevant to the patch so is it a NR again? And do we need more critical followups to fix #17, #18?
Bring the normal task #2418249: Consider improving the DX of #default_value for the entity_autocomplete form element in scope in order to fix critical bug seems wrong to me.
Comment #23
amateescu CreditAttribution: amateescu commentedIf we want to fix only the widget/form element part in this issue, this patch should do it.
Note that a test-only patch cannot be extracted because the full patch changes how the entity_autocomplete form element handles its default value.
@jibran, why is it so wrong since that's exactly what we have to fix here?
@Berdir:
I also think that's not the best way to handle the return value of the autocomplete matcher, that's exactly why my initial test-only patch in #1 expects an empty output from the matcher instead of an array of "- Restricted access -" matches :)
Comment #24
BerdirNice work!
$key that then becomes $entity_labels is a bit confusing, why not use $label instead?
Comment #25
amateescu CreditAttribution: amateescu commentedBecause I'm lazy and I like to copy-paste stuff :D
Comment #27
Berdir:)
I think this is more or less ready to go, but I'm sure Wim can find a few nitpicks.
How do you think we should continue with the other issue?
Open a separate issue I guess, probably a critical? My recommendation would be to make the issue very specific as a start, with the option for a generic fix? Something like "access content permission is not considered for menu link path autocomplete?"? A generic fix might not be easy, we're missing a 'list' entity access operation/method, so we would have to route it through the selection plugins or introduce a new entity list access (related: #2409691: EntityAccessControlHandlers miss entity admin access).
Yet another issue that we should open I guess is whether the default node/file/user/comment query altering should consider the access content permission and/or publication status (this might also be another approach to fix the previous issue) but I don't think that needs to be critical, it has been like that for multiple version, so can't be suddenly release blocking for D8? (would not be the first time to decide that, though ;))
Comment #29
amateescu CreditAttribution: amateescu commentedHmm.. more or less? Why less?! :P
We definitely need to open a sibling issue for the autocomplete matcher, but I'm not very fond of the "very specific" approach for starting it :/ How about a meta or "discussion only" issue and then open sub-issues for each core entity type?
Comment #30
BerdirWorks for me as well. My argument for a specific critical issue is that I'm not sure what exactly is critical. I don't think that moving the file status check to a file_access query alter is a critical thing that we need to fix, for example. I'm not even sure it is desired, unlike node status, files have no permission to see or not see temporary files, except some very specific logic in file_file_download(), so the fact that FileSelection does that is pretty custom.
So having a specific, targeted critical would allow for a quickfix, but we can always decide to go that way and start with a critical meta issue. Just worried a bit that we might discuss that for quite some time...
Comment #31
jibranThis can work as a test only patch.
ok, fine by me. :)
Comment #32
dashaforbes CreditAttribution: dashaforbes commentedIt's working for me.
Steps:
Comment #34
jibranComment #35
amateescu CreditAttribution: amateescu commentedIn case anyone is confused, the patch to review is the one from #29. Maybe re-uploading it will draw a final review/rtbc :)
Comment #36
jibranOh I meant to RTBC in #34. Above patch doesn't contain a single loc written by me so I think I can RTBC. @Berdir is happy in #30, we have manual testing in #32 and we have a fail patch so RTBC.
Comment #37
jibranCan we please add default value change in change notice New 'entity_autocomplete' form element added?
Comment #38
amateescu CreditAttribution: amateescu commentedYes, the change notice will need to be updated after the patch gets in.
Comment #39
alexpottThis issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes.
Committed ade57a9 and pushed to 8.0.x. Thanks!
Let's update the CR :)
Comment #41
amateescu CreditAttribution: amateescu commentedYay! Updated the CR: https://www.drupal.org/node/2418529/revisions/view/8095975/8135945