-
Notifications
You must be signed in to change notification settings - Fork 7
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
Reject or ignore unknown signature metadata parameters? #38
Comments
Happy new year! (I think we agree, so this just to share/clarify my understanding.)
For signature components: it'll never be possible, the user-agent needs to know what to include from the request. For signature parameters, though: my understanding is that this is the behavior described by RFC 9421, which is possible because parameters are self-contained My intuition is that signature parameters bind/harden/enforce extra requirements on the signature. These extra requirements are signed (great! would be lame if not), and it's fine1 to ignore them otherwise. 1 for some very loose definition of fine, it's of course better to check/validate the values we know about! :)
Having |
I agree with you regarding components. We need to define how they're serialized into the signature base, so there's little we can do when presented with an unknown component other than punting on the signature entirely. For parameters, examples might be helpful. Given the following Signature-Input: sig=("identity-digest";sf);keyid="...";type="sri";unknown="value" 1 above would mean that we generate the following signature base and validate signatures against it:
While 2 above would mean that we ignore the signature entirely. I'm suggesting that it's simplest for developers for us to require the same evolution mechanism for new parameters that we require for key rotation (and components): servers will deliver multiple signatures, one with the new parameter, one without. Those would serialized into distinct signature bases, and the signatures associated with those inputs would likewise be distinct. That is:
To spell it out, this is exactly how we're asking them to support key rotation, wherein two signature inputs would be delivered, one with the old key, one with the new key. That seems straightforward to explain, and is my preference at the moment. |
Thanks for your answers! This matches my understanding of the RFC 👍
I think the important bit here is to note it's possible to check that signature. The My first concern here is the lack of negotiation, servers can't easily tell nor measure which components/parameters are supported - and may have to send increasingly larger headers basically forever. Or, alternatively, they will have to pick two: a weaker signature (without the new signature parameters), and the state-of-the-art one.
(This only gets worse with multiple engines supporting various configurations, so I'll assume the simplest scenario - one engine adding features/support over time.) A Server starts with a simple SRI signature. When Browser v2 is introduced, Server adds support for When Browser v3 is introduced, Server adds support for Second concern, and maybe a worse one: the "upgraded" signature doesn't have to be used? If a browser receives two signatures, a basic one and an "upgraded" one:
User-agents check the first With Finally, not a concern but relevant here: I'm not sure key rotations are impacted/impactful here. To achieve key rotation, websites need to change their <script src="https://my.cdn/script.js"
crossorigin="anonymous"
integrity="ed25519-JrQLj5P/89iXES9+vFgrIy29clF9CC/oPPsw3c5D0bs=
ed25519-xDnP380zcL4rJ76rXYjeHlfMyPZEOqpJYjsjEppbuXE="></script> This key is then copied into the
Servers can use this request header to tell which signature they want to serve; and so, which In this case, servers are free to pick which key to use—rather than always delivering multiple signatures, right? (I suspect this ties back into #23.) |
We may just be quibbling over the pedantic meaning of "ignore" here. :) The When I wrote "didn't have an effect on the signature", I meant something along the lines of the parameter being important to the algorithm that generated the signature. Imagine a silly variant of Ed25519 that allowed developers to select between distinct signature output lengths (because longer is more secure!): that would be impossible to integrate in a backwards-compatible way, as the parameter would effect the signature in ways beyond its presence in the signature base.
Let's take it as given that we're going to add parameters and components. I think we have two ways to approach that invariant:
My experience with option 1 is that it leads to more confusion down the road, and complicates the process of evolving the feature. If we can make 2 work, I'd prefer it. (Note: we do have a third option, which is to say that some addition is large enough that it actually constitutes a new profile: this will likely be the case for algorithm changes, for instance.)
Unfortunately, we're never going to live in a world in which every engine moves in lockstep. So I don't think we can assume away this complexity: we simply must design a system which can deal with divergences in support over time, both across engines and within variants of a given engine. :)
If developers are comfortable with dynamic responses, it seems reasonable to use
In the spec, I've modeled things as multiple steps (https://wicg.github.io/signature-based-sri/#overview). Here, we'd validate each of the signatures upon receipt as "server-initiated signature checks". If they're all valid, wonderful! If not, we can abort the request right away. Then, when we have the body, we'll validate So, in this example, we'd internally validate the constraints we understand in two sets of inputs, generate two signature bases, validate two signatures, etc. New browsers might indeed understand more pieces of
That's correct. I still have primarily an offline-signing model in mind, where servers would bake signatures with two keys into a resource that's then delivered to all requestors. But you're entirely correct that servers interested in dynamic signing would be able to determine which signatures to attack based on the |
Thanks again for your detailed response!
Agreed, my apologies. I'll stop there :)
Aye! Just to offer another scenario, the one I had in mind when I wrote my reply: offline-signing with a "smart" server that picks the right signature(s) for a request. I need to weigh the pros/cons.
This is super helpful. Oops! for missing the plain-English note…
👍 |
Makes sense. I'd certainly be interested in hearing about deployment considerations you run into as we evaluate whether or not this approach is deployable in practice. Again, @ddworken probably will have deployment opinions from Google's perspective (and, presumably @yoavweiss from Shopify's?) which might be worth discussing together at some point. WebAppSec next week, for instance? :)
I'm going to leave this open for a bit to make sure we're not missing anything, but at the moment I think this is where we'll land. |
I think I might have a contrasting opinion here. My concern is that with build-time signing, option 2 may be difficult. For example, imagine we were in a scenario where:
IIUC, with option 2, at build-time we'd need to sign potentially four different signatures, including a new one that is required just for the updated version of BrowserBaz. This isn't impossible, but it does make things more complex and will potentially require rebuilding everything if there are changes in what browsers support what parameters. So I'm wondering: How big is the downside to option 1? It seems like just including the parameters in the signature base even if the browser doesn't understand them is pretty simple? I understand wanting to avoid the CSP complexities, but my (maybe wrong) assumption is that signature params won't ever get as complicated as CSP. |
How would introducing a new profile work? New headers? Negotiated as part of
So once developers need to add two (or more) signatures for varying parameter support, a supporting browser will have to do twice (or thrice) the work to validate signatures? Couldn't that end up having some performance impact?
I share that concern. Option 1 seems significantly simpler from a deployment perspective.
Could we tackle this by other means other than ignoring the signature entirely? E.g. console warnings/devtools issues/reporting? |
Thanks, @ddworken and @yoavweiss! To @ddworken:
Yup. It's an approach that's clearly technically possible as long as we remain in a world where any parameter we add has no effect on signature base generation or signature validation. I gave a toy example above, but let's flesh it out to discuss the implications. (The examples below are wild inventions, not things I think would be valuable: I'm trying to imagine what parameters folks might need (and, secretly, hope we'll never add any! :) ):
I don't think we could support either of these kinds of parameters in a system that accepted unknown parameters as part of the signature, and it's not clear to me how we'd add them in a backwards compatible way.
You'll be shocked to learn that CSP authors also didn't anticipate the complexity of the backwards compatibility decisions we made. :) To @yoavweiss:
It's a variant of option 2 that would change the
Yup. Happily, Ed25519 is pretty quick in this case, as the signature base we're validating over is quite small. In my (very very) limited testing, the perf bottleneck is the SHA-256 hashing, not the signature validation. We should certainly add some telemetry, though.
We should certainly have devtools integration. But Postel was wrong. 🤷 Absent practical implications I'm missing, my preference would be to reject the unknown in a way that doesn't break the known. That general philosophical stance, along with the practical considerations noted above, land me pretty solidly on option 2. That said, all y'all are actually deploying this in the wild. If you all tell me that I'm wrong, I'll listen. :) |
@yoavweiss asked about the behavior for unknown signature parameters, and whether rejecting a signature that contains unknown parameters is the behavior we want.
I think we have a few options here:
We could accept any and all parameters, simply ignoring those we don't understand. I think we'd need to include them in the signature base to ensure that the signature remained consistent between user agents that supported the new parameter and those that didn't, which would only really be possible if the parameters didn't have an effect on the signature (e.g. changing or acting as inputs to the signature algorithm, etc). That doesn't seem like an unreasonable thing to do, but does feel like it can cause some problems (e.g. typoing
expires
would simply break expiration rather than breaking the signature in a way developers would notice).We could exclude signatures that contain new parameters from our defined profile, ignoring them when performing validation. This is what's currently implemented in Chromium's prototype.
Both 1 and 2 allow evolution: 1 by simply adding new parameters to a signature that are transparently ignored in older browsers, 2 by delivering multiple signatures with and without the new parameter.
2 is more or less the same mechanism we'll be using for key rotation, so it's a joint that we're going to expect developers to be familiar with. I think I'm comfortable relying on it for agility here too, but I'd be interested in others' opinions.
The text was updated successfully, but these errors were encountered: