Writing secure code in Python
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 112 | |
Author | ||
Contributors | ||
License | CC Attribution - NonCommercial - ShareAlike 4.0 International: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/60848 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
EuroPython 202283 / 112
5
10
14
17
19
23
25
29
31
32
34
44
47
51
53
54
57
61
69
70
82
83
88
93
94
97
101
105
106
00:00
TupleCellular automatonComputer wormVolume (thermodynamics)Functional (mathematics)ChainSocial classObject (grammar)Extension (kinesiology)Right angleResultantForcing (mathematics)Information securityVariable (mathematics)BuildingForm (programming)FreewareEndliche ModelltheorieExpressionBranch (computer science)Cellular automatonPattern languageSoftware developerSystem callGraph coloringDifferent (Kate Ryan album)WordMessage passingData dictionaryParameter (computer programming)Local ringElectronic mailing listLattice (order)Computer programmingCore dumpFormal languageWeightExterior algebraExpert systemSet (mathematics)NeuroinformatikPhysical systemPiString (computer science)Cartesian coordinate systemLine (geometry)Software testingComputer configurationEuler anglesBitError messageNumberFocus (optics)Goodness of fitMalwareVulnerability (computing)SummierbarkeitTupleModule (mathematics)Insertion lossSource codeCodeLevel (video gaming)AgreeablenessOpen setStructural load
08:29
Core dumpLine (geometry)Parameter (computer programming)CASE <Informatik>Task (computing)CodeFunctional (mathematics)Physical systemOpen setObject (grammar)System callGastropod shellBinary fileSocial classCommunications protocolCore dumpComputer fileHydraulic jumpElectronic mailing listSequenceStructural loadInterpreter (computing)NumberSet (mathematics)Pole (complex analysis)Instance (computer science)Right angleModule (mathematics)Library (computing)String (computer science)Control flowEndliche ModelltheorieInformation securityNeuroinformatikTupleStandard deviationComputer configurationRaw image formatReduction of orderIntegerSerial portUniverse (mathematics)Physical lawRule of inferenceStreaming mediaNetwork topologyFormal languageCellular automatonMereologyDirected graphCircleChainMetreFerry CorstenDemosceneComa BerenicesDiscrete element methodTrailWebsiteDampingGame theoryRow (database)Computer animation
16:58
MassReduction of orderGame theoryCore dumpString (computer science)Hash functionCoefficient of determinationIndependence (probability theory)Military operationNetwork socketBuildingCodeFunctional (mathematics)Source codeParameter (computer programming)Type theoryResultantHash functionSocial classInformation securityLine (geometry)Process (computing)Endliche ModelltheorieDeterminantString (computer science)Structural loadRight angleElectronic mailing listDifferent (Kate Ryan album)Dot productReverse engineeringGastropod shellServer (computing)Open setPoint (geometry)Computer fileSlide ruleoutputInstallation artMetadataBitDescriptive statisticsImage resolutionPower (physics)System identificationCASE <Informatik>Binary codeLogicRepository (publishing)BuildingFile formatObject (grammar)Serial portOffice suiteDemosceneView (database)System callPhysical systemAreaMereologyComa BerenicesForcing (mathematics)DataflowVideo gameWebsiteTerm (mathematics)Real number2 (number)Game theoryData storage deviceWorkstation <Musikinstrument>Network topologyRadical (chemistry)CausalitySinc functionPhysical lawConnected spaceRow (database)ECosTouchscreenSet (mathematics)Population densityQuicksort
25:26
Revision controlAuthorizationPrice indexInformation securityDatabaseVector potentialVulnerability (computing)FlagSystem administratorHash functionBinary codeType theoryAnalytic continuationStandard deviationCodeMultiplication signElectronic mailing listInformation securityLibrary (computing)StatisticsRepository (publishing)Subject indexingComputing platformWebsiteQuicksortRight angleGroup actionElectronic program guideGoodness of fitSystem callMedianSlide ruleArea
29:30
Augmented realityFunction (mathematics)Process (computing)Bit rateVariable (mathematics)Absolute valueParameter (computer programming)CodePasswordString (computer science)Numerical digitLattice (order)Frame problemGamma functionElectronic mailing listVulnerability (computing)Revision controlWordModule (mathematics)Information securityRandom number generationFunctional (mathematics)Condition numberComputer fileRandomizationTwitterPasswordSoftware bugNumberResultantAxiom of choiceRight angleElectric generatorNeuroinformatikExterior algebraComputer programmingError messageCodeSequenceLine (geometry)Sound effectComputer configurationFlagLogical constantMachine codeArrow of timeSheaf (mathematics)Software testingTraverse (surveying)Diffuser (automotive)BitSocial classPhysical systemEndliche ModelltheoriePoint (geometry)Prisoner's dilemmaData conversionMassBit rateQuicksortSystem callEvent horizonVideo gameCASE <Informatik>Computer animation
36:51
Keilförmige AnordnungModule (mathematics)Random numberInformation securityElectric generatorSource codeAbsolute valueCodeFile formatMathematical analysisoutputPoint (geometry)Vulnerability (computing)ECosEndliche ModelltheorieData miningFunctional (mathematics)Physical systemMultiplication signComputer configurationOperator (mathematics)Standard deviationSuite (music)Observational studyMathematical analysisArithmetic meanCodeInformationFluid staticsModule (mathematics)System administrator
38:16
Drill commandsMultiplication signRoundness (object)Remote procedure callLecture/ConferenceMeeting/InterviewXML
Transcript: English(auto-generated)
00:06
Hello everyone, I hope you have you're having a fantastic conference. I wish I could be there with you Yeah, so I think I'll just start because we have a lot to talk about so today I'm going to talk about
00:26
writing secure coding Python Let me start doing a quick introduction. I just want to to explain What is my motivation behind this talk? So I'm sure everyone who's worked with Python or even just I don't mess with the language a bit
00:44
Has heard this before that programming in Python is easy And this is something I don't disagree. I think it's one of the core strengths of the language But I believe people sometimes can seem to understand that Why
01:01
Well, it's really easy to create a Python program that runs that Successfully executes. It's not always so trivial to write a quality code. That is both by sonic and secure so Today, of course, I'm gonna focus on the security side
01:23
because Over the years working as a Python developer I got the chance to to see a few patterns with Python code that sometimes we as developers don't think too much about and May end up becoming a security risk and or a security vulnerability So I basically made a list of things that
01:43
And that is what I'm going to show you today. Some topics are a bit obvious are missing a bit obvious to those of you who are more experienced, but overall we got a Lots of cool things to talk about today, so let's start
02:01
The first thing I want to talk about is the function is about the function evil so Yeah, so the topic is evil is really dangerous So let's start for those who aren't familiar Evil, which is short for evaluate is a built-in function that evaluates a Python expression and returns its result
02:24
So I added a few examples on the side of how the function can be used and the first two examples are simple mathematical expressions But in the third example, we can see that with evil we have access to building functions like sum
02:40
And in the last example we see that With evil we can even access declare variables Outside of evil so I declare the variable X and I can access this variable inside of evil the function can receive
03:01
two optional parameters Which are globals and locals They're basically dictionaries that Define what would be the global variables and the local variables available from evil And Yeah, we're gonna use this these parameters
03:21
You'll see how so the danger with this function begins with well if a user tries to to run a malicious code malicious expression Such as this simple expression to to remove all the files from from the computer using OS that system
03:41
And yeah as well evaluates this this expression and executes this code, but considering We can control the global variables with the globals Parameter maybe we can manage to securely run Dysfunction if we try to pass an empty dictionary as the globals argument
04:04
Well that will work so we will get a name error because OS is not defined anymore because We clear the global variables and OS was a global variable But the problem is Python automatically inserts buildings when we don't when we use
04:24
Even when we use an empty dictionary as the the globals Argument So yeah, we don't have access to the imported OS module But we can import it ourselves using the dunder import built-in function But then again, we can control the globals so we can specifically clean the buildings. Maybe then we can create a
04:47
kind of secure evolve and Yet that again we work if we Instead of passing an empty dictionary as the globals variable we pass dictionaries with the
05:01
Dunder built-ins key set to an empty dictionary then we are clearing the the built-in variables that Python automatically inserts and Then the dunder import function is not available anymore But maybe we can
05:21
Work it out some way Because yeah, we can we don't have any built-in and we don't have Any global variables, but we still can create Python objects using the literal form so I Can create for example a tuple?
05:43
Using instantiating the class tuple, but I can create a tuple using the literal form which is the the parenthesis Opening and closing the parenthesis, which creates a tuple So, okay. What if I create a tuple with the literal form and access the dunder class attribute?
06:02
Well, then I get the class tuple and if I access the dunder base Attribute I got the object class and we know that Everything in Python is an object. So if we Call the subclasses method the dunder subclasses method from the the object class
06:20
we basically get all loaded classes in our program and Right now we're looking for an specific class That is the built-in importer because with this class we can import whatever we want. So basically what we need to do is Iterate to through this subclasses not these objects of classes. Look for the one that is called built-in importer and
06:47
Instantiate it and call the its method load map module And then we can import the OS module and call the system function with the malicious code but we need to do that in one line because well, we're calling in from inside the evolve function and
07:07
Yeah, the conclusion is if always really dangerous in we can really create a secure evolve we can Basically do the payload with with all this comprehension
07:20
The this code is from net sec dot expert. You can check them all later. It's a good source and Yes, so what are our alternatives since we can use or we shouldn't use the evil function well we have the little evil from the
07:41
AST model and with this function we can basically create An object a Python object, but only using its literal form. So I have these examples here so we can create Any kind of number we can create a tuple with different kinds of objects inside
08:01
But we can really evaluate an expression. For example, we can do a mathematical expression such as 1 plus 1 It will not run it it's gonna be a value error and if we need something more complex We can try to parse the string ourselves And implement the code ourselves, which will be of course more secure
08:24
so basically When should we use the evolve? So we have this function available as a built-in and when should we use it and My answer to this is we should use it all basically when there is no other viable way to accomplish a task and
08:42
Well when we when we work with Python for long enough you realize That this mean basically never you should never use evil. There is no There is no no really useful It yeah, it's not useful enough to
09:06
To have the security risk, okay, so let's jump into topic two which is about arbitrary code execution with Pico as I said, we have Many topics they're quite different from each other. But
09:24
Yeah, so let's jump into it To Managing time, okay, so About the Pico module the Pico module is a way in Python to store a Python object
09:42
In we serialize despite an object to a sequence of bytes and we can load this object this the serialized object later if we need the object so We basically do that with the dump function so we serialize an object with the dump function and we
10:02
Load it when we need to load it using the load function. So on the right I have an example of that. I serialize a set of numbers And I save it your file and then I load it from this file. So the file is a binary file. I load the
10:20
The This bytes and they are deserialized to our Python object, which is the set of numbers and Again with these functions with the dump function. We have optional parameters we can use so We have this protocol
10:42
Argument, which is an integer denoting what protocol is going to be used for the serialization And we currently have five options to For protocols that goes from zero which is the oldest one and it's basically the human readable one To five which is the newest which is available from the things Python 3.8
11:08
Okay, so what if we need to customize how a class is serialized Python usually knows how to serialize all kinds of objects, but if we need to to customize how a class
11:21
Instance how an object is going to be serialized we can do that using this magic method than the reduce So this method should return a string or a tuple containing a callable and its parameters and we are going to focus on this On the second option, which is that the pole containing a callable and its parameters
11:41
Yeah, so, okay so we can create here a class called exploit pickle Which implements the than the reduce method? And I'm returning The first the callable, which is the OS dot system which I'm using as an example and I'm returning the
12:01
What what arguments should be passed to this callable? which is the the RMRF code to delete all the files. So yeah, okay, we can serialize it Normally, it's going to be serialized to bytes, but when you load it
12:21
if we if we call a pickle dot loads to load the bytes and deserialize it to a Python object then this is going to run and If the interpreter has the right permissions, it's going to delete all the files So this coding side reduce is going to be executed
12:44
We can use pickle tools, which is another module available From the the standard library to basically read the pickle and understand What is doing behind the scenes? so let's just
13:01
Understand what how can we read a pickle files? To maybe create a more complex one okay, so using the the pickle tools dot this function we can read the raw pickle and I'm going to basically go through the the pickle code
13:21
So the pickle starts with the C character The C character is used to import basically import a function. So we use we have the C character Followed by POSIX, which is the model a line break and system so To import a function from a model. We have C the name of the model a line break
13:44
So now it's not the name of the model is the name of the function system So we are basically calling this this function importing this function to to our code Then we have this Open parameter so here when it says 14 the line 14 with
14:04
The column 14. I'm sorry. It's a mark. So it is the it is the the Arguments mark so we start to provide what arguments are going to be passed to this function. We just imported So the first argument which is the only argument is a new nickel string and to denote a new
14:26
Unicode string we use the uppercase V character and Followed by the string itself. So in this case the string itself is the RMRF code to delete all the files we then basically close the parameter
14:43
So in column 14, we open the the list of parameters and in line 24 We use the T character to close the parameter We're passing to the function we imported is the Unicode string RM RF then in column 25
15:01
We have the uppercase R Which is the reduce itself? Which then executes the function with the provided parameters? we specify and on column 26, we have the the dot which is Analyzing that the pickle ended so that's basically what this pickle means and
15:26
With that we're going to try to execute Arbitrary code because in the example I showed before we had a simple OS dot System call but what if you want to really run any kind of code like a reverse shell?
15:42
So we have a function here for a reverse shell. We have this import inside the function to Because we are we want all the code of the necessary code to be inside one function So this is basically a reverse shell. So the attacker can control the the victim shell
16:01
from their computer How can we run this arbitrary code with pickle? Okay. So first we need to serialize this code Problem is pickle can really serialize code So we have to use marshal which which is another
16:22
Which is another module inside the Python standard library to serialize the code And yeah, we have the the dump and dumps and load and loads functions as we have in in in pickle we have in marshal and we can serialize the function with marshal dot dumps and we will then have the sequence of bytes and we
16:45
We can just make more readable we can encode with base 64 and then we'll have a base 64 String, which is basically the code of the function and if we need to run the function again
17:00
we then just Reverse the process we decode with base 64 We load with marshal and then we need to instantiate it with the function type class to Just providing the The result of marshal loads and then we can call the function as if we if we implemented the function in the code
17:25
So, okay, let's create the malicious pickle. I just explained how the pickle works So let's go through it. We have the the C the noting we are importing a function. So it's from model types It's the function function type why we're importing the function type first because the function type is
17:45
what caused the We want the result of the function that we went to to run the function type result Yeah, so inside the function type what are going to be its arguments? So here we have the D on
18:02
On the right when we have the the column 20 we have the mark to open the parameters and in column 21 we have Another import which is the the marshal loads We then have on column 36 another mark for parameters, but then for the the marshal loads function and
18:25
For this parameter we have another import which is the B64 decode from base 64 and then for B64 decode we have another parameter in column 55 and And now we're going to not going to import anything more
18:40
We're just going to pass the the value which is a new nickel string So in column 56, we have the uppercase V denoting a new nickel string, which is our base 64 encoded function We then have on column 81 the T to close the arguments to be 64 decode In column 82 we have the uppercase R to execute the B64 decode
19:06
In line 83 we have the T to close the argument for marshal loads and in column 84 We execute the marshal loads and then in column 85 Oh, I'm sorry I I said we didn't have any more input But we have the building globals import because as I showed in the previous slide
19:26
You have to use for in the function type. We have to pass the globals So yeah, we use the globals to pass as the second parameter for the function type The globals is a function so we have to to call the you have in column
19:41
106 and 107 just an empty list of arguments we then Use on column 108 and the uppercase R to call the globals and okay on line 111 we close the parameters for the function type and
20:02
No, I'm sorry you close the parameter for the For the marshal loads. Yeah, I got lost but in the end we're in line 115 we Execute the function type and on line 116 we stop
20:21
The code so yeah, we have our malicious pickle and I got a really a small Demonstration to it's a gift just to show it how it would work on the right We have the server code executing waiting for the connection and in the left We are going to open the malicious pickle and yes when it loads the pickle
20:41
then the reverse shell is connected and we can execute any comment we want from the from the server and Okay, how can we prevent that? Well, we can prevent that by signing the pickle with cryptographically secure Hash like HMAC so
21:01
Here we are creating a digest for the for the pickle with HMAC on the left and if we save these digest we can check when we want to load if the digest is the same and then if if it's it's the same then we can Trust it. We know it's secure and we can we also have alternative
21:24
So instead of using pickle for for storing Objects we can maybe use a safer serialization format like JSON which is Really really simple. Yeah, I have an example here, which is just a string yeah, okay, so let's go to our
21:43
Third talk. I'm going to try to be a little fast because we have Still a few things to talk about and and now we're going to talk about the power of the peeping stall Coleman So first we have to understand what happens when we run peeping stall, so I basically divide it
22:03
into four four things that happen it's more complicated than that, but basically first we have the identifications of base requirements and the given parameters then we have the resolution of dependencies and the determination of what will be installed and
22:20
The third thing that happens is that is the determination of the installation method then After determining the the one installation method you will use the the package is installed We're focusing on the the third thing which is the determination of installation method and again, I
22:40
simplified what really happens but Basically the logic is if we'll is available if we we have a wheel in the in the repository to download we'll It will download the wheel and install from it If the wheel is not available, it will download the package source code
23:01
And if it's possible to build the wheel from the source code It will build the wheel install from it. If it's not possible. It will install from sit up that pipe and this We're going to focus again if the wheel is not available So if the the person who uploaded the package to IPI didn't upload a wheel binary
23:26
so when when people downloads the the package source code and Try to build a wheel or tries to install from setup Dot PI in in both cases it will run set the point set up dot PI and the thing
23:42
We've set up dot PI is we're basically having a dynamic metadata, so Here is an example of a set up the PI file which just reads the along description from a readme file and calls the setup function, but well, it's
24:03
It's Python code so we can have things a bit more complex than that and in the right I just Put the the comments that would be called so to install the package We would have set up the PI and install and to create the to build the wheel
24:21
We have to set up the PI with this wheel and yes, so we have the set up the PI to to create dynamic metadata and How can we execute arbitrary code in the package installation is by Well, just adding code to the file. It's a Python file so you can add the code we want
24:41
So I'm adding the same code of the the reverse shall we show before the only difference here is instead of sub process Dot run instead of this function We're using sub process dot P open because we want to create a separate process instead of using the same process So that the the installation does and freezes and the user
25:02
will know it freezes and again, I have a demonstration we have the server on the right and we're installing the the Malicious zero pi which is something I uploaded to pipe guy and delete it. You can't install it anymore But if you install it, it's going to execute this it up the pipe because I didn't the portal wheel and yeah
25:24
We're going to have the reverse shell again and what is the real-life risk of this because you can think That you're not going to install any package. You you don't know you're just using I don't Standard packages like Django like requests
25:43
But we have a real problem which is type of squatting so Let's say I'm trying to install the requests package and I miss type and type this request Wrong and someone uploaded a malicious package to pipe guy
26:02
with this if requests spelled wrong and Then the code would be executed Because of that and this is a real problem so in 2021 We had almost 4,000
26:22
libraries which got deleted from pipe guy because of this because they were there are malicious and in here on the the right upside we have statistics from 2017 so from people trying to install
26:42
Package that are available from the standard libraries such as JSON OS Says platform so someone uploaded this This this packages to the pipe guy and this can be malicious packages. So if a beginner user I don't see an example that uses JSON and think so I need to install it
27:04
They are trying to install it, but they're installing the malicious package and Well, another risk is if we use the extra index URL Flag because with this flag we can basically
27:21
use another repository instead of the The center pipe guy and I had another I don't have time to go deep into it, but I added a medium Article that basically it's a guy that made a lot of money by basically doing this
27:42
So Okay, how can we prevent this we can use the only binary flag? We've been installed to only download if we have the wheel and we can require hashes use the require hashes flag to Verify the The hash some to know we were the only the the right thing and
28:04
well, we should never download a package as pseudo or as admin because If you for some reason install a malicious package you have the admin permission and can really do some damage Okay, so let's go to the fourth topic which is about outdated dependencies
28:27
Okay, so basically vulnerabilities are found all the time I have here a screenshot from the I think it's the latest or No, I think right now we have the 407 but on on Django release 406 we
28:44
fixed security a security issue Which is a potential SQL injection and yeah, this happens all the time everyone is always finding new vulnerabilities and fixing these vulnerabilities, so
29:02
It's important to keep up with the releases of the packages we use and it's good if we can keep up with the CV even our abilities list and So we know what are the I don't see all the vulnerabilities found Yeah, the fifth top come when I talk about is basically continuation from the what I just talked but
29:27
It is a specific to Python so outdated Python and again from their abilities are found all the time these are This is a list of some of the vulnerabilities found in Python and when were they disclosure
29:45
Yeah, and this are currently unfixed whenever they saw our vulnerabilities that is to exist and It's important to understand the status of the the Python versions so
30:01
So we don't end up using an unsupported Python version so we have this available in the docs So so we know Well, when will this version of Python I'm using Stop being stop having security updates. So right now we have the the
30:22
From 3.7 that is having security updates to 3.11, which is having bug fixes and 3.6 from and before we it got to the end of life, so we don't have even security updates
30:40
So if you find a security bug and we'll fix it for the 3.7 Onward but we won't fix for the 3.6. And well, this is going to continue one day we won't Updated Security bugs from 3.7. And yeah that goes on and also you should be cautious with deprecated functions
31:04
So if you search the docs you find some deprecated functions I added an example in the temp file module with the make temp function Which is obsolete You shouldn't use it anymore because it can introduce a security hole
31:23
Because of the of a race condition that can happen and We have better functions to do what this function used to do But the function still exists. So if I if you call the function it will work So yeah, you should be cautious with functions that are deprecated. You should look into it
31:43
the six The six topic is about so the silver randomness. So the problem with randomness I saw this tweet a while ago I'm not going to show the user think it's a deleted tweet now, but it was a tweet
32:02
Talking about how to create a secure password generator in four simple lines of item code and This is the code. So it's We have a list of characters a sequence of characters to choose we import the the running and the choice from random from the random module and we use the random choice to
32:26
Create the the password. This is the code that this person presented as secure and this is the problem because of the random module and the Well what I call the infamous seat and the problem
32:42
With the random module is basically almost all the functions in the random module Use a seed so we can We can determine what the seed will be with the seed function so in here in line four, I called random dot seed with the seed arrow Python and
33:01
well When we we generate the password with the same method the person generated We will always end up with this result. So if you get your computer right now and run this code Even using the random module, which should be random Or you think that it's random it will always end up with the same result because of the sit
33:27
So we have lots of alternatives to generate secure passwords or stuff like that So we have the proper secrets module, which is great. It's simple to use we have
33:42
The same functions that the random module has so on the right the first example I show is the token acts which we can create a token and we determine the number of bytes We then use the secrets of choice to basically do the same thing The person was doing but in a secure way because we're using secrets so it's not
34:06
by this predefined seed We can use the you random function from the OS module which would be a little bit more complicated, but we can do that and There is one class in the random module
34:23
That is secure which is the system random It is the only class that uses a cryptographically secure Generator random generator random number generator, which it is this system random class And so the last example on the right is using the system random class to generate the password
34:44
Okay, the seventh topic I want to talk about is about bomb files So yeah, watch out for bomb files we have Okay I'm going to to speed up to end up in this section
35:04
So we have the the billion last attack or X XML Functions are vulnerable to that We can use the diffuse XML package to Secure that we have a problem also with tar bombs if we don't expect the the tar file we are extracting
35:25
We can end up with this path traversal problem. You can Prevent this by expecting the the files. Sorry. I meant to speed it up So the last thing is about the assert a keyword
35:41
So, what is the purpose of assert we're using assert now for tests and we've by test and stuff like that but we basically check if a condition is true, and if it's not true, you have assertion error and People sometimes try to save a line with assert. So we have this Two codes in the in the left I raise the value error if the password is not what the predefined password was and in the right I use the search for
36:05
This but the problem is this are not equivalent Because assert actually checks for the debug Constant and this debug constant is set by the old flag. So if we pass the old flag, it's the optimized flag
36:21
Then the debug will be false and the assert will have no effect. So we shouldn't use assert in our code, I Just want to talk about Auditing our code so we have lots of options lots of programs to audit our code and to check for security vulnerabilities in our code The one I'm showing an example is bandit. It's really simple to use. So in this example, it's showing
36:45
the code have a Randall number generator a problem I talked before and yeah, that's it. So just to finish the talk I want to To Tell five key points to never forget So if we if you learn something from if you want to learn something from this talk
37:04
Just remember these five points. The first one is to never trust user input So basically, I think three topics I talked about the evil one the people stolen the Pico it's basically about user input
37:20
The second point is avoid running Python code as pseudo or admin so we can diminish the damages Keep your system up-to-date and your packages up-to-date. So we have the Fixed for the security vulnerabilities that can happen Read the docs. So I know the docs are not always the the most
37:42
Friendly way to learn something but in the docs we will have the the warnings for dangerous modules We have the warnings for deprecated functions. And this is why I think it's important to some sometimes read the docs and Use a static code analysis tool such as bandit or you have many options to analyze the code and search for
38:07
Security vulnerabilities and That's it. I think I managed to finish on time. Thank you. And this is my contact information And yeah, that's it. Thank you guys. I
38:23
Think we I think we have time for one or two questions Is there any one in the audience like to ask the question if you could use the mic, please? Do we have any remote questions? No Well again, thank you. Another round of applause for Yan, please