WEBVTT 00:00.000 --> 00:13.400 So today I'm going to talk about Sequoia Git, which is a tool for making signed commits matter. 00:13.400 --> 00:16.440 And I'm sure that a lot of people in this room, you're here, you're want to hear about 00:16.440 --> 00:17.440 signed commits. 00:17.440 --> 00:18.440 You sign your commits, right? 00:18.440 --> 00:20.440 How many people do? 00:20.440 --> 00:25.120 A lot of people sign your commits, oh, about more than half, 60 percent. 00:25.120 --> 00:26.120 That's great. 00:26.120 --> 00:28.320 Do you know why you sign your commits? 00:28.320 --> 00:29.320 No. 00:29.320 --> 00:33.880 Nobody knows why they signed their commits. 00:33.880 --> 00:36.440 Maybe I didn't give you enough time to raise your hand. 00:36.440 --> 00:40.800 So what a version control systems do, because we all work with version control systems primarily 00:40.800 --> 00:43.800 get they track changes. 00:43.800 --> 00:46.440 They track the changes to the code. 00:46.440 --> 00:49.400 They track 15 minutes left. 00:49.400 --> 00:50.400 Okay. 00:50.400 --> 00:52.040 They track changes to code. 00:52.040 --> 00:54.120 They track authorship. 00:54.120 --> 00:58.640 They track other metadata, like when you committed it, and they track, of course, the 00:58.640 --> 01:01.240 commit message. 01:01.240 --> 01:08.080 And we have a problem, because the author can actually be faked, who decides who the author 01:08.080 --> 01:09.080 is. 01:09.080 --> 01:10.080 It's the person who commits it. 01:10.080 --> 01:17.040 So the person who commits goes ahead, says, oh, it's whoever, not me, for instance, I 01:17.040 --> 01:20.080 could go ahead and create a commit from Linux. 01:20.080 --> 01:24.920 I use Git Config to set his email address, his name. 01:24.920 --> 01:32.400 I modify a few files, I add a commit, improve build, definitely does not add a backdoor, 01:32.400 --> 01:35.520 very inspiring commit message. 01:35.520 --> 01:36.520 And then I commit it. 01:36.520 --> 01:37.520 And it's good. 01:37.520 --> 01:41.400 It says, when we look at the log, it was by Linux Torvauds. 01:41.400 --> 01:44.360 And believe it or not, Git Hub will even show it. 01:44.360 --> 01:48.560 If you look at the picture over here, you'll see that Linux Torvauds has committed to my 01:48.560 --> 01:50.040 repository. 01:50.040 --> 01:52.240 Git Hub says it must be true. 01:52.240 --> 01:54.840 Now GitHub knows who pushed the commit. 01:54.840 --> 01:55.840 It was me. 01:55.840 --> 01:58.120 I pushed it. 01:58.120 --> 02:01.600 And the person I'm logged in, so that's why GitHub knows. 02:01.600 --> 02:05.720 But the committer and the author are different, and couldn't GitHub go ahead and correct 02:05.720 --> 02:06.720 that. 02:06.720 --> 02:09.760 And the answer is no, because we want attribution, right? 02:09.760 --> 02:13.760 That's one of the important things in the free and open source world is that the person 02:13.760 --> 02:16.360 who does it gets the attribution. 02:16.360 --> 02:22.200 At the same time, it's not only about attribution, it's also about blame, Git blame. 02:22.200 --> 02:23.840 If somebody comes along, it does something bad. 02:23.840 --> 02:27.280 And we want to be able to look at their other commits as well. 02:27.280 --> 02:30.560 So in personation is bad, why do we care about it? 02:30.560 --> 02:35.120 Well, maybe you have a project that's hosted on the forge, and the forge decides to insert 02:35.120 --> 02:36.120 a back door. 02:36.120 --> 02:39.280 Maybe they were forced to buy some three-letter agency. 02:39.280 --> 02:41.440 How do we catch up? 02:41.440 --> 02:46.960 Or maybe your project is hosted on the forge, and your account is compromised, so that 02:46.960 --> 02:47.960 could happen. 02:47.960 --> 02:52.360 And the attacker adds a commit, and they insert a back door into your project. 02:52.400 --> 02:54.680 But we prevented, how do we detect it? 02:54.680 --> 02:59.560 Or maybe there's somebody out there who's submitting patches on your behalf, like I just 02:59.560 --> 03:04.000 did for a Linux, and it's a low quality patch, because it didn't actually fix the 03:04.000 --> 03:05.000 build system. 03:05.000 --> 03:06.560 It introduced the back door. 03:06.560 --> 03:07.560 What do you do? 03:07.560 --> 03:09.200 Did I damage Linux's reputation? 03:09.200 --> 03:14.880 Well, probably not, in this case, but other people, how do we catch up? 03:14.880 --> 03:18.360 Well, preventing impersonations, digitally signed commits. 03:18.360 --> 03:19.560 We have cryptographic proof. 03:19.560 --> 03:20.560 Thank you very much. 03:20.560 --> 03:22.320 It was a pleasure to be here. 03:22.320 --> 03:27.280 No, the signing is the easy part, right? 03:27.280 --> 03:30.760 We already saw that two-thirds of the room does the signing, but nobody knows why we do 03:30.760 --> 03:32.000 the signing. 03:32.000 --> 03:33.560 So why? 03:33.560 --> 03:35.760 Yeah, we can sign. 03:35.760 --> 03:38.480 But again, we have the same problem as we had before. 03:38.480 --> 03:40.600 Anybody can create a certificate with anybody's name. 03:40.600 --> 03:41.600 I can go ahead. 03:41.600 --> 03:44.440 I can create a certificate for Linus Torvals. 03:44.440 --> 03:45.440 Here it is. 03:45.440 --> 03:46.440 Generate, boom. 03:46.440 --> 03:51.760 OpenPQP certificate with the user ID that Linus uses. 03:51.760 --> 03:56.200 Okay, so we want to know, is this really Linus's certificate? 03:56.200 --> 03:59.080 And the answer is, of course, no, because I just generated it, right? 03:59.080 --> 04:01.200 You're all following along. 04:01.200 --> 04:03.680 What about, so how do we authenticate these certificates? 04:03.680 --> 04:05.440 Well, we can talk to the developer. 04:05.440 --> 04:08.320 So if you happen to be here, I've lost them, and you go to the cubes stand. 04:08.320 --> 04:12.040 You might see Martha there, and she's wearing her t-shirt, and at the bottom of it is 04:12.040 --> 04:15.840 the OpenPQP fingerprint for the release key for cubes. 04:15.840 --> 04:20.040 So you could take a picture of her or you could go online on YouTube. 04:20.040 --> 04:23.520 You could talk to other people, and you could figure out what are their release keys. 04:23.520 --> 04:24.520 That's good way to do it. 04:24.520 --> 04:26.160 You could go to a key signing party. 04:26.160 --> 04:29.800 We used to have key signing parties that fall some, not so much anymore. 04:29.800 --> 04:31.800 There are centralized authorities. 04:31.800 --> 04:35.960 For instance, there's keys.openpcp.org, which is a verifying key server. 04:35.960 --> 04:41.160 They verify that you actually control the email address, so it's similar to, for instance, 04:41.160 --> 04:42.480 that's encrypt. 04:42.480 --> 04:45.320 We have the Linux kernel developer key ring. 04:45.320 --> 04:47.160 You can go there onto the website. 04:47.160 --> 04:48.160 You can download the key ring. 04:48.160 --> 04:50.280 It's included in some distributions. 04:50.280 --> 04:54.360 There's the distribution Gpg keys, package, which contains all of the certificates for 04:54.360 --> 04:57.640 all of the different distributions, or most of them at least. 04:57.640 --> 05:03.760 You could even use GitHub if you trust GitHub, GitHub.com slash user handle.chpc, and 05:03.760 --> 05:05.280 boom, you get the certificate. 05:05.280 --> 05:09.480 So there are a lot of different ways you can do this, and preferably you do multiple ways, 05:09.480 --> 05:14.000 and you have multi-path, and then it's harder for an attacker to intercept it. 05:14.000 --> 05:18.720 By the way, this is Linux's certificate. 05:18.720 --> 05:20.280 Now we want to authenticate a project. 05:20.280 --> 05:22.520 We can get a certificate. 05:22.520 --> 05:27.920 We can know that as definitely from Linux, for instance, so we check that the commits are 05:27.920 --> 05:28.920 signed. 05:28.920 --> 05:34.080 We do get log, dash, dash, show signature, and we see that we have a good signature from 05:34.080 --> 05:36.160 Linux Torables, but it's not authenticated. 05:36.160 --> 05:38.800 That's not so good. 05:38.800 --> 05:43.440 Then we have a good signature for me, and it is authenticated. 05:43.440 --> 05:48.040 But we want to check that they're from the expected certificates. 05:48.040 --> 05:50.040 This is not from Linux's certificate. 05:50.040 --> 05:53.640 It says Linux on it, but it's not Linux's certificate. 05:53.640 --> 05:56.080 So how do we authenticate a project? 05:56.080 --> 06:01.120 We have to create a list of all the contributors, and get all of their certificates. 06:01.120 --> 06:06.440 That's on a small project, maybe okay, for a big project like the Linux kernel. 06:06.440 --> 06:08.760 That's quite a lot of work. 06:08.800 --> 06:14.160 We have to track when contributors join and leave the project, because here, we see on 06:14.160 --> 06:18.640 the right, that Alice joins the project, she adds a commit, maybe she adds five, at some 06:18.640 --> 06:23.480 point she leaves the project, she's no longer allowed, maybe she was kicked out, and then 06:23.480 --> 06:24.840 she adds another commit. 06:24.840 --> 06:30.280 The old ones, they're okay, presumably the maintainers have re-audited if they kicked 06:30.280 --> 06:35.000 her out, and they decided that it was okay, but the new ones are not okay. 06:35.000 --> 06:37.720 Now we have a temporal element as well. 06:37.720 --> 06:42.400 This is getting really complicated, we need tooling. 06:42.400 --> 06:48.160 The maintainers need tooling, and for the third parties, maintaining this database is just 06:48.160 --> 06:50.480 completely impossible, because I use a lot of software. 06:50.480 --> 06:55.680 There's no way that I can track all of the maintainers and all of the politics and everything. 06:55.680 --> 06:59.880 I have to delegate this to the maintainers. 06:59.880 --> 07:06.360 So I need to rely on as a third party, the maintainer, to somehow do something, to maintain 07:06.360 --> 07:08.400 this database. 07:08.400 --> 07:10.240 So, why do we want to do this? 07:10.240 --> 07:14.000 We want, of course, to detect the unauthorized commits, as I said before, with the impersonation 07:14.000 --> 07:18.400 thing, we have a malicious forge, we have a compromise forge of accounts, maybe there's 07:18.400 --> 07:23.600 a machine in the middle, but we also want to detect the case when the forge or registry 07:23.600 --> 07:26.720 gives the project to a new maintainer. 07:26.720 --> 07:30.840 So it may be, and we saw, for instance, in the node world with the registries, that 07:30.840 --> 07:34.880 they'll just randomly give a project, we'll take it away from one maintainer and give it 07:34.880 --> 07:39.480 to another, or that happened in the Ruby space recently, and in the node space, there were 07:39.480 --> 07:42.760 some abandoned projects and they just gave them to new maintainers, and maybe they were 07:42.760 --> 07:46.480 malicious, and some of them actually were, and that was a big problem. 07:46.480 --> 07:48.160 And I wanted to detect that. 07:48.160 --> 07:53.600 If the forge goes ahead and does a rug pull, then I as a third party want to easily detect 07:53.600 --> 07:55.200 that that happens. 07:55.280 --> 07:58.520 OK, so we kind of see the problem, what is the solution? 07:58.520 --> 08:02.880 Look like, well, we definitely need some clear semantics for assigning commits because 08:02.880 --> 08:06.000 nobody really understands what's going on. 08:06.000 --> 08:11.680 We need the project to maintain a siding policy, which evolves over time, and we want 08:11.680 --> 08:16.880 our third parties to be able to rely on the maintainers of the projects to authenticate 08:16.880 --> 08:18.320 the project. 08:18.320 --> 08:19.800 And how do we do that? 08:19.800 --> 08:23.200 Well, they're still a check-in-volved, it's just a smaller check. 08:23.200 --> 08:28.080 At the time that we want to use the project, we do an audit. 08:28.080 --> 08:32.880 We look at the code, does the pass the smell tests, we look to see who the maintainers of 08:32.880 --> 08:36.880 the project are, are they trustworthy, do I know them, maybe not personally, but I've 08:36.880 --> 08:42.240 heard of them, they have a reputation, I look online, OK, I'm happy, or maybe I'm a company, 08:42.240 --> 08:45.440 and I actually pay some people to do an audit, I don't know. 08:45.440 --> 08:51.040 But somehow you decide, OK, at this point in time, at this commit, I trust the project, 08:51.040 --> 08:54.720 and then in the future, we're going to chain forward. 08:54.720 --> 08:58.960 Now, the limitations of this is that since we're relying on the maintainers of the project 08:58.960 --> 09:04.400 to maintain the database, if the maintainers are tricked, if there's some sort of social 09:04.400 --> 09:09.360 engineering, then all bets are off, right, because the maintainer of the project is going 09:09.360 --> 09:16.720 to add some g-chain to the list of authenticated commuters, and then they go ahead and 09:16.720 --> 09:18.320 they add it, and I'm not going to detect that. 09:18.800 --> 09:23.680 We can't detect social engineering, but we can detect the rug pull, we can detect impersonation, 09:23.680 --> 09:25.680 and we can detect attacks on infrastructure. 09:27.040 --> 09:31.840 All right, additional goals, we do not rely on authority. 09:33.040 --> 09:36.160 That means that we want verification, not attestation. 09:36.160 --> 09:40.000 Just because GitHub said it was so, does not mean that it is so. 09:40.000 --> 09:46.000 Just because I use six or in Google says that this is a certificate that belongs to me, 09:46.000 --> 09:47.360 does not mean it is so. 09:47.360 --> 09:49.120 I want to verify this. 09:51.040 --> 09:52.800 So Sequoia gets our tool. 09:52.800 --> 09:54.160 It contains three parts. 09:55.280 --> 09:58.000 We have a specification, you can see it over here. 09:58.000 --> 10:02.080 It's not been certified by the ITF, but there is a long document described 10:02.080 --> 10:05.600 all the semantics of somebody could come along and implement their own tool. 10:06.320 --> 10:10.320 We have a configuration file, and I'm a whole bunch of tooling around it. 10:11.200 --> 10:16.800 So the signing policy, the most important thing, the center of the how this works, 10:16.800 --> 10:22.080 it's stored in the Git project itself, not separately in the exact same repository, 10:22.080 --> 10:27.280 that means that evolves with the project, when Alice leaves the project, 10:27.280 --> 10:32.240 the maintainer of the project, modifies this file and says Alice has left. 10:32.240 --> 10:38.560 That means commits before, we can still authenticate commits after, Alice, no, rejected. 10:39.520 --> 10:41.520 We have different capabilities. 10:41.520 --> 10:44.480 We have users who are allowed to add commits. 10:45.200 --> 10:50.080 We have users who are allowed to add tags, create a release, add remove other users, 10:50.080 --> 10:55.600 and even audit commits, which is needed if somebody's certificate has been compromised, 10:55.600 --> 10:59.360 then the maintainer needs to go back and check that the commits are okay. 10:59.920 --> 11:01.280 And also market as search. 11:02.480 --> 11:03.280 Okay. 11:03.280 --> 11:10.880 So on the right-hand side, we see it, the policy file, it is a tumble file at the start, 11:10.880 --> 11:14.960 we have the version, we have the list of the good commits, those that have been audited, 11:14.960 --> 11:16.960 we don't have any compromised keys in this case. 11:17.520 --> 11:22.640 And then we have two certificates here, one for Neil and one for Neil offline. 11:22.640 --> 11:27.200 The Neil certificate is only allowed to add commits to the repository, 11:27.200 --> 11:31.280 but the Neil offline certificate, because on my UB key, 11:31.760 --> 11:34.640 that is allowed to do releases to add users and remove them. 11:35.280 --> 11:40.320 So it's relatively straightforward, but the good news is the maintainer doesn't have to do it themselves, 11:40.320 --> 11:42.400 or do it manually, there's a tool. 11:42.960 --> 11:49.600 So if we want to add, for instance, Alice to the repository, we can run SQGIT policy authorized Alice. 11:50.080 --> 11:55.360 We specify her certificate, and then we see here that Alice was audited, she was granted the 11:55.360 --> 11:58.640 sign commit rights, and then this is her certificate. 11:59.040 --> 12:04.640 And if we want to update it, because people change their certificates, they extend the expiration, 12:04.640 --> 12:10.640 we can do SQGIT policy sync, it goes to the local certificate store that you have, 12:10.640 --> 12:17.280 it goes to a bunch of different key stores, key servers, and checks for updates and integrates them. 12:19.440 --> 12:23.040 And if we want to examine the policy, it's also relatively straightforward, 12:23.120 --> 12:29.680 SQGIT policy described, and here we see all of the people that are allowed to do different things, 12:30.640 --> 12:33.120 what their certificates are, and what their rights are. 12:34.000 --> 12:39.360 Okay, so how do we authenticate commits? What does it mean for a commit to be authenticated? 12:39.360 --> 12:45.360 And SQGIT, we say a commit is authenticated if at least one, not all, at least one, 12:45.360 --> 12:48.720 of the parents say that the commit is acceptable. 12:48.960 --> 12:57.360 So we have the current commit, I want you authenticated, I look at the parent commit, 12:57.360 --> 13:04.720 I get the policy out of the parent commit, and I say does the policy say that this person 13:04.720 --> 13:11.760 is allowed to make this change? And if it has multiple parents, for instance, with the merch 13:11.760 --> 13:19.360 commit, then any of one of them can do it, any one of the parents. Okay, so that's how we authenticated commit, 13:19.360 --> 13:25.280 but how do we authenticate a range of commits? Well, we need a path from A to B, so here we have a path 13:25.920 --> 13:31.280 from the top to the bottom. There's a merch commit involved, only one of the branches of the merch 13:31.280 --> 13:36.320 commit is completely authenticated, and so we have a path from the top to the bottom, and so we 13:36.400 --> 13:43.840 consider this range of commits to be authenticated. Now, why don't we need both branches to be authenticated? 13:43.840 --> 13:52.560 The answer is simple, the person who adds the merch commit has presumably reviewed the changes 13:52.560 --> 13:58.240 in the unauthenticated paths, so there still needs to be the authenticated path for the merch commit, 13:58.240 --> 14:05.200 but we can add things from other people. So how does it look? A quick example, here we have 14:06.080 --> 14:13.680 GitLog graph on the left, and it shows that we have four commits, and on the right we use SQ GitLog 14:13.680 --> 14:20.640 in order to check whether or not a range of commits is considered authenticated. So we have to 14:20.640 --> 14:24.960 specify the starting commit, which is our trust root, that's the point where we audited the project, 14:25.680 --> 14:31.280 and in this case we're going to use the first commit AAB50, and then we see that we check the three 14:31.360 --> 14:37.760 commits that come afterwards, and we can see here in violet that Alice signed the most recent commit 14:37.760 --> 14:43.200 and meal offline signed the other two, and that they were considered okay, there is a verified path 14:43.200 --> 14:51.920 here from the trust root, and then SQ Git returns to zero. What happens if we can't verify 14:51.920 --> 14:56.880 how does that look? Let's imagine that we have Bob come along, he adds a commit to the project, 14:57.680 --> 15:02.960 so if you look here on the left, GitLog shows signature dash n2, we have a commit from Bob, 15:02.960 --> 15:07.520 it is a good signature from Bob, we have the certificate locally, we authenticated it, 15:07.520 --> 15:12.240 maybe we've been no Bob personally, but the maintainer of the project didn't say that Bob 15:12.240 --> 15:20.000 is supposed to commit to the project, and SQ Git detects that, it says error this certificate, or 15:20.000 --> 15:26.480 key is missing from the policy file, we're not able to verify this commit, there is no authenticated 15:26.480 --> 15:33.120 path from the trust root to the head, Bob adds a commit, he is not authorized, rejected, 15:33.760 --> 15:39.040 exit code 1. Okay, so what can we do if we want to merge commits from other people, right, 15:39.040 --> 15:44.560 because when we have a free and open source project, we have the core team, but we also have external 15:44.560 --> 15:49.520 people who come along, well the committer can re-sign Bob's commit, this preserves the 15:50.480 --> 15:58.480 you know, I'm going to take two more minutes on this. Preserve the linear history, or we use 15:58.480 --> 16:06.160 a merge commit, so Alice can go ahead and merge Bob's commit, and in this case we have to use 16:06.160 --> 16:10.160 the dash n0 fast forward otherwise Git is so smart that it just says okay we're going to fast 16:10.160 --> 16:15.120 forward it, so we look here on the left, we see we have a merge commit on top, and then on the 16:15.200 --> 16:22.080 right we see here that SQKit correctly detects that the commit from Bob itself is not authenticated, 16:22.080 --> 16:27.040 but that there is a path, and so we're able to authenticate the new head, which is the merge commit. 16:28.240 --> 16:33.360 So more details, yes you can update your own expired certificate if you haven't committed to the 16:33.360 --> 16:38.800 project for a while, we can recover from hard removal keys by using good listing, we can verify 16:38.800 --> 16:45.920 tags and terables, that's specified in the document, but the implementation is incomplete, 16:45.920 --> 16:50.960 and there's a lot more details in the manpages and documentation. What about forking a project, 16:50.960 --> 16:58.320 we absolutely support that, basically the new maintainer is if it's a fork that's not authorized, 16:58.320 --> 17:04.080 it's not going to appear in the file, but that's exactly the semantics that we want, right, 17:04.080 --> 17:08.560 if somebody forks a project comes in and starts adding commits, I want to know about that, I want 17:08.560 --> 17:17.360 SQKit to say, hey, this is not good. All right, how can you integrate it? SQKit, if using just a 17:17.360 --> 17:25.680 get yourself, then you can use a hook, you can add it to your GitLab CI using this little snippet, 17:25.680 --> 17:30.960 we have a container that has SQKit and does all the right things. If you're on GitHub, we have an action, 17:31.520 --> 17:38.080 unfortunately GitHub destroy signatures on fast forward, so you also need to be extra careful 17:38.720 --> 17:44.960 there, and we have a fast forward action that helps, and here you can see on GitHub, the output of SQKit, 17:45.840 --> 17:52.160 it displays that the new commits are authenticated. So related work, I want to point out very quickly 17:52.160 --> 17:58.560 that Ludovic Quote has had a talk here a couple of years ago about building a secure supply chain 17:58.560 --> 18:03.200 for geeks, and he has a similar system to the one that I describe, the semantics are different, 18:03.200 --> 18:07.760 it's not exactly the same thing, but I'm particularly grateful for the work that Ludovic has done, 18:07.760 --> 18:14.080 and I encourage you to look there as well. And finally, signing commits is useful, we just need 18:14.080 --> 18:18.720 better tooling, I believe that SQKit provides that tooling, and I hope that it's going to help 18:18.720 --> 18:25.600 protect against the impersonations, detect unauthorized commits, and that we don't need to have the 18:25.680 --> 18:32.960 forge as part of our trusted computing base. Thank you. 18:36.160 --> 18:41.920 So I think we have time for some questions, maybe I can hijack this and have start with one, 18:43.760 --> 18:51.280 get this shall-one based, is that the problem here? Is it a problem of the shall-one based? 18:51.360 --> 18:57.520 Yeah, I have someone forges shall-one, identical shall-one commit, that the signatures will 18:57.520 --> 19:08.560 apply to identical shall-one commit. That's a good question, but I'm not sure, but the answer 19:08.560 --> 19:13.600 is definitely once we move to shot 256, then things will be looking better, and everybody is using 19:13.600 --> 19:19.520 the shall-one CD implementation, so we're kind of protected anyways. But I think this would 19:19.600 --> 19:27.520 depend basically on second-premage. So for arbitrary commit, you want another one that has the same 19:27.520 --> 19:37.680 hash. It's like the one, I have one question, very short one. Yeah, when I do like 19:37.680 --> 19:43.280 merit on a rebase is, can I sign like the rebase commits? Yeah, because there are different 19:43.280 --> 19:51.760 authors in the rebase. Yeah, yeah. Yeah, the person who does the signature does not have to 19:51.760 --> 19:55.040 actually match the author, so it's only looking at the signature. 20:06.320 --> 20:13.040 Do you have any thoughts or plans about how or if this could integrate with signing releases 20:13.040 --> 20:19.200 as well? Like, if could you use this to declare the policy this key has allowed to sign releases 20:19.200 --> 20:26.000 and do software supply chain stuff like that? Yeah, absolutely. So the focus in this talk was on 20:26.000 --> 20:31.920 the commits, but we also have support for authenticating tags and releases. That's primarily 20:31.920 --> 20:38.240 in the spec. The implementation has not done the association between the policy and the 20:38.320 --> 20:42.000 tarbles yet, but that's hopefully going to be something for the future. 20:46.240 --> 20:48.480 Thank you very much. Thank you.