<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sqreen</title>
    <description>The latest articles on DEV Community by Sqreen (@sqreenio).</description>
    <link>https://dev.to/sqreenio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F152%2Fd321f046-dcf2-4d95-a8a8-3ef1042ed582.png</url>
      <title>DEV Community: Sqreen</title>
      <link>https://dev.to/sqreenio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sqreenio"/>
    <language>en</language>
    <item>
      <title>Security leader interview: Adam Surak on approaching security at Algolia</title>
      <dc:creator>Sqreen</dc:creator>
      <pubDate>Mon, 20 May 2019 22:43:44 +0000</pubDate>
      <link>https://dev.to/sqreenio/security-leader-interview-adam-surak-on-approaching-security-at-algolia-45dl</link>
      <guid>https://dev.to/sqreenio/security-leader-interview-adam-surak-on-approaching-security-at-algolia-45dl</guid>
      <description>&lt;p&gt;Today, we have a new entry in our security leader interview series. Recently, we sat down with Adam Surak, Director of Infrastructure and Security at &lt;a href="https://www.algolia.com/"&gt;Algolia&lt;/a&gt;, to discuss his approach to security and what he’s learned as far as security goes throughout his career. We wanted to share the great insights that came out of our conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tell me a little bit about yourself and how you got to where you are at Algolia
&lt;/h2&gt;

&lt;p&gt;My name is Adam Surak. I am the Director of Infrastructure and Security at Algolia. I originally joined Algolia in 2014 as an SRE focused on automating infrastructure. At the time, Algolia was 8 people. Now it’s 350, and I manage a team of 22, so quite a bit of growth!&lt;/p&gt;

&lt;p&gt;Prior to Algolia, I was a teacher and researcher at a technical university in Finland.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is your history with security?
&lt;/h2&gt;

&lt;p&gt;Probably my original and most fun experience with security was back in high school. I spent some time developing a web game. At the time, it was a popular thing to try and hack web games, so I had to spend a lot of time figuring out how to protect it.&lt;/p&gt;

&lt;p&gt;Later on, at my job at the university in Finland, I worked with several Russians who had worked in state security in Russia. They were very strict and focused on security. Whenever we developed something, they took the approach of asking “how can we hack it?” This was my first exposure to this angle of security; this way of looking at things.&lt;/p&gt;

&lt;h2&gt;
  
  
  How have you approached security at Algolia so far?
&lt;/h2&gt;

&lt;p&gt;Over the years at Algolia as we grew, we started to have real security requirements. Our primary problem, from a security point of view, is that to make Algolia’s service work, we need to have copies of our customers’ data, and we need to be able to read it, so we can’t just encrypt it at the edge and never look at it. This opens up a lot of potential security risk. As a result, &lt;a href="https://blog.algolia.com/algolia-vault/"&gt;we started to focus on security&lt;/a&gt; early on in the company’s life.&lt;/p&gt;

&lt;p&gt;In early 2015, I was tagged to take on security for Algolia, as I had the deepest knowledge at the time. Now in 2019, I have a team of 3 security engineers, compliance lead, and support of an experienced legal team. We focus on security, compliance, and activities like gap analysis and SOC2 audits.&lt;/p&gt;

&lt;p&gt;One thing we started doing super early on was focusing on building a habit around securing personal devices. We had a lot of people coming in and out of the office, but people frequently left their laptops and such unlocked. We implemented a “shame channel” in Slack, so that if you catch someone’s device unlocked, you post in the shame channel on their Slack account. It’s a lighthearted way of keeping people accountable and &lt;a href="https://www.sqreen.com/checklists/saas-cto-security-checklist"&gt;building the habit around keeping their devices secure&lt;/a&gt;. Nowadays, people tell me they even lock their computers when they’re alone at home and get up to go to the bathroom! So the habit has really caught on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is your philosophy on security?
&lt;/h2&gt;

&lt;p&gt;I would sum it up by saying that security shouldn’t be something that gets patched on top. I truly believe that security and compliance need to be automated. A lot of things that we’re doing with security can be written as code. Historically, security engineers haven’t been looked at as software engineers, but they need to be today. Their job is to automate. The scale is too large to check everything manually.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Don’t reinvent the wheel. There are a lot of tools that have figured an aspect of security out. Take advantage of them.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another thing I believe is of the utmost importance is finding ways to hardcode security into software. In the past, a lot of security has just been policies that no one wanted to follow. Today, these policies need to be brought into the software. One example is with passwords. Nowadays, you prevent people from having an insecure password in software. You force them to enter a secure one or else they can’t sign up or log on. We don’t do that with other security issues, but we should.&lt;/p&gt;

&lt;p&gt;Security needs to be brought closer to developers. At Algolia, the security team sits down with developers and does a PoC of the code they want to create. They look for potential weak points and security risks together. You have to find a level of cooperation, and have the teams work together to solve problems. If the security team is just calling out risks or compliance issues and walking away, you won’t end up with a strong security situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How have you scaled and evolved security at Algolia?
&lt;/h2&gt;

&lt;p&gt;Scaling security is a tricky question, because it’s rarely possible to scale the security team at the pace that company scales. That has been the case for us at Algolia.&lt;/p&gt;

&lt;p&gt;In 2015, one of our customers requested that we do a pentest. It was our first one. When the report came back, they called out a couple things that didn’t matter, and a couple things we didn’t originally think were too important, such as our SSH board being exposed to the world (since we had built protections on top of it). Eventually, we realized that some of these items were worth fixing and it’s strengthened our security.&lt;/p&gt;

&lt;p&gt;At the end of 2015, we felt confident enough to open up a bug bounty program, in invitation-only mode. We were 25 people at Algolia at the time. We invited a lot of people and eventually felt like we had caught most things, so we opened it up to the public.&lt;/p&gt;

&lt;p&gt;It was the biggest security surprise in our company history. After a couple days, everything blew up. We got flooded with alerts and emails, and things started breaking. It took us two months to recover. There were a huge number of issues!&lt;/p&gt;

&lt;p&gt;It’s much smoother these days, since we caught up on our security debt from the first effort. It also has another important effect: when you’re on the public record, you can’t rely on “security by obscurity.” It adds a level of pressure. When people internally are saying something is an issue, it really helps to also have someone external say the same thing. It makes it real and makes you want to fix it, rather than fall prey to the belief that the issue is too small and no one will find it or be bothered by it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Don’t treat security like an afterthought. Invest in it early. The longer you delay, the bigger your security debt becomes.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We’ve also tried to bring about a security mindset at Algolia. Security people think differently. They’re not focused on what a feature does; they care about the risk and how they could be exposed. This mindset tries to do away with the natural inclination to be protective of your work and shield it from a security eye. By paying attention to security and showing people the impact of an exploit (by exploiting it internally for example), you can really communicate the importance of security in a way that sticks with people. It makes the impact real.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the challenges you see blocking your ideal state of security today?
&lt;/h2&gt;

&lt;p&gt;The tools out there aren’t focusing enough on the signal to noise ratio. We need to shift that mindset and push tools towards only outputting actionable information. A lot of security tools output absolutely everything, so the real signal is buried in noise. This is super discouraging to the user. It would be much better to start narrow with the outputs and incrementally improve.&lt;/p&gt;

&lt;p&gt;Another thing I see is the fact that security is flooded with massive amounts of data. Multiple layers, multiple applications, multiple stacks. The volume of data is so massive that security teams are pushed towards anomaly detection — just looking for outliers.&lt;/p&gt;

&lt;p&gt;Another challenge is around vulnerable dependencies. In an ideal world, all dependencies would be kept up-to-date. In reality however, it’s not always possible. Sometimes, a thing you rely on gets deprecated in a new version or the new version breaks something in your flow, and you’re forced to stick with the old version. As a result, you need to be very aware of which CVEs you’re exposed to so you can find ways to wrap protection around them. You also need to decide if these CVEs are actual risks to you and your business. They need to be exploitable and something that could have an impact.&lt;/p&gt;

&lt;p&gt;Security needs to move towards actionability everywhere. We need clear signals and clear recommendations of actions to take based on actual risks that could have an impact on your business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you have any advice for companies or people beginning their own security journey?
&lt;/h2&gt;

&lt;p&gt;If you’re thinking about starting a public bug bounty program, pause and talk to someone who’s done it first! It’s a much bigger event than it seems!&lt;/p&gt;

&lt;p&gt;Really though, here are some pieces of advice based on what I’ve learned along the way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don’t treat security like an afterthought. Invest in it early. The longer you delay, the bigger your security debt becomes. I knew a company that ignored security for years before finally doing a pentest. The report they received was 100 pages long. They had to stall work for 3-6 months just to take care of the major issues. &lt;/li&gt;
&lt;li&gt;Look at automated tools, especially early on when you don’t have to time to look at all the issues that crop up manually. You likely don’t need to be resilient against big state actors; you just need to protect against competitors and script kiddies at first. The level of security you need depends on the level of threat you can reasonably expect. For most businesses, protecting your code and your applications is enough in the beginning.&lt;/li&gt;
&lt;li&gt;Don’t reinvent the wheel. There are a lot of tools that have figured an aspect of security out. Take advantage of them. Even outside of security tools themselves, you should leverage other companies’ security teams. For example, leverage Slack’s security capabilities rather than creating your own messaging app. &lt;/li&gt;
&lt;li&gt;Finally, ask people in the industry for help! Despite some reputation to the contrary, most people in the security space are happy to share their knowledge and experiences with you. Ask them for coffee or to sit on your board of advisors. Involve them, and they’ll be happy to help. &lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Thanks so much to Adam for his time. If you’d like to read more technical and security leader interviews, check out our conversation with &lt;a href="https://blog.sqreen.com/devops-uniplaces/"&gt;Ricardo Félix on scaling DevOps at Uniplaces&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blog.sqreen.com/security-leader-interview-adam-surak-algolia/"&gt;Security leader interview: Adam Surak on approaching security at Algolia&lt;/a&gt; appeared first on &lt;a href="https://blog.sqreen.com"&gt;Sqreen Blog | Modern Application Security&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
      <category>interview</category>
      <category>devsecops</category>
    </item>
    <item>
      <title>How to debug memory leaks in a Node.js application on Heroku</title>
      <dc:creator>Sqreen</dc:creator>
      <pubDate>Thu, 18 Apr 2019 16:25:35 +0000</pubDate>
      <link>https://dev.to/sqreenio/how-to-debug-memory-leaks-in-a-node-js-application-on-heroku-jpj</link>
      <guid>https://dev.to/sqreenio/how-to-debug-memory-leaks-in-a-node-js-application-on-heroku-jpj</guid>
      <description>&lt;p&gt;Debugging memory leaks is rarely a piece of cake, especially when they only happen in production. The best way I’ve found to debug memory leaks in a Node.js application on Heroku is to analyze heap dumps.&lt;/p&gt;

&lt;p&gt;Obtaining such heap dumps in production can be challenging, as it might be hard to connect remotely to a production instance with the debugger.&lt;/p&gt;

&lt;p&gt;In this article, we will go through the steps needed to obtain and analyze heap dumps from a running Heroku dyno. This method will also work on other platforms as long as it is possible to perform similar operations.&lt;/p&gt;

&lt;p&gt;To obtain the heap dump we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the Node.js process has a debugger listening&lt;/li&gt;
&lt;li&gt;Connect Chrome dev tools to the Node.js process&lt;/li&gt;
&lt;li&gt;Collect the heap dump and download it locally&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enabling the Node.js inspector
&lt;/h2&gt;

&lt;p&gt;Before we can analyze anything, we need to ensure that we have a debugger listening. There are two ways to enable the inspector on a Node.js process:&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 1: Changing the startup command
&lt;/h3&gt;

&lt;p&gt;By default, Heroku starts a Node.js application by running &lt;code&gt;npm start&lt;/code&gt;. Usually, this calls a script defined in the &lt;code&gt;package.json&lt;/code&gt; of the application:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Changing this script to add the &lt;code&gt;--inspect&lt;/code&gt; (as documented &lt;a href="https://nodejs.org/en/docs/guides/debugging-getting-started/" rel="noopener noreferrer"&gt;here&lt;/a&gt;) flag will start the instances of the application with a debugger listening on a port that will be specified in the logs:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In total, this is what it will look like when you implement this solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2F3w1D7FwRifOzwf9MoEvnoY4ziAcKuSEOF8Nv0ytBAQ2zf64oZxMJOge14k4aE_wy5GmwMN0fPHcIRVqIj6qyCtHN0uuMiqLa_RQKBqbzeHrPIfRxwgjJSAzPJXRj-PKz8V2-79sl" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2F3w1D7FwRifOzwf9MoEvnoY4ziAcKuSEOF8Nv0ytBAQ2zf64oZxMJOge14k4aE_wy5GmwMN0fPHcIRVqIj6qyCtHN0uuMiqLa_RQKBqbzeHrPIfRxwgjJSAzPJXRj-PKz8V2-79sl"&gt;&lt;/a&gt;What changing the startup command looks like Heroku logs&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 2: Changing the process state through SSH
&lt;/h3&gt;

&lt;p&gt;Solution 1 is the easiest way to enable an inspector in Node.js, but there are situations in which you can’t or won’t want to enable it. For example, you might not have access to the source code of the application and therefore can’t change the startup script. Or maybe you don’t want to change the state of all your production dynos and deploy your application only for debugging.&lt;/p&gt;

&lt;p&gt;Fortunately, there is a way to send a signal to the process to enable a debugger session.&lt;/p&gt;

&lt;p&gt;In order to do so, you will need the &lt;a href="https://devcenter.heroku.com/articles/heroku-cli" rel="noopener noreferrer"&gt;Heroku CLI&lt;/a&gt; to connect to the dyno through an SSH connection.&lt;/p&gt;

&lt;p&gt;For all following Heroku commands, you might need to add the &lt;code&gt;--app &amp;lt;app_name&amp;gt;&lt;/code&gt; flag to tell the CLI which application to connect to. Also, by default, the CLI will connect to the dyno named &lt;code&gt;web.1&lt;/code&gt; and you might want to change that through the command line (see &lt;a href="https://devcenter.heroku.com/articles/exec" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;First, let’s connect to the dyno (Heroku might need to restart the dyno at this point):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Then, we need to identify the PID of the Node.js process:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In our case, the process started with &lt;code&gt;node bin/www&lt;/code&gt; has the PID 69, we will now send a signal to the process to let it know we need it to enable its debugger:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see, we have sent the &lt;code&gt;USR1&lt;/code&gt; signal to the process to change its state (as documented on &lt;a href="https://nodejs.org/en/docs/guides/debugging-getting-started/" rel="noopener noreferrer"&gt;this page&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This is confirmed through the application’s logs on Heroku:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FFbQGi3UtDj23Xqztd40OY00NLMFv6iyxRHA0Y8YLkeiXezIzNeJm_hzcEgjeoX2N-I6mi3ps1_WLgkEBBgS4gbx92MAAVZJoEKVKmeoSbIp5yS3Hgp6WlgJ21_pPQdZN0wJW2m_I" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FFbQGi3UtDj23Xqztd40OY00NLMFv6iyxRHA0Y8YLkeiXezIzNeJm_hzcEgjeoX2N-I6mi3ps1_WLgkEBBgS4gbx92MAAVZJoEKVKmeoSbIp5yS3Hgp6WlgJ21_pPQdZN0wJW2m_I"&gt;&lt;/a&gt;Changing the process state through signals&lt;/p&gt;

&lt;h2&gt;
  
  
  Attaching debugging tools to a Node.js process
&lt;/h2&gt;

&lt;p&gt;In order to attach the debugging tools to our Node.js process, we need to make the WebSocket used by the debugger accessible on our local machine.&lt;/p&gt;

&lt;p&gt;To do that, we first need to identify the port we need to forward. This can be found in the logs of the application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FAPJnqUvq0xN_-hryYWb0PQpuwT5R6xVCaFNSMNa0TTg7BCICSloq_UKJa0kkUVfk_j5uf2fGyRiR7tkJr0NyZIOkhCSwLocKC3qXkWQXoaRwN8gWjLvBSZqxBLVbXFF9R0Sz73Wf" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FAPJnqUvq0xN_-hryYWb0PQpuwT5R6xVCaFNSMNa0TTg7BCICSloq_UKJa0kkUVfk_j5uf2fGyRiR7tkJr0NyZIOkhCSwLocKC3qXkWQXoaRwN8gWjLvBSZqxBLVbXFF9R0Sz73Wf"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our case, this is the port &lt;code&gt;9229&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To forward the port locally, let’s use the Heroku CLI:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;When port forwarding is established, we just need to open Chrome DevTools (going to chrome://inspect on Chrome) and after a few seconds, a target should be displayed under “Remote targets.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2Fd3804gLrIbLkBhR2dKZ9FHraRwkU4R7BQuRPJEz-TyLMO_EOQm4sbY9TX81IXBiQhUl_xAYFp5eEcAmKc1YOk2uWaQyye6eVD8-_N7q6xz2uUP2-8JrpdE2ZAsj450UATIMUjDub" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2Fd3804gLrIbLkBhR2dKZ9FHraRwkU4R7BQuRPJEz-TyLMO_EOQm4sbY9TX81IXBiQhUl_xAYFp5eEcAmKc1YOk2uWaQyye6eVD8-_N7q6xz2uUP2-8JrpdE2ZAsj450UATIMUjDub"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the target does not appear, make sure the port used is listed when clicking on “Configure.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Collecting the heap dump and reading it
&lt;/h2&gt;

&lt;p&gt;Now it’s time to collect and read the heap dump. First, click on the “inspect” link. This will open a new window with different tabs.&lt;/p&gt;

&lt;p&gt;Find the “Memory” one — you should be prompted with the following window:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2Fqy9AEJ6CbSKigmwJV11SbSH1XMujFiKtBKHxlsZa0Y7yMeqjwLJVgwWV6Vyzf3uGgIyejLLLf7SMkAotPnPmA69tbtcF1FvvWh_AWQ0xlp2BN7FBdYxv7OR5bWx-s7Hrf2VdXEqf" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2Fqy9AEJ6CbSKigmwJV11SbSH1XMujFiKtBKHxlsZa0Y7yMeqjwLJVgwWV6Vyzf3uGgIyejLLLf7SMkAotPnPmA69tbtcF1FvvWh_AWQ0xlp2BN7FBdYxv7OR5bWx-s7Hrf2VdXEqf"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on “Take snapshot.” A new file will appear in the left hand side panel. Clicking on it will display the content of the heap:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2F2VfnVv-MeUGhKQYB9vBoRzrNFHULDSREKZnoPrLxea1hv6pdzpCJ3DB_pJZKuvSfGKz8KYBwTvajJNFRFmlT1tpPb2HKN0-K-JqJpFjBpHiHOzVwNFN9CY3YCL6xETamuAjBQZDF" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2F2VfnVv-MeUGhKQYB9vBoRzrNFHULDSREKZnoPrLxea1hv6pdzpCJ3DB_pJZKuvSfGKz8KYBwTvajJNFRFmlT1tpPb2HKN0-K-JqJpFjBpHiHOzVwNFN9CY3YCL6xETamuAjBQZDF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this view, objects are sorted by constructor. For the purpose of this walkthrough, I have introduced a memory leak in this application by creating an instance of the &lt;code&gt;Access&lt;/code&gt; class for each request. This instance keeps a reference to the current HTTP requests and is never cleaned:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can see for yourself that this indeed leaks in the application.&lt;/p&gt;

&lt;p&gt;To detect constructors that have the biggest memory impact, let’s sort the items of this view by “Retained size” (You can learn more about these terms on &lt;a href="https://developers.google.com/web/tools/chrome-devtools/memory-problems/memory-101" rel="noopener noreferrer"&gt;Chrome’s website&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2F3-QDuLDUFN0NUAlm-wCEidkY-K_RLV96knnzeoDl7r2yLpjhaiJsNBFWNwAbYZEVDXS6E_me7owXJ_ezUooEcYh7mvXq0WydNURWzukoKWTl1YMFJaqgHnpGa_rZwfyDn2HvRWxm" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2F3-QDuLDUFN0NUAlm-wCEidkY-K_RLV96knnzeoDl7r2yLpjhaiJsNBFWNwAbYZEVDXS6E_me7owXJ_ezUooEcYh7mvXq0WydNURWzukoKWTl1YMFJaqgHnpGa_rZwfyDn2HvRWxm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that 24% of the process memory is held by these objects.&lt;/p&gt;

&lt;p&gt;Now let’s look at how to identify where the leak is happening.&lt;/p&gt;

&lt;p&gt;When expanding the list of the constructor, we can see all instances of this class. By selecting one of these instances, the list of retainers of this object is displayed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2Fwbo7ng5_qPH4LrHJyWmLtxKXfDeY-Uwz_qhKc8zaZGdWpWAD5kt8IcN5Bs-Xf2UD_x8kfL1mjV42c1mlXgoebjuboavW_56JCEFowewnmhQH0zPwvUArMG5pCnof7UXd42cHJ-pf" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2Fwbo7ng5_qPH4LrHJyWmLtxKXfDeY-Uwz_qhKc8zaZGdWpWAD5kt8IcN5Bs-Xf2UD_x8kfL1mjV42c1mlXgoebjuboavW_56JCEFowewnmhQH0zPwvUArMG5pCnof7UXd42cHJ-pf"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our case, the &lt;code&gt;allAccesses&lt;/code&gt; set is clearly identified as the bad actor! With the location of the memory leak identified, we have everything we need to go off and fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few tips for debugging memory leaks in Node.js
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use the compare view
&lt;/h3&gt;

&lt;p&gt;When suspecting a memory leak, you might want to take two separate heap dumps with a few minutes between them. Then, using the “comparison view”, you can identify which elements have been created between the snapshots.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use constructors and classes in the code
&lt;/h3&gt;

&lt;p&gt;As shown in the article, when reading the heap dump, elements are grouped by their constructor.&lt;/p&gt;

&lt;p&gt;Using more than just classes in your code will make it more readable (and arguably &lt;a href="https://blog.sqreen.com/optimize-your-node-app-by-simply-upgrading-node-js/" rel="noopener noreferrer"&gt;more performant&lt;/a&gt;, but that’s probably a topic for another article). It will save you so much time when hunting for a memory leak. Do it — future you will be grateful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trigger a garbage collection before collecting the snapshot
&lt;/h3&gt;

&lt;p&gt;At the top left hand side of this screen, there’s a little bin picture. Clicking on it will trigger a garbage collection in the application. Doing this before collecting a memory snapshot will actually remove elements that are not leaking and therefore could help save you time when browsing the heap content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we’ve taken a look at how to debug memory leaks in a Node.js process running on Heroku by connecting and using a debugger. Feel free to contact me on &lt;a href="https://twitter.com/poledesfetes" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; if you have any questions or if you want to share your own tips with me!&lt;/p&gt;

&lt;p&gt;If you’re looking for next steps or a more advanced way to debug memory leaks in Node.js in Heroku, try this: Since the Heroku CLI is written with Node.js, you could write an automated tool to perform the collection and start analyzing heap dumps.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blog.sqreen.com/memory-leaks-nodejs-heroku/" rel="noopener noreferrer"&gt;How to debug memory leaks in a Node.js application on Heroku&lt;/a&gt; appeared first on &lt;a href="https://blog.sqreen.com" rel="noopener noreferrer"&gt;Sqreen Blog | Modern Application Security&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>heroku</category>
      <category>debugging</category>
      <category>dev</category>
    </item>
    <item>
      <title>How to fully leverage your pentest</title>
      <dc:creator>Sqreen</dc:creator>
      <pubDate>Thu, 28 Mar 2019 16:05:54 +0000</pubDate>
      <link>https://dev.to/sqreenio/how-to-fully-leverage-your-pentest-n50</link>
      <guid>https://dev.to/sqreenio/how-to-fully-leverage-your-pentest-n50</guid>
      <description>&lt;p&gt;Before co-founding &lt;a href="https://www.sqreen.com/" rel="noopener noreferrer"&gt;Sqreen&lt;/a&gt;, I spent years stressing applications both from the outside (as a security consultant) and from the inside (as part of Apple’s Red Team). As a result, I’m often asked by fellow CTOs what the best practices are in terms of &lt;a href="https://blog.sqreen.com/security-best-practices-saas-startups/" rel="noopener noreferrer"&gt;SaaS security&lt;/a&gt; and penetration tests (pentests). So this article will shed light on pentest best practices and some mistakes you should avoid.&lt;/p&gt;

&lt;p&gt;There are plenty of ways to proactively test an application’s security. One of the more common methods is performing penetration tests on your application. A pentest is a way to reveal security issues in your application and infrastructure from a neutral third party in a way that you can leverage to positively affect the whole company.&lt;/p&gt;

&lt;p&gt;There are plenty of resources out there to help you prepare for a pentest. This article focuses on the actionable learnings a pentest should provide to you, beyond the pages of the report provided by the pentesters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 3 axes of a pentest
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FgRKOKqUXfoK-ePB86261D6uS7zf5S-_Dnwny014Fp_2GfTY6-tnS_O9cVFFZ6yRWRdj0gG5YlaAcvhRs6i8_-V4TH7-xr1RFU9dTiiwPF_SwyLb9fB4MqQ5I9_h84nO6dmPOfz96" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FgRKOKqUXfoK-ePB86261D6uS7zf5S-_Dnwny014Fp_2GfTY6-tnS_O9cVFFZ6yRWRdj0gG5YlaAcvhRs6i8_-V4TH7-xr1RFU9dTiiwPF_SwyLb9fB4MqQ5I9_h84nO6dmPOfz96"&gt;&lt;/a&gt;The 3 learning axes of a pentest&lt;br&gt;&lt;/p&gt;

&lt;p&gt;The learnings you can get out of a penetration test can be grouped into 3 dimensions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the technical learnings:

&lt;ul&gt;
&lt;li&gt;the state of your code security&lt;/li&gt;
&lt;li&gt;the state of your infrastructure security&lt;/li&gt;
&lt;li&gt;the quality of the monitoring and security alerting in place&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;the organizational learnings:

&lt;ul&gt;
&lt;li&gt;how new services or infrastructure changes are handled (e.g. moving to the cloud)&lt;/li&gt;
&lt;li&gt;whether processes and ownership are clearly identified&lt;/li&gt;
&lt;li&gt;the effectiveness of the processes in place&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;the human learnings:

&lt;ul&gt;
&lt;li&gt;the team’s reaction when security issues are reported&lt;/li&gt;
&lt;li&gt;the way the company (hierarchy, stakeholders, etc.) handles security reports.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The technical report and the discussion with the auditors will mostly tell you about the technical axis. It is up to you, however, to carefully prepare your pentest in order to walk away with key insights and clear action items around the human and organizational dimensions.&lt;/p&gt;

&lt;p&gt;A pentest also provides a way to assess how your security has evolved over time. Every penetration test should be followed by some days of validation tests – to ensure that the items you found and planned to fix have indeed been fixed. You should also provide previous test reports to the security auditors as a starting point to find initial vulnerabilities, iterate on the existing ones, and ensure they were fixed (if they’re present again, it means a regression occurred).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The technical learnings&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A pentest will very likely give you new technical insight into your infrastructure and application. It’s important to thoroughly analyze how the technical side of your app responds to the pentesters, and how the tools you’ve set up to monitor and protect your app react. The report you get from the pentesters will give you a great overview, but you know your environment better than anyone, and there’s a lot to learn as well from how it responds during the pentest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prior to the pentest
&lt;/h3&gt;

&lt;p&gt;Before the pentest begins, you and your dev team should review the backlog you have around security. Do you have a security tag in your bug tracker? How many tickets are tagged with security? How old are they?&lt;/p&gt;

&lt;p&gt;No security tickets in the backlog most likely denotes a lack of attention on the security front. Otherwise, check how many have been solved in the past months. If the answer is none, it probably means you haven’t been prioritizing security enough!&lt;/p&gt;

&lt;p&gt;Also, ensure your team is up to date on their technical security knowledge: does everyone knows what an XSS is? An injection? Same Origin Policy? CSRF? &lt;a href="https://blog.sqreen.com/content-security-policy/" rel="noopener noreferrer"&gt;Content Security Policy&lt;/a&gt;? If your team has too many gaps, then you will need to start with updating your team’s knowledge prior to beginning any kind of fixes after the pentest concludes.&lt;/p&gt;

&lt;h3&gt;
  
  
  During the pentest
&lt;/h3&gt;

&lt;p&gt;The quality and effectiveness of your monitoring and alerting tools is one factor to check when you’re doing a pentest. There are plenty of things a team monitors that may trigger because of a pentest. An exception manager, such as &lt;a href="https://www.sentry.io" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;, will have unusual activity during most penetration tests that your dev team will need to interpret.&lt;/p&gt;

&lt;p&gt;You should also check your performance monitoring tool (such as &lt;a href="http://www.newrelic.com" rel="noopener noreferrer"&gt;New Relic&lt;/a&gt;), which can highlight slow parts of the application during the pentest. The tests may slow down your application and put pressure on some specific parts of your infrastructure (e.g. a database or a microservice). This can lead to the detection of potential applicative DOS, and require specific optimization or rate limiting in order to prevent exhausting it. Most penetration tests do not look for DOS since they focus on testing the production: that’s something you need to look for yourself.&lt;/p&gt;

&lt;p&gt;Your log monitoring solution will be a good source of information as well and can also tell you if your application is getting too slow and starts to answer with timeouts or errors. It’s worth checking your logs to see if you have issues in this space.&lt;/p&gt;

&lt;p&gt;Eventually, your security tools will generate alerts regarding the attack. Make sure these alerts came from the testers (based on the IP address, the user names, etc.…) and take screenshots. The testers are gonna be pleasantly surprised you managed to catch them.&lt;/p&gt;

&lt;p&gt;All of this information will most likely be unnoticed by a security researcher performing a test on your application, because they only have an external point of view on your system. It is up to you to be reactive when these kind of alerts occur and interpret them appropriately.&lt;/p&gt;

&lt;p&gt;Refrain from fixing anything the testers may report to you until after the pentest fully wraps up. Doing so would prevent them from fully understanding and exploiting what they found, and also from finding more vulnerabilities in that vein.&lt;/p&gt;

&lt;h3&gt;
  
  
  After the pentest
&lt;/h3&gt;

&lt;p&gt;The report that the pentesters deliver to you at the end of the test will cover any technical vulnerabilities that they’ve uncovered. It is up to you and your team to then prioritize and implement fixes. Many pentests come with a validation period, which is a time during which people can just ask their security contractor to ensure the reported weaknesses have been validated. Using a clear mapping between the pentest and your tickets will help you organize and prioritize this accordingly.&lt;/p&gt;

&lt;p&gt;Take the time to speak in depth with the pentesters about what they’ve found in order to get the most you can out of the exercise. Pentesting companies often offer training, and organizing half a day of training on a particularly hard-to-understand vulnerability could be especially useful to level up your developers and get them interested in the subject.&lt;/p&gt;

&lt;p&gt;Additionally, the report serves as a point-in-time understanding of the state of your infrastructure security and the state of your code security. It will also help you to take a step back and figure out where the gap areas are in your team. Should you train your team on a given family of vulnerabilities? Improve your processes to have a bigger security focus when writing specifications? Hire someone to challenge your team on their security point of view? Hire someone who could be a security champion? The pentest report can help you decide answers to questions like these.&lt;/p&gt;

&lt;h3&gt;
  
  
  tl;dr: actions for the technical axis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Understand your security issue backlog and the state of security knowledge on your team&lt;/li&gt;
&lt;li&gt;Check that your monitoring solutions are working and are properly used by your developers&lt;/li&gt;
&lt;li&gt;Take the time to fully understand the report that the pentesters produce, and take concrete steps to improve your security knowledge on the team and your security within your applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The organizational learnings
&lt;/h2&gt;

&lt;p&gt;Pentests can give you insight into your organization as well. The way your security processes work (or don’t) in practice and the way your team functions as a unit are all key things to watch for and determine what needs improvement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prior to the pentest
&lt;/h3&gt;

&lt;p&gt;This is the time to review your security processes. Ensure the responsibilities for your various processes are well-defined and clearly known. You should know who to alert when security vulnerabilities are found. It is not infrequent that penetration tests highlight existing vulnerabilities that are &lt;strong&gt;currently being exploited&lt;/strong&gt; , and that may require a rapid response – you might need to shutdown a service while the vulnerability is being corrected. In this case make sure you know how to react and how to articulate and route this information within your company – this may involve the legal department as well as the communications department, particularly in the case of public companies.&lt;/p&gt;

&lt;h3&gt;
  
  
  During the pentest
&lt;/h3&gt;

&lt;p&gt;How the team responds to security alerts is a key element of an efficient and effective security response. Is the team trained to do so? Was a process ready for the person on call to respond to this? These processes don’t get triggered very often, so is the team aware of how to find and implement this process? Have all the security alerts sent by your security tools been handed over to the appropriate team? For instance, a vulnerability lying in the code should go to the developer team to fix, and a training session could be conducted to ensure all engineers are now aware of this specific security threat. Also, any new developer joining the team needs to be given this training as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  After the pentest
&lt;/h3&gt;

&lt;p&gt;Some of the vulnerabilities discovered during the penetration test will come from a failure to enforce some processes – or from a lack of process. The initial fix is always technical, such as changing a default password or upgrading a library. But the root cause of the issue often lies in a missing or incomplete process (or an imperfect automatization).&lt;/p&gt;

&lt;p&gt;This can be especially true when new technologies are at stake. The security specifics of a new database system, or a new cloud provider may remain fuzzy to your team, especially from a security point of view. In this case, training should be conducted so your team better understands these technical elements, and can ensure they are correctly configured. This also includes the need to improve the process of adding new technology to your infrastructure: engineers should be trained to reach a decent level of knowledge on the technology from a security point of view. A security review of any new family of elements can also be enforced.&lt;/p&gt;

&lt;h3&gt;
  
  
  tl;dr: actions for the organizational axis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;check you have procedures in place in case of a critical flaw discovery&lt;/li&gt;
&lt;li&gt;check that your processes have clear ownership defined&lt;/li&gt;
&lt;li&gt;test your processes to ensure that people know how to apply them&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The human learnings
&lt;/h2&gt;

&lt;p&gt;Pentests can tell you a lot about the individuals that you have on your team as well. Their reactions and responses can communicate a lot about their preparedness and mindset towards security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before the pentest: accepting the idea
&lt;/h3&gt;

&lt;p&gt;For many technical people, whose job it is to build and operate systems, knowing that a penetration test is being run on what they built can be seen as an offense to their skills and intelligence. It can also be understood as a lack of trust from whoever ordered the tests.&lt;/p&gt;

&lt;p&gt;Of course, this is a spontaneous reaction, driven by their ego, that may not last. The team will soon realize that a penetration test has two positive outcomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, it is an excellent opportunity to learn, since most security professionals will detail their reports in a pedagogical way. Learning is one of the most shared motivations amongst IT professionals.&lt;/li&gt;
&lt;li&gt;Second, it is an excellent opportunity to prioritize leftover tasks that generated security debt – which is a subset of technical debt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The takeaway here is that the way you present the pentest to your team matters. Do not hide behind a compliance excuse as the reason for the tests, but rather clearly leverage these positive points to have the team welcome the security tests.&lt;/p&gt;

&lt;p&gt;To ease the impact of the pentest on your team’s psyche, tell them in advance that a test is coming and promise that they will know the timeframe (e.g. 3-6 months out). Giving them a range rather than an exact date also creates an opportunity for them to get in the habit of thinking about security in their sprints, as well as improving or checking the alerting system for security issues. The team is often aware of security issues that have been long standing in the backlog, so communicating ahead gives them the chance to get around to fixing those issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  During the pentest: monitoring &amp;amp; reacting to attacks
&lt;/h3&gt;

&lt;p&gt;While the tests are ongoing, the team will be warned about the issues by your security alerting tools, if you have one in place (which you should). Critical issues will need immediate response (depending on your agreement with the security auditor) and will be handled by someone from the team.&lt;/p&gt;

&lt;p&gt;Pay extra attention to the human side of these security issues. They will have stronger psychological impact to your team than usual bugs do, since they are proven to have security impact, and will be highlighted in the security auditor’s report that may flow all the way through the company’s hierarchy. This may reveal tensions and finger-pointing across team members. It is the right time to remind everyone about the benevolent motto: everyone is doing his or her best. If mistakes are made, they need to be understood and the team should act accordingly to ensure they won’t happen again. The important thing is correcting the bugs, not assigning blame, so this whole process should be conducted blamelessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  After the pentest
&lt;/h3&gt;

&lt;p&gt;Once the security audit is over, the team needs to debrief about the results. What was detected during the tests needs to be consigned in a shared document and enriched by everyone. Getting a broad team involved will make the results stronger.&lt;/p&gt;

&lt;p&gt;Security successes (e.g. successfully detecting attacks, the parts of the system that the pentesters weren’t able to break, etc.) need to be highlighted and applauded, and failures (e.g. vulnerabilities detected and exploited, weaknesses discovered) have to be added to your bug tracking system, with a specific way to list them (with a tag such as “Q2 penetration test”). As with any other issues, these ones need to be prioritized. Most security consultants will rank their findings to help you prioritize what to fix, but they most often do not have the best understanding of your business. That means you need to go deeper with your team (and maybe the security consultants if an issue outcome is not perfectly clear) in order to properly rate and prioritize them.&lt;/p&gt;

&lt;p&gt;Each issue found (e.g. MongoDB injection in the Company controller) needs to be generalized, multiple times. For example, “if we have injections in this controller, we may have some in other controllers”. “If we have injections, maybe we are not that good at sanitizing inputs, let’s check user inputs”. And so on. This will directly leverage your team’s problem solving skills.&lt;/p&gt;

&lt;p&gt;Eventually, analyze your company’s reaction up and down the chain of command to the bad news that came up during the tests. Security is a sensitive topic that may put people in what they feel is a sensitive position, and have them react with more stress than usual. Good faith, honesty, and transparency are critical values for employees in order to have them proactively report security issues – rather than burying them.They have to be listened to and encouraged in order to bring these issues up. This means more than just stating values. People will read how everyone reacts during the pentest and internalize that.&lt;/p&gt;

&lt;p&gt;A typical reaction when security vulnerabilities are found goes like this: “this is indeed an XSS, but it isn’t exploitable because only the user can do it to himself.” This reaction is understandable: if the vulnerability cannot be exploited, why would we fix it?&lt;/p&gt;

&lt;p&gt;Let’s consider this vulnerability as a regular bug. What do you do with regular bugs? You fix the ones that are quick to fix, or can harm you, or can endanger your application. You also learn the lesson and make sure these kind of bugs do not occur again. Security bugs have to be considered the same way. If it occurred once, it may occur again, and if the part of the application where the vulnerability lies is later reused some place else, the bug will spread. In this case, its exploitability will have a different impact.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;is&lt;/em&gt; a regular bug, but one that has security consequences. That merits a different level of attention from your team.&lt;/p&gt;

&lt;h3&gt;
  
  
  tl;dr: actions for the human axis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Take the time to talk with your team about the pentest before it happens and present it to them the right way&lt;/li&gt;
&lt;li&gt;Pay attention to the psychological side of your team during the pentest. Ensure that everyone knows that whatever is uncovered has nothing to do with blame&lt;/li&gt;
&lt;li&gt;Take the time to debrief fully with your team, and prioritize and log the security issues found in a fair way&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Need some help?
&lt;/h2&gt;

&lt;p&gt;If you’re interested in learning more about maximizing your pentest, we put together a &lt;a href="https://www.sqreen.com/checklists/pentest-checklist" rel="noopener noreferrer"&gt;Pentest Best Practices Checklist&lt;/a&gt;. Check it out!&lt;/p&gt;

&lt;p&gt;Pentesting can give you an excellent point-in-time understanding of your security and show you the critical issues that you need to fix. Sqreen can help you solve these issues with real-time monitoring and protection, and actionable alerting. They work great together! &lt;a href="https://my.sqreen.io/signup" rel="noopener noreferrer"&gt;Try it free today&lt;/a&gt; or &lt;a href="http://sqreen.com/demo" rel="noopener noreferrer"&gt;sign up for a demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blog.sqreen.com/leverage-pentest/" rel="noopener noreferrer"&gt;How to fully leverage your pentest&lt;/a&gt; appeared first on &lt;a href="https://blog.sqreen.com" rel="noopener noreferrer"&gt;Sqreen Blog | Modern Application Security&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
      <category>bestpractices</category>
      <category>pentest</category>
    </item>
    <item>
      <title>The ultimate PHP security checklist</title>
      <dc:creator>Sqreen</dc:creator>
      <pubDate>Thu, 23 Aug 2018 11:25:04 +0000</pubDate>
      <link>https://dev.to/sqreenio/the-ultimate-php-security-checklist-5aae</link>
      <guid>https://dev.to/sqreenio/the-ultimate-php-security-checklist-5aae</guid>
      <description>&lt;p&gt;&lt;em&gt;Read the full checklist &lt;a href="https://www.sqreen.io/checklists/php-security-checklist"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Damn, but security is hard. It’s not always obvious what needs doing, and the payoffs of good security are at best obscure. Who is surprised when it falls off our priority lists?&lt;/p&gt;

&lt;p&gt;This security checklist aims to give developers a list of PHP security best practices they can follow to help improve the security of their code.&lt;/p&gt;

&lt;p&gt;Here is a selection of some of the security checklist items:&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter and Validate All Data
&lt;/h2&gt;

&lt;p&gt;Regardless of where the data comes from, whether that’s a configuration file, server environment, GET and POST, or anywhere else, do not trust it. Filter and validate it! Do this by using one of the available libraries, such as zend-inputfilter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://framework.zend.com/blog/2017-06-13-zend-validator.html"&gt;Validation in Zend Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://symfony.com/doc/current/validation.html"&gt;Validation in Symfony&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/5.6/validation"&gt;Validation in Laravel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use Parameterized Queries
&lt;/h2&gt;

&lt;p&gt;To avoid SQL injection attacks, never concatenate or interpolate SQL strings with external data. Use parameterized queries instead and prepared statements. These can be used with vendor-specific libraries or by using PDO.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://secure.php.net/manual/en/pdo.prepared-statements.php"&gt;Prepared statements and stored procedures in PDO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://secure.php.net/manual/de/mysqli.quickstart.prepared-statements.php"&gt;Mysqli Prepared Statements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://secure.php.net/manual/en/function.pg-query-params.php"&gt;The PostgreSQL pg_query_params function&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set open_basedir
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;open_basedir&lt;/code&gt; directive limits the files that PHP can access to the filesystem from the &lt;code&gt;open_basedir&lt;/code&gt; directory and downward. No files or directories outside of that directory can be accessed. That way, if malicious users attempt to access sensitive files, such as &lt;code&gt;/etc/passwd&lt;/code&gt;, access will be denied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://secure.php.net/manual/en/ini.core.php#ini.open-basedir"&gt;open_basedir configuration directive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://secure.php.net/manual/en/security.filesystem.php"&gt;PHP Filesystem Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/7-security-measures-to-protect-your-servers#isolated-execution-environments"&gt;Isolated Execution Environments by DigitalOcean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Check Your SSL / TLS Configurations
&lt;/h2&gt;

&lt;p&gt;Ensure that your server’s SSL/TLS configuration is up to date and correctly configured, and isn’t using weak ciphers, outdated versions of TLS, valid security certificates without weak keys, etc, by scanning it regularly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ssllabs.com/"&gt;SSL Labs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://observatory.mozilla.org/"&gt;Observatory by Mozilla&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Check out the full checklist &lt;a href="https://www.sqreen.io/checklists/php-security-checklist"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>An in-depth look at CVE-2018-8778 or why integer overflows are still a thing!</title>
      <dc:creator>Sqreen</dc:creator>
      <pubDate>Fri, 30 Mar 2018 02:16:27 +0000</pubDate>
      <link>https://dev.to/sqreenio/an-in-depth-look-at-cve-2018-8878-or-why-integer-overflows-are-still-a-thing-1n01</link>
      <guid>https://dev.to/sqreenio/an-in-depth-look-at-cve-2018-8878-or-why-integer-overflows-are-still-a-thing-1n01</guid>
      <description>&lt;p&gt;A new exciting vulnerability (yes sorry, we easily get excited about these things! 😜) has been released in Ruby. CVE-2018-8778 is a Buffer under-read that is triggered by &lt;code&gt;String#unpack&lt;/code&gt;. In this article, we will do a deep dive into the vulnerability, show how to exploit it and how to mitigate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s a buffer under-read?
&lt;/h2&gt;

&lt;p&gt;Nearly all meaningful computing we do is done on data structures (object) that are stored in memory.&lt;/p&gt;

&lt;p&gt;Each object has a defined size and a layout of fields in memory. So someone looking at the memory can see our object flattened as binary data of a given length (zeros &amp;amp; ones). This is what we call a buffer (a zone of memory). As a developer, when operating on our object, we should work within a given buffer and shouldn’t read/write before/after our object.&lt;/p&gt;

&lt;p&gt;Ruby allocates data on what is called the heap. That’s a memory space (another one is the stack). Nearly every Ruby object will land there.&lt;/p&gt;

&lt;p&gt;So a buffer under-read is a vulnerability that allows attackers to access memory locations before the targeted buffer. This typically occurs when the pointer or its index is decremented to a position before the buffer.&lt;/p&gt;

&lt;p&gt;It is a critical vulnerability, but the severity really depends on the data that your application handles. It may result in the exposure of sensitive information or possibly a crash. You could potentially read data like tokens, database credentials, session cookies or even a transiting credit card number.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what the heck is CVE-2018-8778?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.ruby-lang.org/en/news/2018/03/28/buffer-under-read-unpack-cve-2018-8778/" rel="noopener noreferrer"&gt;Here is the announcement of the vulnerability&lt;/a&gt;. To better understand it let’s first dig into the Ruby source code of the fixing commit &lt;a href="https://github.com/ruby/ruby/commit/d02b7bd864706fc2a40d83fb6014772ad3cc3b80" rel="noopener noreferrer"&gt;here&lt;/a&gt; (yeah OK it’s an SVN revision, Ruby history predates Git!).&lt;/p&gt;

&lt;p&gt;The vulnerability is located inside the &lt;code&gt;String#unpack&lt;/code&gt; method. This method decodes &lt;code&gt;str&lt;/code&gt; according to the provided string format, returning an array of each value extracted (You can read more about it on &lt;a href="https://ruby-doc.org/core-2.5.0/String.html#method-i-unpack" rel="noopener noreferrer"&gt;RubyDoc&lt;/a&gt;). The format string consists of a sequence of single-character directives (numbers, “*”, “_” or “!”) and can specify the position of the data being parsed by the specifier &lt;code&gt;@&lt;/code&gt;. That’s where the issue lies.&lt;/p&gt;

&lt;p&gt;From the &lt;a href="https://github.com/ruby/ruby/commit/d02b7bd864706fc2a40d83fb6014772ad3cc3b80#diff-66ede7a20d01949feaa42bf3f6ba2a5aR555" rel="noopener noreferrer"&gt;non-regression test&lt;/a&gt;, we can see that one just need to use a specific format to trigger this. This format string actually is like a mini program. The string “@42C10” decodes as: skip 42 bytes then decode 10 8-bit integers.&lt;/p&gt;

&lt;p&gt;The issue here is that the offset is poorly validated. If a significant number is passed with &lt;code&gt;@&lt;/code&gt;, the number is treated as a negative value, and &lt;code&gt;unpack&lt;/code&gt; skips a negative amount of bytes. This is where the out-of-buffer read occurs. So an attacker could use this to read sensitive data on the heap.&lt;/p&gt;

&lt;p&gt;The poorly validated offset is a classic mistake called &lt;a href="https://en.wikipedia.org/wiki/Integer_overflow" rel="noopener noreferrer"&gt;integer overflow&lt;/a&gt;. When using signed integers, trying to decode what would be a huge unsigned integer value, the decoded value will be a negative number. Here it gives us a way to have negative offsets. On a related note, the first Ariane 5 crash was triggered by this… &lt;a href="https://hownot2code.com/2016/09/02/a-space-error-370-million-for-an-integer-overflow/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does this integer overflow happen here?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;String#unpack&lt;/code&gt; is actually defined in Ruby core source code in the C programming language. As we can see in the &lt;a href="https://github.com/ruby/ruby/commit/d02b7bd864706fc2a40d83fb6014772ad3cc3b80#diff-1d0f88fabe331fcc38c1adce12c697b0L1130" rel="noopener noreferrer"&gt;remediation commit&lt;/a&gt; the offset that is expressed as a string (a &lt;code&gt;char *&lt;/code&gt; in C) has to be translated to an integer value. For this, Ruby uses a macro called &lt;code&gt;STRTOUL&lt;/code&gt; which in turn calls &lt;code&gt;ruby_strtoul&lt;/code&gt; (they are defined in &lt;a href="https://github.com/ruby/ruby/blob/46b391ff731d66883082e6347d5fc4e54386d7bd/include/ruby/ruby.h#L2189" rel="noopener noreferrer"&gt;ruby.h&lt;/a&gt;). As the name seems to prefigure this will output an unsigned long integer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unsigned long ruby_strtoul(const char *str, char **endptr, int base);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Until here, no issue, the string &lt;code&gt;“18446744073709551416”&lt;/code&gt; is correctly decoded to the long integer &lt;code&gt;18446744073709551416&lt;/code&gt;. Yet this value is stored in &lt;code&gt;len&lt;/code&gt; which is &lt;a href="https://github.com/ruby/ruby/blob/46b391ff731d66883082e6347d5fc4e54386d7bd/pack.c#L267" rel="noopener noreferrer"&gt;declared&lt;/a&gt; as a &lt;code&gt;long&lt;/code&gt;, a signed number. Doing this casts the unsigned number to signed number and &lt;code&gt;18446744073709551416&lt;/code&gt; becomes &lt;code&gt;-200&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here are the offending pieces together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;unsigned&lt;/span&gt; &lt;span class="n"&gt;long&lt;/span&gt; &lt;span class="n"&gt;ruby_strtoul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;endptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;#define STRTOUL(str, endptr, base) (ruby_strtoul((str), (endptr), (base)))&lt;/span&gt;
&lt;span class="sr"&gt;//&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;static&lt;/span&gt; &lt;span class="no"&gt;VALUE&lt;/span&gt;
&lt;span class="n"&gt;pack_pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;VALUE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="sr"&gt;//&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;long&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="sr"&gt;//&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

    &lt;span class="nf"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ISDIGIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;errno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;STRTOUL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;rb_raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rb_eRangeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"pack length too big"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How do you exploit this vulnerability?
&lt;/h2&gt;

&lt;p&gt;The first step in exploiting the vulnerability in a live application is having a small Proof of Concept (PoC). Let’s first try to read memory from the &lt;code&gt;irb&lt;/code&gt; interactive shell. We will use the nice &lt;a href="https://github.com/postmodern/hexdump" rel="noopener noreferrer"&gt;hexdump gem&lt;/a&gt; to display something easier to read for us humans. Without further ado here is a one-liner that will do this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i2.wp.com/blog.sqreen.io/wp-content/uploads/2018/03/Heap-Space-1.png?ssl=1" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi2.wp.com%2Fblog.sqreen.io%2Fwp-content%2Fuploads%2F2018%2F03%2FHeap-Space-1.png%3Fresize%3D300%252C289%26ssl%3D1" alt="Heap Space - Integer Overflow"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;irb

irb&lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt;:145:0&amp;gt; leak &lt;span class="o"&gt;=&lt;/span&gt; 200&lt;span class="p"&gt;;&lt;/span&gt; size &lt;span class="o"&gt;=&lt;/span&gt; 2&lt;span class="k"&gt;**&lt;/span&gt;64-1 - leak + 1 &lt;span class="p"&gt;;&lt;/span&gt; puts size &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="s2"&gt;"BUFF"&lt;/span&gt;.unpack&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"@#{size}C#{leak+4}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;.map &lt;span class="o"&gt;{&lt;/span&gt; |i| i&amp;amp;.chr &lt;span class="o"&gt;}&lt;/span&gt;.join.hexdump
18446744073709551416

Offset    Hex dump                                          ASCII dump
&lt;span class="nt"&gt;--------&lt;/span&gt;  &lt;span class="nt"&gt;-----------------------------------------------&lt;/span&gt;  &lt;span class="nt"&gt;------------------&lt;/span&gt;
00000000  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00 65 08 93 20 00 00 00 00  |........e.. ....|
00000020  c0 7d 8c 50 97 7f 00 00 53 41 56 45 5f 48 49 53  |.&lt;span class="o"&gt;}&lt;/span&gt;.P....SAVE_HIS|
00000030  54 4f 52 59 00 00 00 00 00 00 00 00 00 00 00 00  |TORY............|
00000040  65 40 90 00 00 00 00 00 c0 7d 8c 50 97 7f 00 00  |e@.......&lt;span class="o"&gt;}&lt;/span&gt;.P....|
00000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00 65 40 90 00 00 00 00 00  |........e@......|
00000070  c0 7d 8c 50 97 7f 00 00 00 00 00 00 00 00 00 00  |.&lt;span class="o"&gt;}&lt;/span&gt;.P............|
00000080  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000090  65 40 90 00 00 00 00 00 c0 7d 8c 50 97 7f 00 00  |e@.......&lt;span class="o"&gt;}&lt;/span&gt;.P....|
000000a0  7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000000b0  00 00 00 00 00 00 00 00 65 08 51 20 00 00 00 00  |........e.Q ....|
000000c0  c0 7d 8c 50 97 7f 00 00 42 55 46 46              |.&lt;span class="o"&gt;}&lt;/span&gt;.P....BUFF|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what are we doing here? We have a parameter for the size of the leak (&lt;code&gt;leak&lt;/code&gt;), and we calculate the huge number that will then be decoded as a negative integer. We then create a small buffer and unpack it using a format string using these two values. We’re essentially saying: skip to this huge offset (which ends up a &lt;code&gt;-leak&lt;/code&gt; bytes) and reads &lt;code&gt;leak + 4&lt;/code&gt; bytes.&lt;/p&gt;

&lt;p&gt;This returns 204 bytes as requested.&lt;br&gt;&lt;br&gt;
By passing a large integer as offset, we have gone back 200 bytes before the start of BUFF in memory and then read 204 bytes (the generated format string used: &lt;code&gt;@18446744073709551416C204&lt;/code&gt; ).&lt;/p&gt;

&lt;p&gt;As a sanity check, we can correctly see the content of the buffer we should be working in at the end of the ASCII dump part (BUFF). If Ruby was not vulnerable, it should never have jumped to read memory before the start of BUFF.&lt;/p&gt;

&lt;p&gt;How do we go from the PoC to actual exploitation? We would first need to find an application running on a vulnerable Ruby (pre 2.5.1) application that we can attack. A Ruby on Rails application would be nice, as we could attack it remotely and often contains juicy secrets. This Rails application would need to have a &lt;code&gt;String#unpack&lt;/code&gt; call were the &lt;code&gt;format&lt;/code&gt; parameter is under attacker control. &lt;code&gt;String#unpack&lt;/code&gt; calls are more common than you might think. They are often used to decode data coming from elsewhere (i.e. database drivers are often users of this). So to know if you are affected you might also want to take a look at all your dependencies source code…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i0.wp.com/blog.sqreen.io/wp-content/uploads/2018/03/Heap-Space-2.png?ssl=1" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fblog.sqreen.io%2Fwp-content%2Fuploads%2F2018%2F03%2FHeap-Space-2.png%3Fresize%3D300%252C288%26ssl%3D1" alt="Heap Space - Integer Overflow example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we had such an application, simply sending our generated malicious format string from above enables us to extract as much data as we want from the application. This allows us to read &amp;amp; possibly extract all the secrets that are stored in memory (database credentials, tokens) and maybe also data that would only be transiting through the application (customer credit card number or user session on a concurrent request).&lt;/p&gt;
&lt;h2&gt;
  
  
  Building a remediation
&lt;/h2&gt;

&lt;p&gt;The easiest fix is, of course, to simply update Ruby on your machine. In the real world, this is unfortunately not always quickly doable. This reality pushed us to craft a solution that would protect all &lt;a href="https://www.sqreen.io/?utm_medium=social&amp;amp;utm_source=blog&amp;amp;utm_campaign=Blog%20-%20CVE-2018-8878" rel="noopener noreferrer"&gt;Sqreen&lt;/a&gt; users from CVE-2018-8778 even if they couldn’t update their Ruby version just yet.&lt;/p&gt;

&lt;p&gt;Two primary requirements drive the development of new protections at Sqreen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we can’t break our users’ application with false positives.&lt;/li&gt;
&lt;li&gt;Second, the impact on performance should be nearly invisible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After looking at a few options, we decided that the best solution is to “simply” hook the &lt;code&gt;String#unpack&lt;/code&gt; method and check that the argument containing &lt;code&gt;@&lt;/code&gt; doesn’t include a large offset in the format string. The key here is to make sure this format string is not coming from the current request parameters.&lt;/p&gt;

&lt;p&gt;So the rule we implemented looks a bit like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TWO_GIGABYTES= 2**31
return false unless format_string.include?('@')
return false unless user_parameters.include?(format_string)
offset = parse(format_string)
return offset &amp;gt; TWO_GIGABYTES
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s look at an example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a format string &lt;code&gt;C10&lt;/code&gt; stops processing at the first line ⇒ no attack detected&lt;/li&gt;
&lt;li&gt;a format string &lt;code&gt;@10c12&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;that is not in user parameters stops at the second line ⇒ no attack detected&lt;/li&gt;
&lt;li&gt;If it comes from user parameters (the code would probably be vulnerable), we check the offset size 10 and stop processing ⇒ no attack detected&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;With &lt;code&gt;@18446744073709551416C204&lt;/code&gt; as a format string, the offset &lt;code&gt;18446744073709551416&lt;/code&gt; is bigger than 2**31 ⇒ an attack is detected!&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;And that’s it. After extensive tests, we deployed this rule to our users. They are now all protected against this buffer under-read vulnerability and can update their Ruby version when the time is right. All of this was achieved in less than 21 hours between the disclosure of the vulnerability and the full protection of our clients.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blog.sqreen.io/buffer-under-read-ruby/" rel="noopener noreferrer"&gt;An in depth look at CVE-2018-8878 or why integer overflows are still a thing!&lt;/a&gt; appeared first on &lt;a href="https://blog.sqreen.io" rel="noopener noreferrer"&gt;Sqreen Blog | Modern Application Security&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>security</category>
    </item>
    <item>
      <title>Context information storage for asyncio</title>
      <dc:creator>Sqreen</dc:creator>
      <pubDate>Mon, 26 Feb 2018 23:35:21 +0000</pubDate>
      <link>https://dev.to/sqreenio/context-information-storage-for-asyncio-5303</link>
      <guid>https://dev.to/sqreenio/context-information-storage-for-asyncio-5303</guid>
      <description>&lt;p&gt;At &lt;a href="https://www.sqreen.io/"&gt;Sqreen&lt;/a&gt;, we are building an agent based on dynamic instrumentation. It detects security incidents from inside an application (injections, cross-site scripting etc.) and allows users to configure actions (blocking the attack, logging a stack trace etc.) without requiring code modification. The mechanisms behind dynamic instrumentation in Python are described in &lt;a href="https://blog.sqreen.io/dynamic-instrumentation-agent-for-python/"&gt;a previous blog post&lt;/a&gt;. Dynamic instrumentation is also used in Application Performance Management (APM) solutions, such as &lt;a href="https://www.datadoghq.com/"&gt;Datadog&lt;/a&gt;, &lt;a href="https://www.instana.com/"&gt;Instana&lt;/a&gt; and &lt;a href="https://newrelic.com/"&gt;New Relic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instrumenting the code allows us to execute callbacks before calling potentially hazardous functions. For example, to &lt;a href="https://blog.sqreen.io/block-sql-injections-not-customers/"&gt;protect against SQL injections&lt;/a&gt;, we transparently wrap the method Cursor.execute with a security layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sqreen_execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sql_stmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Before executing the SQL statement, check it was not built with
&lt;/span&gt;    &lt;span class="c1"&gt;# malicious, unescaped request parameters in it.
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;has_malicious_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql_stmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# If there is, this is an SQL injection. Abort!
&lt;/span&gt;        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;SQLinjection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remote_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remote_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# If not, we can safely call the original method.
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql_stmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s assume the instrumented code contains a vulnerable pattern like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/posts'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;sql_stmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'SELECT * FROM posts WHERE id=%s'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# With dynamic instrumentation, sqreen_execute is transparently called
&lt;/span&gt;    &lt;span class="c1"&gt;# instead of cursor.execute.
&lt;/span&gt;    &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql_stmt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;posts_template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the nominal request /posts/?id=42 will be executed (although unescaped, the request parameter is not malicious) but the malicious request /posts/?id=42 OR 1=1 won’t be. This way, we are able to protect the app without breaking it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Context information storage
&lt;/h2&gt;

&lt;p&gt;As we’ve seen above, the function sqreen_execute needs to know the current request to test the SQL statement safety. How can it get it?&lt;/p&gt;

&lt;p&gt;Since our function transparently replaces Cursor.execute, it needs to have the same signature, hence we can’t pass the request as a parameter to sqreen_execute. Some web frameworks provide functions to get the current requests, but not all of them, and we strive for a universal solution.&lt;/p&gt;

&lt;p&gt;What we can do is to insert a middleware (or instrument the framework’s request handling mechanism) to store the current request in a global variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;CURRENT_REQUEST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;CURRENT_REQUEST&lt;/span&gt;
    &lt;span class="n"&gt;current_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CURRENT_REQUEST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is a catch: web frameworks are able to handle several requests concurrently, for obvious performance reasons. So the above pattern won’t work: we may receive a first request request_1 (and store it in CURRENT_REQUEST), and before serving it receive a second request request_2 (overriding request_1 in CURRENT_REQUEST). At the time we look for SQL injections in request_1, we will mess it up with request_2! So we need a stronger, concurrent-safe mechanism to store the current request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thread-local storage
&lt;/h3&gt;

&lt;p&gt;To tackle this issue, we need to know how concurrency is implemented. Most of Python web frameworks use threads: this is notably the case of &lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt;, &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; and &lt;a href="https://trypyramid.com/"&gt;Pyramid&lt;/a&gt;, which are probably the most popular. They implement a common communication protocol with web servers, called WSGI (Web Server Gateway Interface) and initially described in &lt;a href="https://www.python.org/dev/peps/pep-0333/"&gt;PEP 333&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;WSGI servers also use threads, along with processes, to spawn several application instances. Multiprocessing is not an issue here, since each process will handle its own copy of CURRENT_REQUEST. So, we just have to find a solution to let a service thread to store the request it is currently dealing with without impacting other threads.&lt;/p&gt;

&lt;p&gt;And Python offers a solution for that. The function threading.local &lt;a href="https://docs.python.org/3/library/threading.html#threading.local"&gt;in the standard library&lt;/a&gt; return a namespace object whose values are thread specific. This allows us to implement thread-safe request storage as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;threading&lt;/span&gt;

&lt;span class="n"&gt;RUNTIME_STORAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;RUNTIME_STORAGE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;RUNTIME_STORAGE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;RUNTIME_STORAGE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What about asyncio?
&lt;/h3&gt;

&lt;p&gt;In Python 3.4, a new concurrency model was introduced: &lt;a href="https://docs.python.org/3/library/asyncio.html"&gt;asyncio&lt;/a&gt;. It provides infrastructure for single-threaded, asynchronous programming, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Coroutine functions, defined with async def, whose execution can be paused using the await keyword with another coroutine, and resumed once the other coroutine is completed.&lt;/li&gt;
&lt;li&gt;An event loop to schedule and execute coroutines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is an example of asynchronous code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Compute %s + %s ..."&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s + %s = %s"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;print_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two coroutine functions, print_sum and compute. At execution time&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The event loop enters print_sum and immediately hands over to compute.&lt;/li&gt;
&lt;li&gt;compute prints the computation and hands over to asyncio.sleep.&lt;/li&gt;
&lt;li&gt;Nothing is done in the next second. If other tasks were scheduled in the event loop, they could be executed in the meantime, something that is not possible with the blocking function time.sleep.&lt;/li&gt;
&lt;li&gt;compute is resumed and completed.&lt;/li&gt;
&lt;li&gt;print_sum is resumed and completed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;asyncio is a great model for concurrency when IO is involved: when the code being executed is blocked waiting for an answer (for example, DB results), the program can switch to other tasks and come back to it later. It is less system-expensive than threads, and is usually faster when slow IO operations are involved.&lt;/p&gt;

&lt;p&gt;This makes asyncio well suited for network operations and, despite being relatively young, &lt;a href="https://github.com/timofurrer/awesome-asyncio#web-frameworks"&gt;several web frameworks&lt;/a&gt; have been developed around it. Among them, we recently brought support for &lt;a href="https://aiohttp.readthedocs.io/"&gt;aiohttp&lt;/a&gt; in our agent. This was a very interesting and challenging task since we had no support for aiohttp at all so far, and an important issue we met was with the request storage mechanism.&lt;/p&gt;

&lt;p&gt;Here is what can happen: we receive a first request request_1 and start dealing with it in a coroutine. At some point, the coroutine is suspended and the event loop hands over to another one that handles request_2. The important point is that these two coroutines are executed in the &lt;em&gt;same thread&lt;/em&gt;, so threading.local contains the same data for both. When the first coroutine resumes, RUNTIME_STORAGE.request has been set to request_2: that is precisely what we want to prevent.&lt;/p&gt;

&lt;h2&gt;
  
  
  First attempt: let’s use tasks!
&lt;/h2&gt;

&lt;p&gt;What we need is a mechanism similar to threading.local that works with asyncio, i.e. lets us store context variables and keep track of values per asynchronous execution context.&lt;/p&gt;

&lt;p&gt;Unfortunately, there is currently no built-in mechanism in Python to handle this. Different proposals have been made to provide a generic solution in future versions of Python (&lt;a href="https://www.python.org/dev/peps/pep-0550/"&gt;PEP 550&lt;/a&gt;, &lt;a href="https://www.python.org/dev/peps/pep-0567/"&gt;PEP 567&lt;/a&gt;), but in the meantime, we have to devise a solution on our own.&lt;/p&gt;

&lt;p&gt;Let’s dig a bit further into the internals of asyncio. A coroutine whose execution is scheduled is wrapped into an asyncio.Task &lt;a href="https://docs.python.org/3/library/asyncio-task.html#task"&gt;object&lt;/a&gt;, responsible for executing the coroutine object in an event loop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pAwvGajS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/blog.sqreen.io/wp-content/uploads/2018/02/https-docs-python-org-3-_images-tulip_coro-png.png%3Fw%3D840%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pAwvGajS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/blog.sqreen.io/wp-content/uploads/2018/02/https-docs-python-org-3-_images-tulip_coro-png.png%3Fw%3D840%26ssl%3D1" alt="https://docs.python.org/3/_images/tulip_coro.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sequence diagram of the example&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is also a function asyncio.Task.current_task that returns the currently running task. Mmh… We could use this to map the current request to the task handling it. Something like this could work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;

&lt;span class="n"&gt;TASK_REQUESTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;TASK_REQUESTS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;TASK_REQUESTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this implementation, we’d also need a mechanism to ensure request deletion once the task is completed, to avoid accumulating old requests and cause a memory leak. A way to avoid dealing with it is to store the request &lt;em&gt;within&lt;/em&gt; the Task object, as an extra attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
     &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
     &lt;span class="nb"&gt;setattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
     &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, does it work? Let’s test!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Dummy request object, for the sake of testing.
&lt;/span&gt;    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Check that the stored request corresponds to the current request. If not,
&lt;/span&gt;    &lt;span class="c1"&gt;# an AssertionError is raised and the test is interrupted with an error.
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"wrong request"&lt;/span&gt;

&lt;span class="n"&gt;NUM_REQUESTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;coros&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NUM_REQUESTS&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;coros&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Success!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test simulates one thousand concurrent requests. Each one is handled in a dedicated coroutine handle_request. This function stores the request, then pauses for a random duration (this simulates an async operation such as a DB access, and ensures that the coroutine execution flow is interleaved). When resumed, a nested coroutine check_request is called that ensures that get_request returns the correct request. If not, the test is interrupted by an error.&lt;/p&gt;

&lt;p&gt;And here are some good news: the test runs smoothly with task-based request storage. It also fails with thread-local storage, which was expected but shows the test is relevant. So, have we solved our problem?&lt;/p&gt;

&lt;h2&gt;
  
  
  Context inheritance between tasks
&lt;/h2&gt;

&lt;p&gt;Let’s try something a bit more twisted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="n"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of executing asyncio.sleep and check_request sequentially, this version of handle_request runs them concurrently. This should not be a big deal: the code is a bit more concurrent, but it does not impact request handling. In particular, check_request is still called &lt;em&gt;after&lt;/em&gt; set_request for each request.&lt;/p&gt;

&lt;p&gt;Nevertheless, this new test fails! Something went wrong when we introduced asyncio.gather, but what?&lt;/p&gt;

&lt;p&gt;Well, remember that scheduled coroutines are wrapped into tasks? That’s exactly what happens here: asyncio.gather creates tasks around the arguments asyncio.sleep() and check_request() and these tasks are executed by the event loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                              &lt;span class="c1"&gt;# Running in task 1.
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;          &lt;span class="c1"&gt;# Create child task 2.
&lt;/span&gt;        &lt;span class="n"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;                       &lt;span class="c1"&gt;# Create child task 3.
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"wrong request"&lt;/span&gt;  &lt;span class="c1"&gt;# Running in task 3.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The consequence is that set_request and get_request are called in different tasks, making the test fail. This is not due to request interleaving, as we can check by setting NUM_REQUESTS to 1: the test keeps failing.&lt;/p&gt;

&lt;p&gt;In fact, when calling get_request from a child task, we need a mechanism to retrieve the request from the parent task if it is not defined in the child task. But asyncio does not allow us to access the parent task, so this is not going to work.&lt;/p&gt;

&lt;p&gt;On the other hand, something asyncio let us do is to replace the function called to create new tasks, a.k.a. the &lt;em&gt;task factory&lt;/em&gt;. This function is called in the context of the parent task, and returns a fresh child task. Well, let’s use it to decorate the child task with the current request!&lt;/p&gt;

&lt;p&gt;Here is what a “request-aware” task factory would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;request_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# This is the default way to create a child task.
&lt;/span&gt;    &lt;span class="n"&gt;child_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Retrieve the request from the parent task...
&lt;/span&gt;    &lt;span class="n"&gt;parent_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;current_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ...and store it in the child task too.
&lt;/span&gt;    &lt;span class="nb"&gt;setattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;child_task&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install the task factory, we also need to call loop.set_task_factory(request_task_factory) before running the loop. So, here is the final version of our code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;setattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;request_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;child_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parent_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;current_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;setattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;child_task&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;set_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="n"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;get_request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;NUM_REQUESTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request_task_factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;coros&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NUM_REQUESTS&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;coros&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it works flawlessly!&lt;/p&gt;

&lt;h2&gt;
  
  
  And now what?
&lt;/h2&gt;

&lt;p&gt;We now have the foundations to solve the request storage issue in our agent. Since we want the agent to work as transparently as possible and not require code modification from the user, there are still two minor issues to be tackled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We want to automatically set up the task factory. This will be done with dynamic instrumentation.&lt;/li&gt;
&lt;li&gt;But if a custom task is set up by the user, we don’t want to overwrite it. Instead, we will wrap it up on our own.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s start with the second problem. We can define a generic function wrap_request_task_factory that takes a task factory as argument and returns a variant of it that supports request propagation. The code of the wrapped function is really close to the one of request_task_factory above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;wraps&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrap_request_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_factory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;wraps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;child_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;parent_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;current_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;setattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;child_task&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the definition of request_task_factory can be simplified to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;wrap_request_task_factory&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;request_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time to go back to dynamic instrumentation. By hooking the import system, we can transparently replace an imported class by a custom one. So let’s define a function patch_loop_cls that creates a custom loop class with the desired behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrap_loop_cls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop_cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SqreenLoop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop_cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# We want to use request_task_factory to be the default task
&lt;/span&gt;            &lt;span class="c1"&gt;# factory.
&lt;/span&gt;            &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;set_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request_task_factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_factory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# If the user sets up a custom task factory, let's wrap it with
&lt;/span&gt;            &lt;span class="c1"&gt;# request propagation.
&lt;/span&gt;            &lt;span class="n"&gt;wrapped_task_factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wrap_request_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;set_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wrapped_task_factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SqreenLoop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This loop class transparently replaces the base one. It uses the correct task factory by default and allows the user to change it while keeping the request management layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing words
&lt;/h2&gt;

&lt;p&gt;We have published most of this work (without the instrumentation part) in a Python library called &lt;a href="https://github.com/sqreen/AioContext"&gt;AioContext&lt;/a&gt;. It comes with generic Context objects that behave like dictionaries. It also allows to restore the original task factory if contexts are no longer needed, and stores contexts as an extra attribute of the task factory to avoid messing with the asyncio.Task class itself. The documentation is available &lt;a href="https://aiocontext.readthedocs.io/"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;aiocontext&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;CONTEXT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aiocontext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;CONTEXT&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="n"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;CONTEXT&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'current_request'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;NUM_REQUESTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;aiocontext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wrap_task_factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;CONTEXT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;coros&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NUM_REQUESTS&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;coros&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This work was strongly inspired by Manual Miranda’s blog post &lt;a href="https://medium.com/@SkyscannerEng/from-flask-to-aiohttp-22f1ddc5dd5e"&gt;From Flask to aiohttp&lt;/a&gt; and the library &lt;a href="https://github.com/Skyscanner/aiotask-context"&gt;aiotask-context&lt;/a&gt;. We want to thank him for the great contribution.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blog.sqreen.io/asyncio/"&gt;Context information storage for asyncio&lt;/a&gt; appeared first on &lt;a href="https://blog.sqreen.io"&gt;Sqreen Blog | Modern Application Security&lt;/a&gt; and was written by Vivien Maisonneuve.&lt;/p&gt;

</description>
      <category>dev</category>
      <category>python</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
