[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Proposed change to WebGL spec section 4.2 (Security Origin Restrictions)

Indeed this is another option that I would be perfectly happy with, as it is even more flexible for the developer. I thought it might be harder to keep track in this way, but it doesn't seem to be that hard actually.

I think it is worth it, but others may disagree. I think it may not be that uncommon for an application to want to use readpixels for click detection like Gregg mentions, take screenshots, or otherwise get data back from the rendering pipeline. The overlap between those applications and applications that have at least one resource from a different origin is likely to be significant. Given that, it doesn't seem like a good idea to prevent this functionality by keeping it out of the spec when all implementations could support it with some slightly more complicated security logic.


On Oct 4, 2010 10:57 PM, "Gregg Tavares (wrk)" <gman@google.com> wrote:
> On Mon, Oct 4, 2010 at 3:44 PM, Chris Marrin <cmarrin@apple.com> wrote:
>> On Oct 4, 2010, at 2:23 PM, Brian Cornell wrote:
>> > Currently section 4.2 of the specification provides a sufficient but not
>> necessary restriction on readPixels to prevent reading data from other
>> origins. Greater functionality could be given to application developers by
>> slightly increasing the complexity here, while still maintaining the desired
>> security.
>> >
>> > I propose that rather than texImage2D from a different origin or unclean
>> resource causing the canvas to be marked as unclean, it would set a flag
>> marking that texture as unclean, and also set a flag marking the current
>> framebuffer as unclean. Binding a texture would set the flag marking the
>> framebuffer as unclean if the bound texture is marked as unclean. Changing
>> the attached framebuffer would set the flag marking the new framebuffer as
>> unclean if any bound texture is marked as unclean. The origin-clean flag of
>> the canvas would reflect the status of the currently bound framebuffer.
>> >
>> > This would allow developers to read the contents of a framebuffer from a
>> context where different origin images were used, but only in certain same
>> circumstances, such as the following pseudocode:
>> >
>> > create texture A
>> > bind texture A
>> > texImage2D into A with different origin data // canvas, default
>> framebuffer, and texture are all now unclean
>> > draw some stuff using texture A and cached buffers
>> > bind null in place of texture A // canvas and default framebuffer are
>> still marked as unclean
>> > create framebuffer B // framebuffer B is clean
>> > bind framebuffer B // canvas and framebuffer B are marked as clean
>> > draw some stuff using same cached buffers but not texture A
>> > readPixels // this can now succeed because the unclean data has never
>> been connected to framebuffer B
>> > bind default framebuffer // canvas now back to unclean because default
>> framebuffer is unclean
>> > bind texture A
>> > draw
>> > ...
>> >
>> >
>> > This is a significant win over using separate canvases for the two
>> operations if the unclean drawing and the clean drawing share a significant
>> amount of buffered data or clean textures.
>> >
>> > As an example of how this could be used, say you had a 3d game that
>> showed ads on billboards in the game. The ads are served as images by some
>> other domain. You want to include a way to take screenshots in the game. For
>> a screenshot, you use a different framebuffer and don't bind the images for
>> ads, you render a black box or an ad placeholder image from the clean origin
>> instead. You want to reuse all of the buffered data and clean textures for
>> the screenshot, so using a different canvas would be painful and slow. Using
>> this proposed change you would be able to read the pixels from the alternate
>> framebuffer as long as no ad textures were ever bound at the same time as
>> that framebuffer.
>> >
>> > Thoughts?
>> This seems like enough added complexity that it will be hard to maintain
>> security. There are many places where a hole might be discovered to give an
>> author access to the other's origin's pixels. Seems like it would be easier
>> if, in your use case, you simply created a new canvas, initialized it and
>> loaded it with resources, skipping the undesired textures. That keeps things
>> clean and lets you get your screen shot. That's more work and more resource
>> allocation, but keeps the system simple and easier to keep secure.
> It would be rather complex. Here's the list off the top of my head
> It seems like the rules you'd want are
> *) A texture level is marked as "tainted" if an non origin clean
> image/canvas/texture/video is loaded into it with texImage2D or
> texSubImage2D
> *) A texture level is marked as "clean" if a origin clean
> image/canvas/texture/video/arraybuffer is loaded into it only with
> texImage2d
> *) All of a texture's levels are marked as "tainted" if generateMipmap is
> called and level 0 is tainted.
> *) All of a texture's levels are marked as "clean" if generateMipmap is
> called and level 0 is "clean"
> *) If any level in a texture is marked as "tainted" the texture is
> considered "tainted"
> *) When rendering, if an texture used in rendering is marked as tainted
> then:
> *) if rendering to the backbuffer the backbuffer is marked as tainted
> *) if rendering to a framebuffer, all of its renderbuffers and textures
> levels are marked as tainted.
> *) If clear is called and the color mask is true, true, true, true (and if
> there is a depth buffer, the depth mask is true, and if there is a stencil
> the stencil mask is -1) and if scissor is disabled then:
> *) if rendering to the backbuffer the backbuffer is marked as clean
> *) if rendering to a framebuffer, all of its renderbuffers and textures
> levels are marked as clean.
> *) A framebuffer is considered tainted if any of it's current renderbuffers
> or texture levels are tainted
> *) If the current rendering target (framebuffer or backbuffer) is marked as
> tainted then:
> *) calling readPixels will throw SECURITY_ERR
> *) calling copyTexImage or copyTexImag2d will taint the level of the
> texture being targeted
> *) If the current backbuffer is marked as tainted then:
> *) toDataURL will throw SECURITY_ERR
> *) drawImage will mark canvases as non-origin clean
> It does seem like quite a PITA though not that hard. I guess the question is
> is it worth it. It is a common technique to draw using IDs instead of colors
> and then using readpixels to find out which thing you clicked on. As it is,
> that technique will only work if you're serving all the assets. Up till now
> that was probably the most common case but adding 3D to the web might make a
> cross origin case more common. Does CORS like stuff apply to images so a
> server can declare images from it are usable by any domain?
>> -----
>> ~Chris
>> cmarrin@apple.com
>> -----------------------------------------------------------
>> You are currently subscribed to public_webgl@khronos.org.
>> To unsubscribe, send an email to majordomo@khronos.org with
>> the following command in the body of your email: