WEBVTT 00:00.000 --> 00:05.000 Hello, everyone. 00:05.000 --> 00:10.000 We're going to start the second talk for the package manager 00:10.000 --> 00:14.000 Devroom. My name is Exigner, and we're going to talk about the 00:14.000 --> 00:18.000 current state of attestations in programming language ecosystems. 00:18.000 --> 00:22.000 So first, we're going to talk about the two attestation types that 00:22.000 --> 00:26.000 these ecosystems have been adopting over the past three years or so. 00:26.000 --> 00:31.000 We're going to go through a tour of the different package repositories and 00:31.000 --> 00:34.000 how you can get this information from them to use in your own 00:34.000 --> 00:36.000 security incident response. 00:36.000 --> 00:39.000 Most of these implementations are very similar, but there's also a few 00:39.000 --> 00:41.000 differences to call out. 00:41.000 --> 00:43.000 And then we're going to talk a little bit about sort of like the 00:43.000 --> 00:47.000 near-term future and the longer-term future with the attestations. 00:47.000 --> 00:50.000 What are the sort of like next steps and what sort of future 00:50.000 --> 00:53.000 direction are we looking at here? 00:54.000 --> 00:57.000 Okay, so first of all, we're going to talk about build 00:57.000 --> 00:58.000 provenance. 00:58.000 --> 01:02.000 As far as I know, this is a net new capability, security 01:02.000 --> 01:06.000 capability across ecosystems, and it provides a very easy way for 01:06.000 --> 01:10.000 us to connect a package with a specific hash to the exact 01:10.000 --> 01:14.000 source code, build instructions, and build logs in a 01:14.000 --> 01:16.000 non-falsifiable way. 01:16.000 --> 01:20.000 So this is really a tremendous tool that we can use for 01:20.000 --> 01:21.000 instant response. 01:21.000 --> 01:24.000 You have some binary on disk, and you're like, where the 01:24.000 --> 01:25.000 heck did this come from? 01:25.000 --> 01:26.000 What's the source code? 01:26.000 --> 01:27.000 How is it built? 01:27.000 --> 01:31.000 Can I go and look in that for malicious behavior? 01:31.000 --> 01:36.000 We almost all of the ecosystems are using salsa build 01:36.000 --> 01:39.000 provenance, so the specification for it can be found on 01:39.000 --> 01:43.000 the salsa.dev website. 01:43.000 --> 01:46.000 And then the other attestation we're going to be talking about 01:46.000 --> 01:49.000 today is release attestations. 01:49.000 --> 01:52.000 This is more recent, and so it goes by a couple of different 01:52.000 --> 01:53.000 names. 01:53.000 --> 01:56.000 Several ecosystems call these publish attestations, but 01:56.000 --> 02:00.000 this is what we traditionally think of as the job of a 02:00.000 --> 02:01.000 package repository. 02:01.000 --> 02:04.000 We're mapping a specific package name, a specific 02:04.000 --> 02:07.000 version string, and we want to know exactly what 02:07.000 --> 02:10.000 packages we should be expecting with the hash, so that 02:10.000 --> 02:12.000 we know that they weren't tampered with. 02:12.000 --> 02:15.000 I do a lot of work in the NPM ecosystem. 02:15.000 --> 02:17.000 There's a one-to-one mapping. 02:17.000 --> 02:19.000 If you have a package name and a version string, it's just a 02:19.000 --> 02:23.000 single package, but many other ecosystems provide the 02:23.000 --> 02:25.000 ability to have several packages. 02:25.000 --> 02:27.000 Maybe you're building for the very popular doors of 02:27.000 --> 02:29.000 11 ecosystem. 02:29.000 --> 02:33.000 And so build the provenance or sort of release 02:33.000 --> 02:36.000 attestations doesn't require a one-to-one mapping. 02:36.000 --> 02:39.000 It can be a one-to-many mapping, as many different 02:39.000 --> 02:42.000 artifacts as you want. 02:42.000 --> 02:46.000 This release attestation is defined by the 02:46.000 --> 02:47.000 Intodo project. 02:47.000 --> 02:50.000 We'll see that some ecosystems have their own 02:50.000 --> 02:53.000 definition for publisher release attestations, but if you 02:53.000 --> 02:55.000 are looking to use this in the future, I would really 02:55.000 --> 02:59.000 recommend using the Intodo attestation 02:59.000 --> 03:01.000 predicate type here. 03:01.000 --> 03:03.000 And if you follow that URL, there are sort of like 03:03.000 --> 03:05.000 details on the specification and 03:05.000 --> 03:06.000 invitation, that sort of thing. 03:06.000 --> 03:09.000 All the must-shoulds and nice to have. 03:09.000 --> 03:12.000 Okay, so these two attestation types, they're like 03:12.000 --> 03:15.000 different, but they're also very linked. 03:15.000 --> 03:20.000 So if you put them together, you can follow this sort of 03:20.000 --> 03:22.000 really interesting chain of information. 03:22.000 --> 03:24.000 First, you could say, okay, I want to know this package 03:24.000 --> 03:26.000 name, this version string, what should contain? 03:26.000 --> 03:28.000 I get back a list of hashes. 03:28.000 --> 03:30.000 You can take those hashes and feed them into 03:30.000 --> 03:33.000 build provenance, and then get back the exact source 03:33.000 --> 03:35.000 code and build logs for them. 03:35.000 --> 03:38.000 So, you know, these are like very similar, sometimes 03:38.000 --> 03:41.000 confusingly similar, but really the two of these 03:41.000 --> 03:44.000 capabilities are meant to link together and sort of 03:44.000 --> 03:47.000 provide you this trail of evidence that you can follow to 03:47.000 --> 03:51.000 figure out how a given package was built. 03:51.000 --> 03:54.000 So, I thought it was really funny that Adam was talking about 03:54.000 --> 03:55.000 an attack on PIPI. 03:55.000 --> 03:57.000 I'm also going to talk about an attack on PIPI. 03:57.000 --> 04:00.000 This is not at all to throw shade at PIPI. 04:00.000 --> 04:02.000 The reason why we keep bringing it up is because 04:02.000 --> 04:05.000 they do a really excellent job of writing blog posts 04:05.000 --> 04:08.000 with instant response and talking about not only the 04:08.000 --> 04:10.000 attack, but the mitigations that took place. 04:10.000 --> 04:13.000 So, Adam was talking about an attack in 2025. 04:13.000 --> 04:17.000 This attack was in late 2024 against a package called 04:17.000 --> 04:19.000 ultra-littics. 04:19.000 --> 04:24.000 Version 8.3.40 was a normal release, and it had this 04:24.000 --> 04:27.000 build provenance information, and then the community 04:27.000 --> 04:31.000 noticed that on the source control platform, someone 04:31.000 --> 04:36.000 made a pull request and the name of the branch for the 04:36.000 --> 04:39.000 pull request looked like it was an injection attack. 04:39.000 --> 04:43.000 And sure enough, when they went to PIPI, there were two 04:43.000 --> 04:46.000 new versions of this package published. 04:46.000 --> 04:48.000 Version 41.42. 04:48.000 --> 04:52.000 It still had build provenance, but it also included 04:52.000 --> 04:53.000 malicious code. 04:53.000 --> 04:56.000 And the community was able to determine that quickly because 04:56.000 --> 04:58.000 of the build provenance information. 04:58.000 --> 05:01.000 They were able to look at the source code. 05:01.000 --> 05:03.000 They were able to look at the build logs and the build 05:03.000 --> 05:06.000 instructions and find that malicious behavior. 05:06.000 --> 05:10.000 So, then the community, this package was able to 05:10.000 --> 05:16.000 regain access to the package in the source control. 05:16.000 --> 05:18.000 But during the attack, the attackers also 05:18.000 --> 05:21.000 exfiltrated the PIPI API keys. 05:21.000 --> 05:25.000 So, then versions 43 and 44 were published directly 05:25.000 --> 05:28.000 with those exfiltrated API keys. 05:28.000 --> 05:30.000 So, did not have a build provenance. 05:30.000 --> 05:32.000 And so, it's important to note here that just because 05:32.000 --> 05:34.000 the package has a build provenance doesn't mean it's 05:34.000 --> 05:36.000 not secure or if it doesn't have build provenance doesn't 05:36.000 --> 05:37.000 mean it's not secure. 05:37.000 --> 05:40.000 All we're providing here are links to source code and build 05:40.000 --> 05:41.000 instructions. 05:41.000 --> 05:43.000 You still have to follow those links and make your own 05:43.000 --> 05:45.000 sort of like security decision. 05:45.000 --> 05:48.000 However, it is very suspicious when a package is using 05:48.000 --> 05:49.000 build provenance and then stops. 05:49.000 --> 05:50.000 I would call that a yellow flag. 05:50.000 --> 05:52.000 So, again, I'm not saying it's, you know, 05:52.000 --> 05:55.000 bad or malicious, but that's definitely a signal that 05:55.000 --> 05:57.000 is worth following up. 05:57.000 --> 05:59.000 And so, then after the maintainers, we established 05:59.000 --> 06:02.000 control both of their source management and also 06:02.000 --> 06:06.000 in PIPI, they published version 45, which 06:06.000 --> 06:08.000 should not contain that malicious behavior. 06:08.000 --> 06:12.000 So, this is an example of why build provenance is useful 06:12.000 --> 06:16.000 in an attack to do incident response and why we've seen it 06:16.000 --> 06:20.000 be adopted in so many different ecosystems. 06:20.000 --> 06:24.000 Okay, so let's talk a little bit about build provenance 06:24.000 --> 06:28.000 works and that will make the examples of how to get this 06:28.000 --> 06:30.000 information in ecosystems make a lot more sense. 06:30.000 --> 06:33.000 So, this is really winding back the clock, at least 06:33.000 --> 06:35.000 from a technology perspective. 06:35.000 --> 06:39.000 Five whole years ago, many build systems started adding 06:39.000 --> 06:43.000 this concept of a signed workload identity so that during 06:43.000 --> 06:46.000 your build process, you can request this, usually it's in 06:46.000 --> 06:49.000 like an OIDC token and then that OIDC token contains 06:49.000 --> 06:51.000 all of the build provenance properties we care about 06:51.000 --> 06:53.000 the source code, build instructions, etc. 06:53.000 --> 06:58.000 So, our goal is to transform the signed OIDC token 06:59.000 --> 07:02.000 and we want to have that information available 07:02.000 --> 07:04.000 when we sign our package. 07:04.000 --> 07:09.000 And then the signature is in an X519 certificate and so 07:09.000 --> 07:13.000 we'll go in the extensions and we have a couple of OIDs 07:13.000 --> 07:17.000 for build provenance and we just sort of map the information 07:17.000 --> 07:21.000 from the ODC token and we put it into the signing certificate. 07:21.000 --> 07:24.000 So, then we have this information available with the signature 07:24.000 --> 07:27.000 that travels along with the package. 07:27.000 --> 07:30.000 There's an open source project called Sixdoor. 07:30.000 --> 07:34.000 It contains both implementation of a number of clients 07:34.000 --> 07:38.000 in different programming languages as well as a 07:38.000 --> 07:42.000 public good service, which has multiple port parts. 07:42.000 --> 07:47.000 There's Fulcio and that will exchange the OIDC token 07:47.000 --> 07:49.000 and create for you the signed certificate. 07:49.000 --> 07:52.000 There's also a transparency log, we'll touch on briefly. 07:52.000 --> 07:56.000 But the main component we're going to focus on here is Fulcio, 07:56.000 --> 07:59.000 which is sort of doing this translation. 07:59.000 --> 08:02.000 So, of course, it needs to contact the workload identity provider, 08:02.000 --> 08:05.000 make sure that the signature verifies correctly, 08:05.000 --> 08:08.000 and then it can return to your build this signing certificate, 08:08.000 --> 08:11.000 which then the build can for the distribute. 08:11.000 --> 08:15.000 And so, you send your package along with your signing certificate 08:15.000 --> 08:20.000 to the package manager just like you would normally. 08:20.000 --> 08:24.000 One last slide, before we start typing into what this looks like 08:24.000 --> 08:25.000 in different ecosystems. 08:25.000 --> 08:28.000 So, like I mentioned before, there's a couple of different components 08:28.000 --> 08:29.000 to Sixdoor. 08:29.000 --> 08:31.000 Mostly we're going to be dealing with the signing certificate 08:31.000 --> 08:33.000 because that's where the build problem lives. 08:33.000 --> 08:36.000 But there's a couple of other items in here. 08:36.000 --> 08:41.000 There's a transparency log that's to allow folks to monitor 08:41.000 --> 08:45.000 both that their identity is being used for signing 08:45.000 --> 08:47.000 when they expect and also to ensure the trust 08:47.000 --> 08:50.000 with the operation of the Sixdoor public good instance. 08:50.000 --> 08:53.000 And then, at the bottom of the bundle, 08:53.000 --> 08:56.000 you can either have a plain signature over your build, 08:56.000 --> 08:58.000 or you can have an adaptation. 08:58.000 --> 09:02.000 So, this is a JSON document with some metadata 09:02.000 --> 09:06.000 that you want to communicate along with the signature. 09:06.000 --> 09:10.000 And we'll see what that looks like in a second. 09:10.000 --> 09:14.000 And then, it's also really important to note that 09:14.000 --> 09:17.000 you should not just download a Sixdoor bundle and trust it. 09:17.000 --> 09:20.000 You need to verify that the bundle hasn't been tampered with. 09:20.000 --> 09:24.000 You need to verify that the bundle refers to the build that you're expecting. 09:24.000 --> 09:28.000 So, we're going to come back to the Mavent Central ecosystem. 09:28.000 --> 09:31.000 But here we're downloading a specific jar file. 09:31.000 --> 09:34.000 We're downloading the associated Sixdoor bundle. 09:34.000 --> 09:41.000 And then, cosine is the Sixdoor CLI that folks use to verify content. 09:41.000 --> 09:45.000 And so, in all the slides, I'm not going to show the verification process. 09:45.000 --> 09:48.000 Just how to access the province information. 09:48.000 --> 09:53.000 We should make sure that you're using cosine to verify any Sixdoor bundles 09:53.000 --> 09:56.000 before you start trusting the content that's inside of them. 09:56.000 --> 10:01.000 There's a couple of really great blogs from Sixdoor about what this process looks like. 10:01.000 --> 10:05.000 To verify bundles specifically, and then also, like, in general, 10:05.000 --> 10:11.000 what you should think about if you're going to build a system that relies on Sixdoor bundles. 10:11.000 --> 10:16.000 Okay, we are finally ready to dive into the various ecosystems. 10:16.000 --> 10:20.000 I do a little bit of work with NPM, so that's why I started. 10:20.000 --> 10:27.000 NPM shows to implement a new API endpoint, the attestations API. 10:27.000 --> 10:32.000 And so, here I'm creating that for the SEMVER package at a specific version. 10:32.000 --> 10:36.000 There's going to be a lot of JQ on the next slide. Sorry, not sorry. 10:36.000 --> 10:39.000 But, you know, this data is sort of like nested deeply inside of it. 10:39.000 --> 10:44.000 As we'll see in a second, NPM has support both for salsa province, 10:44.000 --> 10:47.000 as well as publish attestations. 10:47.000 --> 10:52.000 And so, the first JQ is saying, we want to take all the attestations NPM returns, 10:52.000 --> 10:55.000 and we specifically want to select prominence. 10:55.000 --> 10:59.000 And then the second JQ is diving into that Sixdoor bundle, 10:59.000 --> 11:02.000 looking at the signing certificate, getting the raw bites, 11:02.000 --> 11:05.000 and passing that to open this to SEL. 11:05.000 --> 11:12.000 And then, of course, you can see here, we have information about exactly what platform this package was built on, 11:12.000 --> 11:15.000 what repository the specific source commit. 11:15.000 --> 11:19.000 Also, there would be build information if I had more room on this slide. 11:19.000 --> 11:25.000 But this is an example of how to get build province information from the NPM ecosystem. 11:25.000 --> 11:30.000 Instead of using release attestations, NPM uses publish attestations. 11:30.000 --> 11:34.000 This is for the very good reason that it was implemented before release attestations existed. 11:34.000 --> 11:37.000 It was sort of a precursor to release attestations. 11:37.000 --> 11:40.000 This is almost the exact same query, 11:40.000 --> 11:43.000 except instead of looking for the build province this time, 11:43.000 --> 11:47.000 I'm looking for the NPM publish attestation. 11:47.000 --> 11:51.000 And it has the exact same information as the release attestation, 11:51.000 --> 11:56.000 the pearl of the package, and the exact hash that uses. 11:56.000 --> 12:00.000 As we're going to talk about more publish attestations and release attestations 12:00.000 --> 12:03.000 are kind of in a weird state currently. 12:03.000 --> 12:07.000 NPM, I think, is the only ecosystem that exposes information. 12:07.000 --> 12:12.000 And part of the reason is because we're not exactly sure how people are going to consume this. 12:12.000 --> 12:16.000 It's really worth noting here that the history of security, 12:16.000 --> 12:21.000 especially software security is filled with people proposing like, you know, ways to sign things. 12:21.000 --> 12:24.000 But they don't always talk about, like, how is it verified. 12:24.000 --> 12:27.000 And so, this information is being distributed. 12:27.000 --> 12:30.000 But, for example, the NPM CLI doesn't currently consume it. 12:30.000 --> 12:35.000 And so, you can certainly go on the transparency log of six store and see this information being published. 12:35.000 --> 12:40.000 You can get it directly from the registry, but it's not yet being consumed, 12:40.000 --> 12:46.000 which is something that would be a good thing for us as ecosystems to figure out in the near future. 12:46.000 --> 12:48.000 Next up is a pie pie. 12:48.000 --> 12:52.000 I'm not going to go through this as much detail, just kind of note the similarities and the differences. 12:52.000 --> 12:59.000 One of the main similarities is that it's using a separate API to expose this information. 12:59.000 --> 13:02.000 If you have the problems URL, otherwise this is exactly the same. 13:02.000 --> 13:05.000 You grab this certificate, pass it to the open to the cell. 13:05.000 --> 13:09.000 You can see exactly where this package came from. 13:09.000 --> 13:14.000 And then pie pie collects information for a published adaptation. 13:14.000 --> 13:19.000 And I think it actually submits it to the public transparency log. 13:19.000 --> 13:23.000 I'm 95% sure, but it doesn't serve it out. 13:23.000 --> 13:31.000 And again, this is because that ecosystem wants to wait to understand who and when this information would be used. 13:31.000 --> 13:39.000 And so, currently, the CLIs that are frequently used to access information from pie pie don't use this information. 13:39.000 --> 13:46.000 But if you're curious as to the format of that adaptation, even though it's not currently being served via an API, 13:46.000 --> 13:51.000 you can see what the format of it looks like there. 13:51.000 --> 13:55.000 Ruby gems has some pluses and minuses. 13:55.000 --> 13:59.000 Again, like the other two ecosystems, it has its own attestation API. 13:59.000 --> 14:06.000 There is a little bit of a speed bump, though, in that the information that it serves out isn't formatted correctly. 14:06.000 --> 14:09.000 The good news here is that it could be. 14:09.000 --> 14:11.000 But there's a bug currently. 14:11.000 --> 14:15.000 Marty, I think I said you this before, so hopefully you're not learning about this just now. 14:16.000 --> 14:23.000 But essentially, instead of the certificate robites, it's taking the payment coding of the certificate, 14:23.000 --> 14:27.000 based 64 and coding it again, and that's what it's serving out. 14:27.000 --> 14:32.000 So if this is an interesting topic to you, if you're looking for a sort of like a small project to maybe dip your toe in, 14:32.000 --> 14:36.000 this would be an interesting issue to follow up on. 14:36.000 --> 14:43.000 And if this was changed, then you could verify it with a six or two link. 14:44.000 --> 14:49.000 Last but not least, there are a tour of ecosystems is Maven Central. 14:49.000 --> 14:55.000 They made a different invitation decision, which I think is interesting. 14:55.000 --> 14:57.000 It's totally fine. 14:57.000 --> 15:05.000 And so instead of having a separate attestation API, they're just serving the six tour bundle alongside the content of the package. 15:05.000 --> 15:11.000 This really illustrates that in these conversations that we're having across ecosystems, 15:11.000 --> 15:16.000 the goal here isn't like 100% alignment lockstep everyone implements it the same way. 15:16.000 --> 15:19.000 We're all seeking to serve the same goals, right? 15:19.000 --> 15:22.000 We want transparency and our things that are built. 15:22.000 --> 15:26.000 We want the registry to be consistent about what packages it's serving. 15:26.000 --> 15:30.000 The specific implementation details don't necessarily matter here. 15:30.000 --> 15:35.000 But once you pull it down, it's just the same pattern as before, pass it through open to SL, 15:35.000 --> 15:41.000 and you can cross out the build properties properties. 15:41.000 --> 15:44.000 So, where do we go from here? 15:44.000 --> 15:50.000 I think that probably the next step that needs the most clarification is like, 15:50.000 --> 15:53.000 what are we doing with these release adaptations? 15:53.000 --> 15:56.000 Or maybe that's even the wrong way to face the problem. 15:56.000 --> 16:00.000 Taking a further step back, how do we want to protect the index of package repositories? 16:00.000 --> 16:05.000 It's really, really bad if an attacker accesses the data store for these package repositories 16:05.000 --> 16:11.000 and modifies them and says, oh no, the package didn't have hash 1, 2, 3, it had hash 4, 5, 6. 16:11.000 --> 16:15.000 Whatever my malicious version is that I'm serving out. 16:15.000 --> 16:20.000 So, somehow we know that we need to better protect these indices. 16:20.000 --> 16:23.000 There's a couple of different approaches that folks are taking. 16:24.000 --> 16:33.000 For example, the way that NPM is signing content, it actually provisioned sort of a durable public private key pair. 16:33.000 --> 16:38.000 And got the public key as a trusted delegate inside of six source verification material. 16:38.000 --> 16:40.000 Is it interesting experiment? 16:40.000 --> 16:44.000 I would not encourage anyone else to follow that path because then if you need to rotate your key material, 16:44.000 --> 16:47.000 you have to coordinate with this like third party open source project. 16:47.000 --> 16:49.000 It was a little clunky. 16:49.000 --> 16:54.000 The key I did this in a more elegant way with a sister capability called trusted publishing. 16:54.000 --> 16:59.000 So, here again, they used that signed OIDC token, the workload identity, 16:59.000 --> 17:05.000 but they use it to make it so you don't need a API key in order to publish to IPI. 17:05.000 --> 17:10.000 Instead, you set up a trust relationship and you say, if my build is coming from this platform, 17:10.000 --> 17:15.000 this repository and this known build workflow, you can trust it. 17:15.000 --> 17:17.000 I don't even need an API key to authenticate. 17:18.000 --> 17:27.000 That's a really powerful property and it allows them to construct public addestations using six source when they receive that signed OIDC token. 17:27.000 --> 17:32.000 And then in the open SSF, there's another project that's taking a completely different approach. 17:32.000 --> 17:42.000 So, instead of publishing addestation per package, they are signing the entire package index periodically and then publishing that information. 17:42.000 --> 17:46.000 I think like multiple times per day on the order of like several hours. 17:46.000 --> 17:53.000 The only sort of like downside or limitation here is that no one has deployed this to production yet. 17:53.000 --> 17:59.000 I believe it's being used in dev in some of the packed repository ecosystems. 17:59.000 --> 18:05.000 So, you know, in summary, there's like this really cool new security capability build profits. 18:05.000 --> 18:07.000 So, I hope people go and check out. 18:07.000 --> 18:11.000 We still don't know exactly how to protect the indices of packed repositories. 18:11.000 --> 18:19.000 There's a couple of interesting experiments that are ongoing, but we don't yet have a definitive answer of what we think this should look like. 18:19.000 --> 18:21.000 Thanks. 18:21.000 --> 18:29.000 We have time for some questions. 18:29.000 --> 18:33.000 So, wonderful. 18:33.000 --> 18:35.000 Yes, happy to. 18:35.000 --> 18:36.000 Yeah, go ahead. 18:36.000 --> 18:38.000 What's your presentation? 18:38.000 --> 18:42.000 I would have the one question that we have of opinion. 18:42.000 --> 18:49.000 One thing I noticed is if you have the build blocks linked in, for example, the vegetation in the NPM. 18:49.000 --> 18:51.000 And the build blocks are on data. 18:51.000 --> 18:55.000 You type of own the best system for roughly any year. 18:55.000 --> 18:57.000 Do you see that as a problem? 18:57.000 --> 19:01.000 Or do you have anything in the bottom of this building better because probably, 19:01.000 --> 19:04.000 I don't think we're going to have to solve that. 19:04.000 --> 19:07.000 Let's talk about the best thing that you have. 19:07.000 --> 19:08.000 Yeah. 19:08.000 --> 19:09.000 I guess. 19:09.000 --> 19:10.000 Yes. 19:10.000 --> 19:14.000 So, I mentioned a couple of times that, oh, sorry. 19:14.000 --> 19:15.000 Yes, yes. 19:15.000 --> 19:24.000 The question was build profits includes build logs, but many platforms do not process those build logs more than like 14 days. 19:24.000 --> 19:30.000 And it seems like a security incident later, you might want to know what was in those build logs for a critical build. 19:30.000 --> 19:34.000 And full disclosure, I work at GitHub. 19:34.000 --> 19:40.000 I think that you are right that we need a way to store these build logs more accurately. 19:40.000 --> 19:45.000 I'm not prepared to commit publicly on GitHub's behalf. 19:45.000 --> 19:51.000 When this might be addressed, but it is something that we are aware of and talking of internally. 19:51.000 --> 19:56.000 And I hope that soon there might be more information. 19:57.000 --> 20:00.000 Thank you. 20:00.000 --> 20:04.000 Any more questions? 20:04.000 --> 20:05.000 Great. 20:05.000 --> 20:06.000 Thank you. 20:06.000 --> 20:16.000 Thank you.