Small bug in Firebase rules simulator

92 views
Skip to first unread message

Zack Morris

unread,
Mar 15, 2015, 5:19:27 PM3/15/15
to fireba...@googlegroups.com
Hi, just wanted to report a small bug (feature?) so other people don’t encounter it. Be careful with escaping the URL in the simulator. If one of your path segments is:

facebook%3A12345

It fails the conditions, but:

facebook:12345

Fails the conditions but shows a *different* error.

Here are the logs from the simulator:

////////////////////////////////////////////////////////////

Attempt to write Success(true) to /users/facebook%3A12345/invites/67890/notification with auth=Success({"id":42,"provider":"anonymous","uid":"server"})
/:.write: "auth != null && root.child('moderators').hasChild(auth.uid)"
=> false
/users
/users/facebook%3A12345:.write: "auth != null &&\nauth.uid == $userId"
=> false
/users/facebook%3A12345/invites
/users/facebook%3A12345/invites/67890:.write: "auth != null &&\n(\n\t(\n\t\tnewData.exists() &&\n\t\t(\n\t\t\tauth.uid == root.child('games').child($gameId).child('owner').val() ||\n\t\t\t(\n\t\t\t\tauth.uid == $userId &&\n\t\t\t\troot.child('games').child($gameId).child('users').hasChild(auth.uid)\n\t\t\t)\n\t\t)\n\t\t&&\n\t\t!data.parent().parent().child('blocked').hasChild(root.child('games').child($gameId).child('owner').val())\n\t)\n\t||\n\t(\n\t\t!newData.exists() &&\n\t\t!root.child('games').child($gameId).child('users').hasChild($userId)\n\t)\n)"
=> false
/users/facebook%3A12345/invites/67890/notification:.write: "auth != null &&\nauth.uid == 'server' &&\ndata.parent().hasChild('fromUser') &&\nroot.child('games').child($gameId).child('users').hasChild($userId) &&\n/* begin server request */\nnewData.val() != data.val() &&\n(\n\t(data.val() === null && newData.val() === now) ||\n\t(\n\t\tdata.isNumber() &&\n\t\t(\n\t\t\tnewData.val() >= data.val() + root.child('constants').child('server').child('timeout').val() ||\n\t\t\tnewData.val() === true\n\t\t)\n\t)\n)\n/* end server request */"
=> false

No .write rule allowed the operation.
Write was denied.

////////////////////////////////////////////////////////////

Attempt to write Success(true) to /users/facebook:12345/invites/67890/notification with auth=Success({"id":42,"provider":"anonymous","uid":"server"})
/:.write: "auth != null && root.child('moderators').hasChild(auth.uid)"
=> false
/users
/users/facebook:12345:.write: "auth != null &&\nauth.uid == $userId"
=> false
/users/facebook:12345/invites
/users/facebook:12345/invites/67890:.write: "auth != null &&\n(\n\t(\n\t\tnewData.exists() &&\n\t\t(\n\t\t\tauth.uid == root.child('games').child($gameId).child('owner').val() ||\n\t\t\t(\n\t\t\t\tauth.uid == $userId &&\n\t\t\t\troot.child('games').child($gameId).child('users').hasChild(auth.uid)\n\t\t\t)\n\t\t)\n\t\t&&\n\t\t!data.parent().parent().child('blocked').hasChild(root.child('games').child($gameId).child('owner').val())\n\t)\n\t||\n\t(\n\t\t!newData.exists() &&\n\t\t!root.child('games').child($gameId).child('users').hasChild($userId)\n\t)\n)"
=> false
/users/facebook:12345/invites/67890/notification:.write: "auth != null &&\nauth.uid == 'server' &&\ndata.parent().hasChild('fromUser') &&\nroot.child('games').child($gameId).child('users').hasChild($userId) &&\n/* begin server request */\nnewData.val() != data.val() &&\n(\n\t(data.val() === null && newData.val() === now) ||\n\t(\n\t\tdata.isNumber() &&\n\t\t(\n\t\t\tnewData.val() >= data.val() + root.child('constants').child('server').child('timeout').val() ||\n\t\t\tnewData.val() === true\n\t\t)\n\t)\n)\n/* end server request */"
269:330: Type error: >= only operates on numbers and strings.
=> false

No .write rule allowed the operation.
Write was denied.

////////////////////////////////////////////////////////////

Notice the last line of the log for facebook:12345 gives a detailed description of why the last rule failed (it was due to me trying to compare true with a number). I also experienced times when it didn’t find a rule for a node at all, and I began to think that my JSON editor was broken. I would see things like:

/users/facebook%3A12345/invites/67890/notification:<no rules>

Even though I verified that I wrote rules for that node. I began to feel like I was in a dream, because I would paste in URLs and see rules working, and other times they would disappear on me. I ended up writing a test rule at root and moving it down, explicitly typing each path segment until I finally realized what was happening.

I can send my details off-list for reproduction if needed, but it should be fairly easy to trigger. I have not tried any other characters in the URL, but I imagine that using a safe escape (that preserves the URL if it’s already escaped), then unescaping it back to its original form should fix the issue.

Thanks,

Zack Morris

Andrew Lee

unread,
Mar 16, 2015, 3:41:47 AM3/16/15
to fireba...@googlegroups.com
Thanks for the report Zach! I'll get our team in charge of the security rules / simulator to take a look, and we'll contact you off list if we need more info.

Thanks!

-Andrew


--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/5CCDDBC1-E67C-4E4B-838A-6DEDAF4D5E98%40gmail.com.
For more options, visit https://groups.google.com/d/optout.



--
Andrew Lee | Firebase Cofounder | and...@firebase.com | (805) 426-9663 

Michael Lehenbauer

unread,
Mar 16, 2015, 10:09:52 AM3/16/15
to fireba...@googlegroups.com
Hey Zach,

You are right, although the field is labeled as "URL", it's actually being treated as a raw path (and not being url-decoded) currently.  We'll get this fixed up.

Thanks!
-Michael

Reply all
Reply to author
Forward
0 new messages