get() on dynamic relation is inconsistent

Issue #893 resolved
Former user created an issue

Using the get() method of a dynamic relation produces inconsistent results. When an object with the given ID is not already in memory, a query is issued which selects only from members of the relation; but when the object is in memory, it's returned regardless of whether it belongs to the relation. This could lead SQLAlchemy users into a false sense of security, and cause them to produce insecure code which gives users access to other users' private data.

I suggest that either get() shouldn't work on queries with existing conditions, or it should always honor those conditions, or it should never honor them.

Comments (5)

  1. Mike Bayer repo owner
    • changed milestone to 0.5.0
    • changed component to orm
    • marked as major

    id vote for get() and load() raising an error on any Query if any existing filtering criterion are present. they really were not meant as "generative" methods, even though they can take advantage of options(), with_lockmode(), etc.

    But this could cause some upgrade pain for lots of folks, so its possible that we'd just have to do a warning for now with the hard change in 0.5.

    I don't think too many people are actually "confused" thinking that get() is honoring existing filtered criterion, and also the potential "security" breach is certainly not limited to "dynamic" relations.

    ill bring it up on sqlalchemy-devel.

  2. Mike Bayer repo owner

    yes, i see what you mean by the cached lookup. Thats the real usage contract here and we have not yet implemented in-python filters so thats not an option here. get()'s main contract is that it won't do any database work if it doesn't have to.

    So Ive changed my mind - get(id) means get that id, so existing criterion should be cleared out. Your test case returns the out-of-band data in all cases now, which is at least consistent. 4580e77da28ee9bf98c109e8f7a81cb569112dcc.

  3. Log in to comment