<?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: Tristan Kalos</title>
    <description>The latest articles on DEV Community by Tristan Kalos (@tristankalos).</description>
    <link>https://dev.to/tristankalos</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%2Fuser%2Fprofile_image%2F831088%2F4b297e96-a4f4-444a-8c62-ef9ae5d868b0.jpg</url>
      <title>DEV Community: Tristan Kalos</title>
      <link>https://dev.to/tristankalos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tristankalos"/>
    <language>en</language>
    <item>
      <title>Express.js Security Best Practices</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Wed, 22 Nov 2023 10:55:17 +0000</pubDate>
      <link>https://dev.to/tristankalos/expressjs-security-best-practices-1ja0</link>
      <guid>https://dev.to/tristankalos/expressjs-security-best-practices-1ja0</guid>
      <description>&lt;p&gt;Express.js is a fast, unopinionated, minimalist web framework for Node.js. It's widely used to build web applications, and as such, ensuring that applications built with Express.js are secure is paramount. Here, we’ll walk through ten best practices to help you strengthen the security of your Express.js applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Use Helmet
&lt;/h2&gt;

&lt;p&gt;Helmet helps secure your Express apps by setting various HTTP headers. It's not a silver bullet, but it can help protect against some well-known web vulnerabilities by setting headers like &lt;code&gt;X-Content-Type-Options&lt;/code&gt;, &lt;code&gt;X-DNS-Prefetch-Control&lt;/code&gt;, and others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;helmet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;helmet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;helmet&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Keep Dependencies Updated
&lt;/h2&gt;

&lt;p&gt;Vulnerabilities in software are discovered regularly. Using outdated packages can leave you susceptible to these issues. Use tools like &lt;code&gt;npm audit&lt;/code&gt; or &lt;code&gt;Snyk&lt;/code&gt; to identify and update vulnerable dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm audit fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Implement Rate Limiting
&lt;/h2&gt;

&lt;p&gt;Rate limiting helps to prevent brute-force attacks by limiting the number of requests users can make within a certain timeframe. For Express.js, you can use the &lt;code&gt;express-rate-limit&lt;/code&gt; middleware.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rateLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express-rate-limit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rateLimit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;windowMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Sanitize Input
&lt;/h2&gt;

&lt;p&gt;Input sanitization helps prevent injection attacks. It's important to never trust user input and always to sanitize and validate it before processing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validationResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express-validator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isAlphanumeric&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isEmail&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&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;span class="c1"&gt;// Proceed with handling request&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Use HTTPS
&lt;/h2&gt;

&lt;p&gt;HTTP traffic is unencrypted, making it susceptible to interception and alteration. Use HTTPS to encrypt data in transit. With Express.js, you can use Node's &lt;code&gt;https&lt;/code&gt; module in conjunction with fs to read SSL/TLS certificates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key.pem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cert.pem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Handle Errors Properly
&lt;/h2&gt;

&lt;p&gt;Express.js has default error handling, but it's recommended to implement a custom error handling middleware to catch and properly manage errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Something broke!&lt;/span&gt;&lt;span class="dl"&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;
  
  
  7. Use Cookies Securely
&lt;/h2&gt;

&lt;p&gt;If you’re using cookies for session management, use secure + httpOnly flags to prevent client-side scripts from accessing the cookie.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express-session&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;session&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-secret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// other configuration&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Avoid Revealing Stack Traces
&lt;/h2&gt;

&lt;p&gt;Express.js, by default, will expose a stack trace to the client on an error. Turn off stack traces in production to avoid revealing too much.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Server Error&lt;/span&gt;&lt;span class="dl"&gt;'&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;
  
  
  9. Secure File Uploads
&lt;/h2&gt;

&lt;p&gt;If your application deals with file uploads, ensure you check the file type, limit the size, and scan for malware.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;multer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uploads/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fileSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;fileFilter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.(&lt;/span&gt;&lt;span class="sr"&gt;jpg|jpeg|png|gif&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Only image files are allowed!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&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;
  
  
  10. Authenticate &amp;amp; Authorize
&lt;/h2&gt;

&lt;p&gt;Always implement strong authentication and authorization checks. Tools like Passport.js can help you manage these securely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passport&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LocalStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passport-local&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LocalStrategy&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Implement your verification logic&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you follow these best practices, you're not only protecting your application but also safeguarding users' data and trust in your application. Remember, security is an ongoing effort and &lt;strong&gt;requires regular code reviews, monitoring, and updates&lt;/strong&gt; to stay ahead of potential threats 😉&lt;/p&gt;

</description>
      <category>express</category>
      <category>javascript</category>
      <category>node</category>
      <category>security</category>
    </item>
    <item>
      <title>Introducing APIrank.dev algorithm update - a better benchmark of 7000+ Public APIs on the internet</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Sat, 15 Apr 2023 20:38:42 +0000</pubDate>
      <link>https://dev.to/tristankalos/introducing-apirankdev-algorithm-update-a-better-benchmark-of-7000-public-apis-on-the-internet-3ij6</link>
      <guid>https://dev.to/tristankalos/introducing-apirankdev-algorithm-update-a-better-benchmark-of-7000-public-apis-on-the-internet-3ij6</guid>
      <description>&lt;p&gt;tl;dr we (Escape) have updated our ranking of 7000+ public APIs according to security, performance, reliability, and design criteria. The results are public on &lt;a href="https://apirank.dev"&gt;APIrank.dev&lt;/a&gt;. You can also request to index your own API for free and see how it compares to others.&lt;/p&gt;

&lt;p&gt;APIrank is a powerful tool that ranks over 7000 public APIs based on security, performance, reliability, and design criteria. And now, with our latest update, we've made it even better. We've improved the weights of the ranking parameters and added additional data sources, like domain reputation, for more accurate results.&lt;/p&gt;

&lt;p&gt;By using APIrank, developers can easily find and pick the right external APIs for their projects. Our platform provides in-depth insights about the security, reliability, performance, and ease of use of the APIs, so you can make informed decisions and avoid any potential headaches down the road.&lt;/p&gt;

&lt;p&gt;And the best part? You can index your own API for free and see how it stacks up against the competition.&lt;/p&gt;

&lt;p&gt;Ready to get started? Head over to &lt;a href="https://apirank.dev"&gt;APIrank.dev&lt;/a&gt; to learn more and try it out for yourself. And if you need any help along the way, be sure to check out our blog for more information and resources. Happy coding! 🤖&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>security</category>
      <category>performance</category>
    </item>
    <item>
      <title>Getting started with Postman for GraphQL</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Fri, 07 Apr 2023 20:21:39 +0000</pubDate>
      <link>https://dev.to/tristankalos/getting-started-with-postman-for-graphql-3gkc</link>
      <guid>https://dev.to/tristankalos/getting-started-with-postman-for-graphql-3gkc</guid>
      <description>&lt;p&gt;This is an article by &lt;a class="mentioned-user" href="https://dev.to/nohehf"&gt;@nohehf&lt;/a&gt; that also have been published on our blog: &lt;a href="https://escape.tech/blog/getting-started-with-postman-graphql/"&gt;https://escape.tech/blog/getting-started-with-postman-graphql/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're building an API, you need to have tools to query it. Postman is the reference for this, allowing you to create and send requests to your endpoints and so much more.&lt;/p&gt;

&lt;p&gt;Postman has loads of built-in parameters and features, such as custom cookies, environment variables, scripting, testing, and exporting requests to HTTP clients (curl, fetch, python, axios...). Postman also allows you to share and collaborate on your requests collections, making it a go-to tool for many tech enterprises. It also ships with a powerful mocking engine, allowing developers to design their APIs directly in Postman before implementing them.&lt;/p&gt;

&lt;p&gt;In this guide, you'll learn the basics of Postman for GraphQL APIs, so you can quickly start using it to create and debug yours.&lt;/p&gt;

&lt;p&gt;To get started, get Postman here: &lt;a href="https://www.postman.com/downloads/"&gt;https://www.postman.com/downloads/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: if you already use Postman for REST and only want to see the GraphQL part, head to #🕸using-postman-with-graphql-apis&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Postman general concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
   Requests
&lt;/h3&gt;

&lt;p&gt;As Postman is an API client, HTTP requests are its fundamental building block. Create a request by with "new" -&amp;gt; "HTTP request"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nFxK8Nhg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kjiiz47drlp073kyu5ry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nFxK8Nhg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kjiiz47drlp073kyu5ry.png" alt="Postman API Client" width="600" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The top bar allows you to set the request mode (GET, POST, PUT, ...) and its URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1iOBjOe8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9gqwevhgstd9gyghmro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1iOBjOe8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9gqwevhgstd9gyghmro.png" alt="Postman Top Bar" width="800" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below you'll find several tabs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zrcpWuNx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lau4r6wi8ae3vetk7tea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zrcpWuNx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lau4r6wi8ae3vetk7tea.png" alt="Postman tabs" width="800" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Params are REST query params of URLs:&lt;code&gt;?key=value&lt;/code&gt;, those are useless for GraphQL&lt;/li&gt;
&lt;li&gt;Authorization allows you to define multiple types of Auth such as Bearer Token, API key, etc.&lt;/li&gt;
&lt;li&gt;Headers are self-explanatory&lt;/li&gt;
&lt;li&gt;Body is the part that interests us for GraphQL, and I'll detail it in the next paragraph&lt;/li&gt;
&lt;li&gt;Pre-request Script and Tests are more advanced functionalities that I'll cover in an advanced guide.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And last but not least, remember to save your requests! (ctrl + s or the "save" button).&lt;/p&gt;

&lt;h3&gt;
  
  
  Collection
&lt;/h3&gt;

&lt;p&gt;If you try to save your request, a prompt will ask you to choose a collection. Postman collections are just groups of recommendations. Try to edit and save your request in a collection!&lt;/p&gt;

&lt;h3&gt;
  
  
  Workspace
&lt;/h3&gt;

&lt;p&gt;The workspace is like a group of collections &amp;amp; requests, but with superpowers. You can share workspaces (publicly or privately with your team), have scoped environments, variables, etc. You can see your current workspace name and its "parts" on the left tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SkclLIhm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dabp4a7x1cansdssoe1x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SkclLIhm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dabp4a7x1cansdssoe1x.png" alt="For this first guide I'll only cover Collections and Environments." width="766" height="896"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🕸 Using Postman with GraphQL APIs
&lt;/h2&gt;

&lt;p&gt;Back to business: fortunately, Postman has built-in full support for GraphQL! 🎉Let's take a quick tour of the capabilities by exploring the Rick and Morty API. To get started, create a new HTTP request in Postman. Set the request mode to POST and the URL to &lt;a href="https://rickandmortyapi.com/graphql"&gt;https://rickandmortyapi.com/graphql&lt;/a&gt;. Now; in the body section, select GraphQL. You should end up with something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z6I-crCZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjb6r7yhevrm4gb87e0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z6I-crCZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjb6r7yhevrm4gb87e0h.png" alt="Postman GraphQL Client" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cool thing about Postman is that it auto-fetches your endpoint's schema, as you can see with the green "Schema Fetched." indication. That allows auto-completion of your queries with typing and so on. Start typing a query with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you hit [⌃ + space] or [ctrl + space], you should see auto-suggestions of what you can query in the API:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zeeWVf9h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xb9qz615cxco6ntzzhvy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zeeWVf9h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xb9qz615cxco6ntzzhvy.png" alt="Image description" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's say we want to get the characters of the show, simply type character inside of the query, and Postman will quickly tell you what your request is missing, thanks to the schema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pzyHw_p2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fcwlcxhcau5zgneiwmjj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pzyHw_p2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fcwlcxhcau5zgneiwmjj.png" alt="Image description" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So here we can see what's the problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subfields: character is an object type, so we need to specify which fields of the character we want to get.&lt;/li&gt;
&lt;li&gt;Argument: the character has to be selected with its id.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's correct the request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YJGFnCxZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9l6kcql76fht3617dov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YJGFnCxZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9l6kcql76fht3617dov.png" alt="Image description" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But you can see that you still need to select subfields, same as before, to see what's valid just hit [⌃ + space] or [ctrl + space] to get suggestions of available fields:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--22H3vD0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/izlft2bt7pw154xnj4g5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--22H3vD0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/izlft2bt7pw154xnj4g5.png" alt="Image description" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can complete and send it. You can see that we got the desired results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mqvOa4V4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zaweks11eul9lgqu33c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mqvOa4V4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zaweks11eul9lgqu33c.png" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also have object fields that need their subfields; see &lt;code&gt;origin&lt;/code&gt; here.&lt;/p&gt;

&lt;p&gt;As a last detail, let's use variables:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uPWOqHbN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jcc87l9b8rbg4boot6zx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uPWOqHbN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jcc87l9b8rbg4boot6zx.png" alt="Image description" width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This request will get you the same result. Still, its format is way cleaner, and the variable fields can be bound to postman variables and scripted this way, allowing you to write super powerful tests and routines, which I'll cover in the following guide! &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Escape will gain you hours
&lt;/h2&gt;

&lt;p&gt;What if I told you that all the heavy work of crafting requests for your GraphQL API could be fully automated? &lt;/p&gt;

&lt;p&gt;&lt;a href="https://escape.tech"&gt;Escape&lt;/a&gt; automatically tests the security, performance a reliability of your GraphQL API in a few seconds. &lt;/p&gt;

&lt;p&gt;But the cool thing is that it is based on a powerful feedback-driven API exploration algorithm that is able to generate legitimate requests on your API before fuzzing them for security purposes.&lt;/p&gt;

&lt;p&gt;And the cool stuff is that in addition to be able to find and fix your API bugs, you can easily reproduce them thourgh the autogenerated Postman Collection, while exploring all your API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oTa5R7oU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t5g0suuywo3ztxlid3du.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oTa5R7oU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t5g0suuywo3ztxlid3du.png" alt="Postman Collection export in Escape GraphQL Security Platform" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://escape.tech"&gt;Try it yourself fo free in 1 minute!&lt;/a&gt; It does not require any configuration ;) &lt;/p&gt;

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

&lt;p&gt;By now, you should be able to query your GraphQL API using Postman, and this will help you a lot in your development process, trust me!&lt;/p&gt;

&lt;p&gt;But as I said, Postman can do a lot more than what I've covered here: scripting, testing, environment setup, exports... I'll cover those advanced and super powerful concepts in the following article, so stay tuned to become a Postman master! 😎&lt;/p&gt;

</description>
      <category>postman</category>
      <category>graphql</category>
      <category>api</category>
      <category>testing</category>
    </item>
    <item>
      <title>Demystifying GraphQL Security: A Comprehensive Guide to Introspection</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Thu, 30 Mar 2023 18:00:33 +0000</pubDate>
      <link>https://dev.to/tristankalos/demystifying-graphql-security-a-comprehensive-guide-to-introspection-34fm</link>
      <guid>https://dev.to/tristankalos/demystifying-graphql-security-a-comprehensive-guide-to-introspection-34fm</guid>
      <description>&lt;p&gt;This post by &lt;a href="https://twitter.com/iCarossio" rel="noopener noreferrer"&gt;Antoine&lt;/a&gt; is easier to read &lt;a href="https://escape.tech/blog/should-i-disable-introspection-in-graphql/" rel="noopener noreferrer"&gt;on our blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whether or not to disable introspection has been a common debate among GraphQL developers since its inception. In this blog post, we will explain why completely disabling introspection is not necessary and why it can be counterproductive.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1221971611953369088-742" src="https://platform.twitter.com/embed/Tweet.html?id=1221971611953369088"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1221971611953369088-742');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1221971611953369088&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;Marc-André Giroux, Author of Production Ready GraphQL&lt;/p&gt;
&lt;h2&gt;
  
  
  Why is introspection useful?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What is introspection?
&lt;/h3&gt;

&lt;p&gt;Firstly, it's essential to understand what Introspection is in GraphQL. It is the ability to provide metadata about its schema, including types, fields, and directives. It allows developers to explore the API structure and understand the available data.&lt;/p&gt;

&lt;p&gt;The simplest way to know if your introspection is open is to fetch it yourself!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --location 'https://example.com/graphql' \
--header 'Authorization: Bearer &amp;lt;token&amp;gt;' \
--header 'Content-Type: application/json' \
--data '{"query":"query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description locations args { ...InputValue } } } } fragment FullType on __Type { kind name description fields(includeDeprecated: true) { name description args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } possibleTypes { ...TypeRef } } fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } }","variables":{}}' \ &amp;gt; introspection.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The curl introspection command&lt;/p&gt;

&lt;h2&gt;
  
  
   An essential feature for productivity and flexibility
&lt;/h2&gt;

&lt;p&gt;Introspection is a handy feature for front-end and client developers. In particular, one of the most significant advantages of GraphQL is its ability to allow them to request only the data they need. Introspection plays a crucial role in this process by enabling them to discover and understand the available types and fields in the schema. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By disabling introspection, you're essentially taking away a valuable tool&lt;/strong&gt; that developers can use to improve their productivity and make better-informed decisions about how to structure their queries.&lt;/p&gt;

&lt;p&gt;Moreover, Introspection can be a valuable tool for API documentation and discovery. By disabling it in production, you might need to invest additional resources in maintaining separate documentation and keeping it up-to-date. This can increase the complexity of your API maintenance process and potentially lead to inconsistencies between the actual schema and the documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is introspection really a security concern?
&lt;/h2&gt;

&lt;h3&gt;
  
  
   It seems like a potential security risk
&lt;/h3&gt;

&lt;p&gt;The main argument for disabling introspection is that it can be a security risk. By allowing introspection, malicious actors can exploit this information to craft targeted attacks against your application. In particular, it can potentially expose additional entry points, such as hidden or undocumented operations that might not be as secure as the rest of your application.&lt;/p&gt;

&lt;p&gt;It can also be a performance issue. When a GraphQL server receives an introspection query, it must traverse the entire schema and gather metadata, which can be time-consuming and resource-intensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where there's a will; there's a way
&lt;/h2&gt;

&lt;p&gt;At that point, it might seem obvious to disable introspection for security purposes. The problem is that disabling it is just a "false good idea". There is always a simple way to find your schema and craft malicious requests against your GraphQL API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Field suggestion leaks your schema
&lt;/h2&gt;

&lt;p&gt;Most GraphQL engines have a feature called Field Suggestion. When the server receives a query with invalid fields, it will respond with an error message indicating that the requested field does not exist.&lt;/p&gt;

&lt;p&gt;However, this error message also contains information about fields with similar names that do exist within the schema. This GraphQL feature is called Field Suggestion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "errors": [
    {
      "message": "Cannot query field \"space\" on type \"Query\". Did you mean \"escape\"?",
      "locations": [
        {
          "line": 1,
          "column": 5
        }
      ],
      "extensions": {
        "code": "GRAPHQL-VALIDATION-FAILED"
      }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
   Field suggestion in GraphQL
&lt;/h3&gt;

&lt;p&gt;This feature can be abused: by sending random field names in a query and gathering the suggestions that the servers send back, one can build back the complete GraphQL Schema! This is an attack called Field Fuzzing.&lt;/p&gt;

&lt;p&gt;Clairvoyance is an open-source tool created by Nikita Stupin and maintained by Escape that allows developers to retrieve GraphQL introspection data even when disabled using Field Fuzzing.&lt;/p&gt;

&lt;p&gt;By analyzing these error messages, Clairvoyance can determine the structure of the schema and retrieve the necessary introspection data.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F022blvi2ag7b21b6c1mz.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F022blvi2ag7b21b6c1mz.png" alt="Full GraphQL schema built back by Clairvoyance on an endpoint with deactivated introspection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On Apollo and Yoga servers, you can easily disable Field Suggestion using our free, open-source tool GraphQL Armor.&lt;/p&gt;

&lt;h2&gt;
  
  
  The frontend knows everything.
&lt;/h2&gt;

&lt;p&gt;Obviously, it is possible to recreate the introspection from the traffic generated by a front-end. This means that even if you disable introspection, a determined attacker could still gain access to the schema information by navigating to your application's website.&lt;br&gt;
My introspection is only enabled on staging&lt;/p&gt;

&lt;p&gt;Do you think keeping your introspection open on staging makes your production more secure?&lt;/p&gt;

&lt;p&gt;Most of the time, we notice that if your production endpoint is available on &lt;code&gt;https://graphql.example.com/&lt;/code&gt;, your staging environment is accessible through &lt;code&gt;https://staging.graphql.example.com/&lt;/code&gt;. In that case, getting the introspection of your staging is a no-brainer.&lt;/p&gt;

&lt;p&gt;Let's say you tried to hide your staging environment on a random URL. At Escape, we developed open-source software to find any GraphQL endpoint related to your main application. &lt;/p&gt;

&lt;p&gt;Using subdomain enumeration, web crawling, and brute forcing, &lt;a href="https://github.com/Escape-Technologies/goctopus" rel="noopener noreferrer"&gt;Goctopus&lt;/a&gt; can find any of your GraphQL endpoints and know whether introspection or field suggestions are enabled on each of them.&lt;/p&gt;

&lt;p&gt;We use Goctopus in our own platform, Escape, to index all our customer's exposed GraphQL Endpoints. We discovered that a surprisingly high amount of organizations have their staging and development environment open, with introspection activated.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dbvuci3gcqnhecqzttl.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dbvuci3gcqnhecqzttl.png" alt="In our platform, Escape, we index all our customer's exposed GraphQL Endpoints using Goctopus "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
   Conclusion: don't trade productivity against obscurity
&lt;/h2&gt;

&lt;p&gt;At Escape, we believe in security by obscurity, and thus we advise not to disable introspection.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You can keep your introspection enabled: Completely disabling introspection doesn't actually make your server more secure; it just makes it harder for developers to do their jobs.

Optionally, implement role-based access control: If you still don't fill confident in letting your introspection open to the world, you can configure your GraphQL server to enable introspection only for specific user roles, such as administrator or developers, ensuring the feature is accessible only to trusted users. See more details in our documentation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ultimately, deciding to disable introspection in production depends on your specific use case and requirements. Ensure you provide your developers with the best experience while maintaining a robust application.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>security</category>
      <category>api</category>
    </item>
    <item>
      <title>The State of Public APIs 2023</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Thu, 23 Mar 2023 17:02:16 +0000</pubDate>
      <link>https://dev.to/tristankalos/the-state-of-public-apis-2023-1m1f</link>
      <guid>https://dev.to/tristankalos/the-state-of-public-apis-2023-1m1f</guid>
      <description>&lt;p&gt;&lt;em&gt;tl;dr we (&lt;a href="https://escape.tech" rel="noopener noreferrer"&gt;Escape&lt;/a&gt;) scanned 6056+ public APIs on the internet with our in-house &lt;a href="https://escape.tech/blog/feedback-driven-api-exploration/" rel="noopener noreferrer"&gt;feedback driven exploration&lt;/a&gt; tech and ranked them using security, performance, reliability, and design criteria. We decided to analyze the resulting data and produce a full featured report: &lt;a href="https://apirank.dev/state-of-public-api-2023" rel="noopener noreferrer"&gt;The State of Public APIs 2023&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why build this report? 🤔
&lt;/h2&gt;

&lt;p&gt;Two weeks ago, we released &lt;a href="//apirank.dev"&gt;apirank.dev&lt;/a&gt;, the result of extensive research on public APIs on the internet, conducted at an unprecedented scale using our feedback-driven API exploration technology. You can read more about this in our &lt;a href="https://escape.tech/blog/apirank-dev-we-scanned-and-ranked-5651-public-apis-on-the-internet/" rel="noopener noreferrer"&gt;original APIRank post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But we quickly realized that the data we gathered for &lt;strong&gt;ranking&lt;/strong&gt; APIs could also be used to establish a &lt;strong&gt;benchmark&lt;/strong&gt; of the current state of Public APIs in the wild. &lt;/p&gt;

&lt;p&gt;Thus, we compiled this dataset into a full-featured report that analyzes the performance, reliability, design, and security of the APIs we scanned.&lt;/p&gt;

&lt;p&gt;To our knowledge, this is one of the first of its kind study about the quality of APIs, mostly because of its scale and the depth of the data we gathered.&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%2Fi.imgur.com%2FYb74Sf9.png" 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%2Fi.imgur.com%2FYb74Sf9.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the properties we analyzed? 🎯
&lt;/h2&gt;

&lt;p&gt;Since the data we used for creating the report comes from APIRank.dev, we used similar properties to those in our original study:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security &lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;li&gt;Design&lt;/li&gt;
&lt;li&gt;Popularity&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Results 🏅
&lt;/h2&gt;

&lt;p&gt;The full results can be found on &lt;a href="https://apirank.dev/state-of-public-api-2023" rel="noopener noreferrer"&gt;The State of Public APIs 2023&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We discovered that while public APIs are getting more and more documented, significant improvement in the industry can still be made regarding documentation quality, response reliability, and especially security.&lt;/p&gt;

&lt;p&gt;We hope to see more studies of this kind to be conducted to observe how those tendencies evolve in the future.&lt;/p&gt;

</description>
      <category>api</category>
      <category>security</category>
      <category>performance</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>APIRank.dev - we crawled and ranked all public APIs on the internet 🔭</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Tue, 21 Mar 2023 17:07:57 +0000</pubDate>
      <link>https://dev.to/tristankalos/apirankdev-we-crawled-and-ranked-all-public-apis-on-the-internet-1iho</link>
      <guid>https://dev.to/tristankalos/apirankdev-we-crawled-and-ranked-all-public-apis-on-the-internet-1iho</guid>
      <description>&lt;p&gt;&lt;em&gt;tl;dr we (&lt;a href="https://escape.tech" rel="noopener noreferrer"&gt;Escape&lt;/a&gt;) scanned 3000+ public APIs on the internet with our in-house &lt;a href="https://escape.tech/blog/feedback-driven-api-exploration/" rel="noopener noreferrer"&gt;feedback driven exploration&lt;/a&gt; tech and ranked them using security, performance, reliability, and design criteria. The results are public on &lt;a href="https://apirank.dev/" rel="noopener noreferrer"&gt;APIrank.dev&lt;/a&gt;. You can also request to index your own API for free and see how it compares to others.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why APIrank? 🤔
&lt;/h2&gt;

&lt;p&gt;During a YC meetup I spoke with a fellow founder that told me how hard it was to pick the right external APIs to use within your own projects.&lt;/p&gt;

&lt;p&gt;It's true that as developers and hackers, we rely more on external services for building our products. &lt;/p&gt;

&lt;p&gt;We interact with those vendors' services through their public APIs, which often become a central part of our stacks.&lt;/p&gt;

&lt;p&gt;Yet, no good resource existed to compare the quality of similar vendors' public APIs to help engineering/product teams pick the right provider.&lt;/p&gt;

&lt;p&gt;What if there was a website that would help you compare the performance, reliability, security, and design of different vendors' public APIs? &lt;/p&gt;

&lt;p&gt;Well, say hello to &lt;a href="//apirank.dev"&gt;apirank.dev&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%2Fi.imgur.com%2FeXoy50k.png" 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%2Fi.imgur.com%2FeXoy50k.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is ranking public APIs &lt;em&gt;hard&lt;/em&gt;? 🥵
&lt;/h2&gt;

&lt;p&gt;Automating the audit of public APIs is a very hard problem. First, we needed to find all the public APIs and their specifications - mostly OpenAPI files. &lt;/p&gt;

&lt;p&gt;We used several different strategies to fetch OpenAPI specifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crawl API repositories like &lt;a href="https://apis.guru/" rel="noopener noreferrer"&gt;apis.guru&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Crawl github for &lt;code&gt;openapi.json&lt;/code&gt; and &lt;code&gt;openapi.yaml&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;A cool google dork &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those strategies enabled us to gather around ~20.000 OpenAPIs specs.&lt;/p&gt;

&lt;p&gt;Then lies the hard part of the problem:&lt;/p&gt;

&lt;p&gt;We want to dynamically evaluate the security, performance, and reliability of those APIs.&lt;/p&gt;

&lt;p&gt;But APIs take parameters that are tightly coupled to the underlying business logic. &lt;/p&gt;

&lt;p&gt;A &lt;em&gt;naive&lt;/em&gt; automated would also not work: putting random data in parameters would likely not pass the API's validation layer, thus giving us little insight into the real API behavior.&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%2Fi.imgur.com%2FGj3IFvd.png" 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%2Fi.imgur.com%2FGj3IFvd.png" alt="Naive API testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Manually creating tests for each API is also not sustainable: it would take years for our 10-people team. We needed to do it in an automated way.&lt;/p&gt;

&lt;p&gt;Fortunately, our main R&amp;amp;D efforts at Escape aimed to generate legitimate traffic against any API efficiently. &lt;/p&gt;

&lt;p&gt;That's how we developed Feedback-Driven API Exploration, a new technique that quickly asses the underlying business logic of an API by analyzing responses and dependencies between requests. (We did a more in-depth &lt;a href="https://escape.tech/blog/feedback-driven-api-exploration/" rel="noopener noreferrer"&gt;blog post about it&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%2Fi.imgur.com%2F8zItMEV.png" 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%2Fi.imgur.com%2F8zItMEV.png" alt="Feedback-Driven API Exploration Testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We originally developed this technology for advanced API security testing. But from there, it was super easy also to test the performance and the reliability of APIs. &lt;/p&gt;

&lt;h2&gt;
  
  
  How we ranked APIs 1️⃣0️⃣0️⃣
&lt;/h2&gt;

&lt;p&gt;Now that we have a scalable way to gather exciting data from public APIs, we need to find a way to rank them. And this ranking should be meaningful to developers when choosing their APIs.&lt;/p&gt;

&lt;p&gt;We decided to rank APIs using the following five criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security &lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;li&gt;Design&lt;/li&gt;
&lt;li&gt;Popularity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An API's &lt;strong&gt;security&lt;/strong&gt; score is computed as the combination of two sub-scores: the number of OWASP top 10 vulnerabilities and the number of personally identifiable information (PII) leaks detected by our scanner.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;performance&lt;/strong&gt; score is derived from the median response time of the API, sometimes referred to as p50. &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;reliability&lt;/strong&gt; score is derived from the number of inconsistent server responses, either server errors or non-conforming return values.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;design&lt;/strong&gt; score reflects the quality of the specification file. Having a high-quality specification file (with up-to-date types and examples) helps developers understand the API and tools to produce relevant documentation.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;popularity&lt;/strong&gt; score is computed from the number of references to the API found online.&lt;/p&gt;

&lt;p&gt;If you are curious about your API's performance, you can &lt;a href="https://apirank.dev/submit" rel="noopener noreferrer"&gt;ask us to index your API on APIrank.dev&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Our ask 😃
&lt;/h2&gt;

&lt;p&gt;Ranking all public APIs on the internet is a massive project, and we would gladly welcome help from the community!&lt;/p&gt;

&lt;p&gt;You can help us by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Giving your feedback on our ranking criteria and proposing new ones&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apirank.dev/submit" rel="noopener noreferrer"&gt;Sending us Public APIs to add to our index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sharing your favorite API's score on social media&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>programming</category>
    </item>
    <item>
      <title>Releasing OpenAPI.security, a free tool to quickly check the security of any Swagger / OpenAPI-based API</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Sat, 11 Feb 2023 18:46:43 +0000</pubDate>
      <link>https://dev.to/tristankalos/releasing-openapisecurity-a-free-tool-to-quickly-check-the-security-of-any-swagger-openapi-based-api-4d47</link>
      <guid>https://dev.to/tristankalos/releasing-openapisecurity-a-free-tool-to-quickly-check-the-security-of-any-swagger-openapi-based-api-4d47</guid>
      <description>&lt;p&gt;&lt;em&gt;tl;dr we released &lt;a href="https://openapi.security"&gt;openapi.security&lt;/a&gt;, an online tool that performs a dozen of security tests on any given openapi/swagger-based API, with no signup or email required&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our team at Escape is mainly focused on securing GraphQL APIs. For this, we developed a new approach called Feedback driven API Exploration, basically inferring the right security tests cases to run using the specification and a carefully crafted in house graph traversal algorithm. - We published a more in depth review of this algorithm &lt;a href="https://escape.tech/blog/feedback-driven-api-exploration/"&gt;in another post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At Escape, we often organise internal hackathons. It's a way to learn new things, but also to experiment with our internal tools and discover new applications. This time, we wondered if our Feedback Driven Exploration could be applied to good old REST APIs as well and ended up creating OpenAPI.security.&lt;/p&gt;

&lt;p&gt;The concept is simple: anybody can enter an OpenAPI / Swagger spec, and &lt;a href="https://openapi.security"&gt;openapi.security&lt;/a&gt; will run a bunch of security tests on it and give back a report. It's designed to be fast and smart in the way it analyzes input specs.&lt;/p&gt;

&lt;p&gt;Since it worked quite well we wanted to share it with the community as well. (NB It's a side project for now)&lt;/p&gt;

</description>
      <category>security</category>
      <category>api</category>
      <category>testing</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Graphman: generate a postman collection for any GraphQL endpoint</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Tue, 09 Aug 2022 12:00:49 +0000</pubDate>
      <link>https://dev.to/tristankalos/graphman-generate-a-postman-collection-for-any-graphql-endpoint-4hff</link>
      <guid>https://dev.to/tristankalos/graphman-generate-a-postman-collection-for-any-graphql-endpoint-4hff</guid>
      <description>&lt;p&gt;&lt;em&gt;tl;dr we released &lt;a href="https://github.com/Escape-Technologies/graphman"&gt;github.com/Escape-Technologies/graphman&lt;/a&gt;, a free and open source tool that generates a Postman collection for any GraphQL endpoint in seconds&lt;/em&gt; 👨‍🚀&lt;/p&gt;

&lt;p&gt;We use GraphQL with Postman a lot in our team. GraphQL is pretty verbose and we found it quite painful to write all the queries by hand when interacting with any new endpoint.&lt;/p&gt;

&lt;p&gt;So we created Graphman, a tiny utility that uses GraphQL's introspection capability to generate a full Postman collection for any GraphQL endpoint.&lt;/p&gt;

&lt;p&gt;Happy to release this to the community as a free and open source dev tool 🤟 &lt;/p&gt;

&lt;p&gt;Link to the repo: &lt;a href="https://github.com/Escape-Technologies/graphman"&gt;https://github.com/Escape-Technologies/graphman&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you use GraphQL, feel free to help us by staring and contributing 🤩&lt;/p&gt;

</description>
      <category>postman</category>
      <category>api</category>
      <category>graphql</category>
      <category>tooling</category>
    </item>
    <item>
      <title>GraphQL Armor: A middleware to make your GraphQL endpoints secure</title>
      <dc:creator>Tristan Kalos</dc:creator>
      <pubDate>Fri, 05 Aug 2022 12:06:00 +0000</pubDate>
      <link>https://dev.to/tristankalos/graphql-armor-a-middleware-to-make-your-graphql-endpoints-secure-1fg3</link>
      <guid>https://dev.to/tristankalos/graphql-armor-a-middleware-to-make-your-graphql-endpoints-secure-1fg3</guid>
      <description>&lt;p&gt;&lt;em&gt;tl;dr we released &lt;a href="https://github.com/Escape-Technologies/graphql-armor"&gt;github.com/Escape-Technologies/graphql-armor&lt;/a&gt;, a developer friendly, free and open source middleware that adds a security layer to any js-based GraphQL server.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"GraphQL is less secure than most REST APIs"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is something we have heard a lot since GraphQL's inception in 2015.&lt;/p&gt;

&lt;p&gt;Our security research team confirmed this when spending a year on evaluating security in the GraphQL ecosystem. (I even &lt;a href="https://www.youtube.com/watch?t=2574&amp;amp;v=J7926_Loy7o&amp;amp;feature=youtu.be"&gt;gave a talk about the results at GraphQL SF 2022&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;We decided the GraphQL ecosystem deserved to be more secure and created &lt;strong&gt;GraphQL Armor&lt;/strong&gt;, a developer friendly middleware that quickly adds a security layer to any js-based GraphQL server.&lt;/p&gt;

&lt;p&gt;Out-of-the-box, you get protection against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bruteforcing&lt;/li&gt;
&lt;li&gt;Query complexity attacks (Depth, Width, cyclomatic complexity)&lt;/li&gt;
&lt;li&gt;Information Disclosure (Schema leaks)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But more is to come, we are adding protection against new attacks every week 😎 &lt;/p&gt;

&lt;p&gt;Link to the repo: &lt;a href="https://github.com/Escape-Technologies/graphql-armor"&gt;https://github.com/Escape-Technologies/graphql-armor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you use GraphQL, feel free to help us by staring and contributing 🤩&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>apolloserver</category>
      <category>typescript</category>
      <category>security</category>
    </item>
  </channel>
</rss>
