-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Iteration over Tables does not randomize the order #12070
Comments
I've said it before, people are much better off using tree structures for these things instead of playing whack-a-mole with hash algorithms. |
In the Rust discussion I've linked there are two topics - first the hash map algorithm itself and second the randomization when iterating. Randomization is the thing I'd definitely like to have by default in Nim. The hash map algorithm itself is a different beast and I don't want to bring it in discussion here. Would you consider specifying in the Nim 1.0 that the iteration order on |
I think you miss the entire point here. The reason for iteration randomization is to prevent people from playing "whack-a-mole with hash algorithms". I've said it before, Go does the same thing and I think it is a good solution to prevent people from depending on the iteration order of hash tables. |
Yeah, we discussed this before, I think Go's solution is terrible. Python's is much better. |
Just to clarify - Nim has |
And how do you prove its security? That is far from being easy. If security is a concern, use a BTree, maybe an OrderedTable and stay away from "O(1) fast hashing". The O(1) on average is what creates all the trouble. |
I'd say the reasons aren't that technical, but I'm rather concerned with all the issues which e.g. the switch from python2 to python3 (and analogically from golang 0.x to 1.x) caused - just because people relied upon "iterating the map twice in a row yields the same order" and often even "iterating a map once is actually like iterating an ordered map with preserved insertion order". I don't know about any compile-time way how to catch such wrong assumptions (which are way more common than one would guess) - therefore this runtime solution. |
If it really is common, the module's documentation yelling at users not to do so in the first paragraph is the easiest solution. |
This never worked - it has to yell at "edition time" or compile time or at the latest in runtime. Yelling in "edition time" could be achieved by making the default |
We could also deprecate the table's iterators. :-) |
I'm confused - I meant my words seriously, not as a joke. Feel free to close this issue if the topic is not a priority for Nim. |
I think we just need a separate |
I was serious too. |
Sounds good to me (assuming a compile-time warning). |
@dumblob but that's not quite good: iterating is a completely valid usage of even unordered tables, iterating and using the order is not really: the second one is basically impossible to catch tho in an automatic way as it's related to the intentions/assumptions of the user . I guess warning might be ok, but it seems wrong to me |
@alehander42 sure, iteration is valid even on unordered maps - but if we don't want to change |
It seems there are 2 issues raised here:
and
An easy way to solve the 2nd issue is to start iterating at a random slot instead of always starting at slot 0. Something like:
I tried this in the tables.nim code - works fine. It doesn't address the attack scenario, but does prevent users from relying on a specific iteration order, which could be a good thing to avoid perceived compatibility problems if a table implementation or hash function changes in a future release of Nim, as you mentioned. |
IMO we should close this issue as a wont-fix, unless someone can show a benchmark illustrating the problem with nim's current implementation (or even #13440) which differ from rust's implementation IIUC and shouldn't be affected by the "Without an attacker" case at least
Uses cases where you care about robustness against adversarial inputs are not the common case, and shouldn't impact the common case. |
Thanks @timotheecour for the heads up. I see you did a lot of work on I still feel there is too much low hanging fruit here compared to radically saying "won't fix".
Btw. it seems to me some of the changes you made to |
I'm closing this because there is no reasonable actionable item, feel free to re-open this issue if you have an update involving one or a reproducible bug involving afore mentioned attack vector but involving nim code instead of rust code; the algorithms used differ. the changes recommended here involve breaking changes (eg renaming tables) that don't provide value. The attack mentioned revolved around a library in rust, not in nim. See #13440 for a better alternative, with benchmarks to support it. |
Yep, this is what I meant with saying you did a lot of very valuable work on So again - it seems to me some of the changes you made to |
indeed, both #13440 and the (more expensive) Dealing against adversarial attacks is much harder and needs a threat model in order to do something about it; I don't think it can be done without sacrificing something else (eg performance for the common case not involving adversarial attack). The "With an attacker" scenario described in rust-lang/rust#36481 doesn't seem realistic though; if a production grade server returns all the data to a client for some requests, it should have safeguards in place against leaking internal logic. Lots of mitigation strategies can be used, eg hashing with a salt, or adding a randomized order iteration in tables.nim (which shouldn't be the default for obvious reasons). Note that with |
Didn't think of this - could this also be mentioned in the doc of |
no reason it should be mentioned in Table, because of separation of concerns. The feature is general purpose and applicable in all cases where you need private access and don't care about having your code broken by upstream changes (in particular is applicable for private code, or for visibility violations within the same project for which you control the code, or debugging, as example use cases) |
Iterating over Tables is insecure (prone to attacks) - see the discussion rust-lang/rust#36481 .
Example
N/A
Current Output
N/A
Expected Output
N/A
Possible Solution
Potentially good solution in the comment rust-lang/rust#36481 (comment) . Some languages (e.g. Dao) additionally provide for performance reasons a choice at instantiation time whether the order shall be undefined or random (or the insertion order, but for that there is a different type in Nim).
Additional Information
Would be wise to solve/define before the final
1.0
.The text was updated successfully, but these errors were encountered: