<?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: Philippe Arteau</title>
    <description>The latest articles on DEV Community by Philippe Arteau (@h3xstream).</description>
    <link>https://dev.to/h3xstream</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%2F251294%2F3c61559c-5ece-41a9-958b-8591a0f30967.jpeg</url>
      <title>DEV Community: Philippe Arteau</title>
      <link>https://dev.to/h3xstream</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/h3xstream"/>
    <language>en</language>
    <item>
      <title>Fixing Jest import failure</title>
      <dc:creator>Philippe Arteau</dc:creator>
      <pubDate>Mon, 29 Jul 2024 18:25:18 +0000</pubDate>
      <link>https://dev.to/h3xstream/fixing-jest-import-failure-186b</link>
      <guid>https://dev.to/h3xstream/fixing-jest-import-failure-186b</guid>
      <description>&lt;p&gt;If you are reading this post, you likely encounter this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; 4 | import someConfig from '../config/SomeConfigs.json' with { type: 'json' }; 
    |                                                                ^
  5 |
  6 | /**

Add @babel/plugin-syntax-import-attributes (https://github.com/babel/babel/tree/main/packages/babel-plugin-syntax-import-attributes) to the 'plugins' section of your Babel config to enable parsing.

If you already added the plugin for this syntax to your config, it's possible that your config isn't being loaded.
You can re-run Babel with the BABEL_SHOW_CONFIG_FOR environment variable to show the loaded configuration:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue in my case was to create a babel configuration file for Jest to use when transpiling the different source files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;babel.config.js (or babel.config.cjs)&lt;/strong&gt;&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&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;isTest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/plugin-syntax-import-attributes&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;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Source
&lt;/h3&gt;

&lt;p&gt;I took inspiration from &lt;a href="https://saptaks.blog/posts/configuring-jest-with-react-and-babel.html" rel="noopener noreferrer"&gt;this blog post which described issues with React dependencies in Jest unit tests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This complete example uses the &lt;a href="https://jestjs.io/docs/getting-started#using-babel" rel="noopener noreferrer"&gt;conditional configuration suggested in Jest documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = api =&amp;gt; {
  const isTest = api.env('test');
  // You can use isTest to determine what presets and plugins to use.

  return {
    // ...
  };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>jest</category>
      <category>tooling</category>
      <category>babel</category>
    </item>
    <item>
      <title>Solving FlashBoy "Error opening COM port"</title>
      <dc:creator>Philippe Arteau</dc:creator>
      <pubDate>Wed, 23 Feb 2022 23:01:44 +0000</pubDate>
      <link>https://dev.to/h3xstream/solving-flashboy-error-opening-com-port-4p6n</link>
      <guid>https://dev.to/h3xstream/solving-flashboy-error-opening-com-port-4p6n</guid>
      <description>&lt;p&gt;This is a short post to help Flash Boy &lt;sup&gt;&lt;a href="https://www.aliexpress.com/item/4001330749681.html"&gt;1&lt;/a&gt; &lt;a href="https://www.ebay.com/itm/264065747210"&gt;2&lt;/a&gt;&lt;/sup&gt; users find the right software and drivers. Flash Boy is a GameBoy cartridge dumper. The manufacturer does not have any product page therefore it can be time consuming to find the software needed or documentation.&lt;/p&gt;




&lt;p&gt;If you are reading this, you are probably unable to use the device. Here are the error messages you could get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Device not found!"&lt;/li&gt;
&lt;li&gt;"Check COM port connection."&lt;/li&gt;
&lt;li&gt;"Error opening COM port."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a few trials and errors, I found that FlashBoy dumpers seem to have multiple versions with different firmware and required different softwares.&lt;/p&gt;

&lt;h2&gt;
  
  
  Software options
&lt;/h2&gt;

&lt;p&gt;Here is the list of flasher program available.&lt;/p&gt;

&lt;h3&gt;
  
  
  1) GBX Driver 2.0
&lt;/h3&gt;

&lt;p&gt;This UI tool is developed by Tengu Development. Tengu is also the manufacturer shown when the device is mounting the "fake" drive (GBX).&lt;/p&gt;

&lt;p&gt;As of 2021, this is the software to interact with the latest hardware.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://drive.google.com/file/d/13ferDd2TQ_dg1VdFCFZpd59U9IYZM_dU/view?usp=sharing"&gt;Download GBX Driver 2.0 for Flash Boy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E0V5pBXy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fgkluxsw3d31vn9zy0ev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E0V5pBXy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fgkluxsw3d31vn9zy0ev.png" alt="GBX Driver 2.0" width="490" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2) GB Cart Flasher version 1.1
&lt;/h3&gt;

&lt;p&gt;Software release by Kraku and Chroost. It seems to support older version of the FlashBoy.&lt;/p&gt;

&lt;p&gt;This is the first software I tested because it appears in this &lt;a href="https://www.youtube.com/watch?v=aaEEqqJB3Ws"&gt;Youtube Flash Boy review&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sourceforge.net/projects/gbcf/"&gt;Download GB Cart Flasher version 1.1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cxMp0zIn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hlmxng0e368a7gexeqtz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cxMp0zIn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hlmxng0e368a7gexeqtz.png" alt="GB Cart Flasher version 1.1" width="786" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3) FlashBoy Cyclone
&lt;/h3&gt;

&lt;p&gt;This software is dedictated to the Cyclone version of the FlashBoy. I don't have this specific device to validate that its validity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.box.com/s/nvme61lnm6chn3ludccto5fyy6rdvckt?spm=a2g0o.detail.1000023.1.273a12efhMNomd"&gt;Download FlashBoy Cyclone&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EcSNWmRJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rnblya9cgecjc89ao747.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EcSNWmRJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rnblya9cgecjc89ao747.png" alt="FlashBoy Cyclone" width="794" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4) FlashGBX
&lt;/h3&gt;

&lt;p&gt;Last but not least, FlashGBX is the recommended software for the &lt;a href="https://shop.insidegadgets.com/product/gbxcart-rw/"&gt;GBxCart RW from insidegadgets&lt;/a&gt;. While GBxRW is not manufactured by Backlight ENG.LAB (the company behind Flash Boy), it is my recommendation if you haven't bought a dumper/flasher yet. It can read the ROM and RAM just like the previous, but it also to write the ROM and RAM of numerous cartridges types including cheap reproduction cartridge (~4 USD) found on Aliexpress or eBay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lesserkuma/FlashGBX/releases"&gt;Download FlashGBX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PoxT51a6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8scr8s9s00l4v3h0zoau.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PoxT51a6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8scr8s9s00l4v3h0zoau.png" alt="FlashGBX for the GBxRW" width="593" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gameboy</category>
      <category>retro</category>
      <category>backup</category>
    </item>
    <item>
      <title>Advanced Scripting for Orange Data Mining</title>
      <dc:creator>Philippe Arteau</dc:creator>
      <pubDate>Tue, 01 Feb 2022 16:25:47 +0000</pubDate>
      <link>https://dev.to/h3xstream/advanced-scripting-for-orange-data-mining-49f0</link>
      <guid>https://dev.to/h3xstream/advanced-scripting-for-orange-data-mining-49f0</guid>
      <description>&lt;p&gt;Have you ever heard of &lt;a href="https://orangedatamining.com/"&gt;Orange Data Mining&lt;/a&gt;? It is a powerful data mining framework that includes Python API and a visual GUI.&lt;/p&gt;

&lt;p&gt;This blog post is for people looking to create add new attributes dynamically to your data set. It will also provide a good example of scripting in Orange.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I have a CSV dataset with an attribute that has multi-values possible and I want to create a new attribute for every value present in the multi-values attribute.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Here is a simple example that is easier to understand than my actual dataset.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Initial dataset
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;country&lt;/th&gt;
&lt;th&gt;flag_colors&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;italy&lt;/td&gt;
&lt;td&gt;green,white,red&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;united kingdom&lt;/td&gt;
&lt;td&gt;red,blue,white&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;russia&lt;/td&gt;
&lt;td&gt;white,blue,red&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;canada&lt;/td&gt;
&lt;td&gt;red,white&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;brazil&lt;/td&gt;
&lt;td&gt;green,blue,yellow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;germany&lt;/td&gt;
&lt;td&gt;black,red,yellow&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Target dataset
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;country&lt;/th&gt;
&lt;th&gt;...&lt;/th&gt;
&lt;th&gt;green&lt;/th&gt;
&lt;th&gt;white&lt;/th&gt;
&lt;th&gt;red&lt;/th&gt;
&lt;th&gt;blue&lt;/th&gt;
&lt;th&gt;yellow&lt;/th&gt;
&lt;th&gt;black&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;italy&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;united kingdom&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;russia&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;canada&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;brazil&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;germany&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Custom Script Solution
&lt;/h2&gt;

&lt;p&gt;I have annotated my solution.&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;Orange.data&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ContinuousVariable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DiscreteVariable&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;copy&lt;/span&gt;

&lt;span class="n"&gt;attributes_to_expand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'colors'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;separator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"|"&lt;/span&gt; &lt;span class="c1"&gt;#Separator can be changed to , ; - 
&lt;/span&gt;
&lt;span class="c1"&gt;# Structure used to build the new model
&lt;/span&gt;&lt;span class="n"&gt;attributes_to_keep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;class_vars_to_keep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;metas_to_keep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;# Old and new variables
&lt;/span&gt;&lt;span class="n"&gt;all_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#values to keep for each multi-values columns
&lt;/span&gt;
&lt;span class="c1"&gt;# Building a list of all the known values for each column to expand
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;in_data&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;att_exp&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attributes_to_expand&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;separator&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;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;values&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="ow"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_values&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
                &lt;span class="n"&gt;all_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#One new attribute per value maximum
&lt;/span&gt;            &lt;span class="n"&gt;all_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Keeping existing metadata and class variables (target)
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;orig_meta&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;in_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;metas_to_keep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orig_meta&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;orig_class_var&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;in_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class_vars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;class_vars_to_keep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orig_class_var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Keeping non-multi-values variables
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;orig_var&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;in_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;variables&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;orig_var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attributes_to_expand&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;orig_var&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;class_vars_to_keep&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orig_var&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;attributes_to_keep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orig_var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# Adding the list of all the new variables
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;att_exp&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attributes_to_expand&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;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ContinuousVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;"="&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Output Table construction
&lt;/span&gt;
&lt;span class="c1"&gt;## Domain describes the variables of our dataset
&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;class_vars&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;class_vars_to_keep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;metas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;metas_to_keep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;## Table include both the domain definition and the data
&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in_data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;## Rebuilding the data line by line
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Variables that we keep as-is
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;att&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;class_vars_to_keep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;att&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;att&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;att&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attributes_to_keep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;att&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;att&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;metas_to_keep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;

    &lt;span class="c1"&gt;# New variables
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;att_exp&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attributes_to_expand&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;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;values_for_current_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;separator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;value_is_present&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;values_for_current_line&lt;/span&gt;
            &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;att_exp&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;"="&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value_is_present&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="c1"&gt;# making the new dataset available to linked widget
&lt;/span&gt;&lt;span class="n"&gt;out_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tips for Building Scripts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Don't copy objects such as Domain's variable from in_data to out_data. Altering in_data can cause side effects.&lt;/li&gt;
&lt;li&gt;Don't forget to &lt;em&gt;class variables&lt;/em&gt; and &lt;em&gt;metadatas&lt;/em&gt;. The information could be helpful later in your pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;print()&lt;/code&gt; debugging is your friend. There is also an interactive console that is very helpful.&lt;/li&gt;
&lt;li&gt;Some shortcuts are available &lt;code&gt;[Ctrl]-R&lt;/code&gt;: Run script, &lt;code&gt;[Ctrl]-R&lt;/code&gt;: Save script,  &lt;code&gt;[Ctrl]-/&lt;/code&gt;: Comment line ... There is also a Vim mode for the purist. 😉 &lt;/li&gt;
&lt;li&gt;Look at existing transformations before building your own&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Transforming multi-values columns into multiple attributes is &lt;strong&gt;very helpful to apply machine learning&lt;/strong&gt; algorithm to classify and do prediction based on samples data.&lt;/p&gt;

&lt;p&gt;Maybe this small script will save you some time...&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://docs.biolab.si/orange/2/widgets/rst/data/pythonscript.html"&gt;Official Orange Documentation: Python Scripting&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>datascience</category>
      <category>python</category>
      <category>orange</category>
      <category>datamining</category>
    </item>
    <item>
      <title>Security Puzzle (Log4J Edition)</title>
      <dc:creator>Philippe Arteau</dc:creator>
      <pubDate>Mon, 10 Jan 2022 16:16:00 +0000</pubDate>
      <link>https://dev.to/h3xstream/security-puzzle-log4j-edition-465f</link>
      <guid>https://dev.to/h3xstream/security-puzzle-log4j-edition-465f</guid>
      <description>&lt;p&gt;Apache Log4J has been in the spotlight for its JNDI feature introducing a major security flaw in december.&lt;/p&gt;

&lt;p&gt;Here is the function for JNDI lookups modified to avoid unexpected remote class being loaded. This function was used to fix potential RCE in version 2.15.&lt;/p&gt;

&lt;p&gt;Can you see why the validation was &lt;strong&gt;insufficient&lt;/strong&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;DirContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//javax.naming.directory.DirContext&lt;/span&gt;

&lt;span class="o"&gt;[...]&lt;/span&gt;

&lt;span class="nd"&gt;@SuppressWarnings&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unchecked"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;NamingException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;synchronized&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;NamingException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;URI&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getScheme&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;allowedProtocols&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getScheme&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Locale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ROOT&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="no"&gt;LOGGER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Log4j JNDI does not allow protocol {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getScheme&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;LDAP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getScheme&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="no"&gt;LDAPS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getScheme&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;allowedHosts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getHost&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="no"&gt;LOGGER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Attempt to access ldap server not in allowed list"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="nc"&gt;Attributes&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAttributes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// In testing the "key" for attributes seems to be lowercase while the attribute id is&lt;/span&gt;
                &lt;span class="c1"&gt;// camelcase, but that may just be true for the test LDAP used here. This copies the Attributes&lt;/span&gt;
                &lt;span class="c1"&gt;// to a Map ignoring the "key" and using the Attribute's id as the key in the Map so it matches&lt;/span&gt;
                &lt;span class="c1"&gt;// the Java schema.&lt;/span&gt;
                &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Attribute&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attributeMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
                &lt;span class="nc"&gt;NamingEnumeration&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Attribute&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;enumeration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enumeration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasMore&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;Attribute&lt;/span&gt; &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enumeration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;attributeMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getID&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="nc"&gt;Attribute&lt;/span&gt; &lt;span class="n"&gt;classNameAttr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attributeMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CLASS_NAME&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributeMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SERIALIZED_DATA&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classNameAttr&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;classNameAttr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;allowedClasses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;className&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                            &lt;span class="no"&gt;LOGGER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Deserialization of {} is not allowed"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;className&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                        &lt;span class="o"&gt;}&lt;/span&gt;
                    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="no"&gt;LOGGER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"No class name provided for {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                    &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributeMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;REFERENCE_ADDRESS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
                        &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;attributeMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;OBJECT_FACTORY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="no"&gt;LOGGER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Referenceable class is not allowed for {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;URISyntaxException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This is OK.&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lookup&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Ref: &lt;a href="https://github.com/apache/logging-log4j2/commit/d82b47c6fae9c15fcb183170394d5f1a01ac02d3#diff-271353c1076e53f6893261e4420de27d34588bfd782806b5c66a3465c43b7f51R209"&gt;Changeset&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is/are the weakness in the code above?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A) Incomplete blacklist / whitelist&lt;/li&gt;
&lt;li&gt;B) Improper URL parsing&lt;/li&gt;
&lt;li&gt;C) Unexpected Nullpointer&lt;/li&gt;
&lt;li&gt;D) Exception handling&lt;/li&gt;
&lt;li&gt;E) Time of Check, Time of Use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Answer (SPOILER!)
  &lt;blockquote&gt;
&lt;p&gt;It is both a &lt;strong&gt;TOCTOU&lt;/strong&gt; and a &lt;strong&gt;URL parsing&lt;/strong&gt; issue!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TOCTOU explanation: &lt;a href="https://www.gosecure.net/blog/2021/12/21/log4j-2-15-toctou-vulnerability-illustrated-by-gosecure-researchers/"&gt;https://www.gosecure.net/blog/2021/12/21/log4j-2-15-toctou-vulnerability-illustrated-by-gosecure-researchers/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;DNS re-parsing issue: &lt;a href="https://www.lunasec.io/docs/blog/log4j-zero-day-severity-of-cve-2021-45046-increased/"&gt;https://www.lunasec.io/docs/blog/log4j-zero-day-severity-of-cve-2021-45046-increased/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Did you identify either weakness?&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;br&gt;


</description>
      <category>security</category>
      <category>java</category>
      <category>challenge</category>
      <category>log4j</category>
    </item>
    <item>
      <title>Bypassing ModSecurity WAF</title>
      <dc:creator>Philippe Arteau</dc:creator>
      <pubDate>Thu, 21 Oct 2021 02:10:12 +0000</pubDate>
      <link>https://dev.to/h3xstream/bypassing-libinjection-waf-1jm2</link>
      <guid>https://dev.to/h3xstream/bypassing-libinjection-waf-1jm2</guid>
      <description>&lt;p&gt;Being able to bypass Web Application Firewall (WAF) depends on your knowledge about their behavior. Here is a cool technique that involve &lt;strong&gt;expressions that are ignored in MySQL SQL parser&lt;/strong&gt; (&lt;a href="https://bugs.mysql.com/bug.php?id=105143" rel="noopener noreferrer"&gt;MySQL &amp;lt;= 5.7&lt;/a&gt;). This post summarizes the impact on libinjection. The &lt;a href="https://github.com/client9/libinjection" rel="noopener noreferrer"&gt;libinjection library&lt;/a&gt; is used by WAF such as &lt;a href="https://github.com/SpiderLabs/ModSecurity" rel="noopener noreferrer"&gt;ModSecurity&lt;/a&gt; and &lt;a href="https://docs.fastly.com/signalsciences/how-it-works/" rel="noopener noreferrer"&gt;SignalScience&lt;/a&gt;. For more details on AWS Cloudfront impact, read the &lt;a href="https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/" rel="noopener noreferrer"&gt;original GoSecure article&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1bwt2caxl3q8m5d3rdc.jpg" 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%2Fs1bwt2caxl3q8m5d3rdc.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Scientific expression in MySQL
&lt;/h1&gt;

&lt;p&gt;When MySQL sees &lt;code&gt;1.e(abc)&lt;/code&gt;, it will ignore the &lt;code&gt;1.e(&lt;/code&gt; portion because the following characters do not form a valid numeric value.&lt;/p&gt;

&lt;p&gt;This behavior can be abused to fool libinjection tokenizer. Libinjection internally tokenizes the parameter and identifies contextual section types such as comments and strings. Libinjection sees the string “1.e” as an unknown SQL keyword and concludes that it is more likely to be an English sentence than code. When libinjection is &lt;a href="https://github.com/libinjection/libinjection/blob/49904c42a6e68dc8f16c022c693e897e4010a06c/src/libinjection_sqli_data.h#L8686" rel="noopener noreferrer"&gt;unaware of an SQL function&lt;/a&gt; the same behavior can be exhibited.&lt;/p&gt;

&lt;h1&gt;
  
  
  Attack in action
&lt;/h1&gt;

&lt;p&gt;Here is a demonstration of modsecurity’s capability to block a malicious pattern for SQL injection. A forbidden page is returned which is the consequence of detection.&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%2F9ie8vtjdsmyrvge560hn.gif" 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%2F9ie8vtjdsmyrvge560hn.gif" alt="SQL injection blocked"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;*Blocked!*&lt;/center&gt;

&lt;p&gt;In the following image, you can see the original request being slightly modified to bypass modsecurity and libinjection.&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%2F54colvp1kugv5i09mfzq.gif" 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%2F54colvp1kugv5i09mfzq.gif" alt="SQL injection bypass WAF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;*WAF Bypass!*&lt;/center&gt;

&lt;h2&gt;
  
  
  Complete payload
&lt;/h2&gt;

&lt;p&gt;Now, how do we go beyond &lt;code&gt;or 1=1&lt;/code&gt; payloads? The &lt;code&gt;NUMBER.e&lt;/code&gt; expression can be inserted at plenty of locations without breaking the SQL query. The following payload demonstrated read on arbitrary SQL tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;' 1.e(ascii 1.e(substring(1.e(select password from users limit 1 1.e,1 1.e) 1.e,1 1.e,1 1.e)1.e)1.e) = 70 or'1'='2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same payload was indented below for readability. &lt;code&gt;1.e(&lt;/code&gt; and &lt;code&gt;1.e,&lt;/code&gt; are ignored from the parser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.e(ascii 
1.e(substring(
1.e(select password from users limit 1 1.e,1 1.e) 1.e,1 1.e,1 1.e)1.e)1.e) = 70 #(first char = 70)
or'1'='2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Most bypass techniques evolve using special encoding to obfuscate the malicious requests (URL encoding, Unicode multibytes, XML entities, etc). This technique will work if the system behind the WAF is doing an unexpected decoding. This new technique is not encoding related. For this reason, it will be a versatile trick until most system upgrade their MySQL instances.&lt;/p&gt;

&lt;center&gt;*Full story on [GoSecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/) (More details on AWS Cloudfront)*&lt;/center&gt;

</description>
      <category>security</category>
      <category>firewall</category>
      <category>libinjection</category>
      <category>mysql</category>
    </item>
    <item>
      <title>How to solve: "Symbol is declared in module X which does not export package Y"</title>
      <dc:creator>Philippe Arteau</dc:creator>
      <pubDate>Thu, 18 Feb 2021 20:21:43 +0000</pubDate>
      <link>https://dev.to/h3xstream/how-to-solve-symbol-is-declared-in-module-x-which-does-not-export-package-y-303g</link>
      <guid>https://dev.to/h3xstream/how-to-solve-symbol-is-declared-in-module-x-which-does-not-export-package-y-303g</guid>
      <description>&lt;p&gt;If you are here, I assume that you have encounter a message like one of these.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Symbol is declared in module 'java.desktop' which does not export package 'sun.awt.image'
Symbol is declared in module 'java.xml' which does not export package 'com.sun.org.apache.xerces.internal.xni.parser'
Symbol is declared in module 'java.base' which does not export package 'sun.net.www.protocol.http'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  What is happening?
&lt;/h1&gt;

&lt;p&gt;You are accessing a class in a package that was not intended to be used by external library. The class is part of an &lt;strong&gt;internal package that is subject to change&lt;/strong&gt;. When updating the library, it is likely that it will break your application.&lt;/p&gt;

&lt;p&gt;These modules restrictions were introduce in Java 9.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Long-term fix
&lt;/h3&gt;

&lt;p&gt;If you are working on a project that has long term stability in mind, you should look for an equivalent function that is public. This may required an additional library.&lt;/p&gt;

&lt;p&gt;Here is a simple example in Kotlin where &lt;code&gt;Strings.isNullOrEmpty&lt;/code&gt; was use by accident. The function call can simply be replace by &lt;code&gt;CharSequence.isNullOrEmpty()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jdk.internal.joptsimple.internal.Strings.isNullOrEmpty&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enter your name : "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;userName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readLine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//FIX: userName.isNullOrEmpty()&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, $userName"&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;p&gt;&lt;em&gt;Example taken from &lt;a href="https://stackoverflow.com/questions/57196948/kotlin-symbol-is-declared-in-module-jdk-internal-opt-which-does-not-export-pa"&gt;stackoverflow.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  "I know what am doing"
&lt;/h1&gt;

&lt;p&gt;You may still want to use internal API regardless of the recommendation from the compiler. Here are the solution for Java and Kotlin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Java fix
&lt;/h3&gt;

&lt;p&gt;In order to still use the internal API, you will need to pass additional arguments to the compiler (&lt;code&gt;--add-exports ...&lt;/code&gt;). This can be configured in your Maven or Gradle build.&lt;/p&gt;

&lt;p&gt;Here is an example of Maven configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-compiler-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;1.9&lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;target&amp;gt;&lt;/span&gt;1.9&lt;span class="nt"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;compilerArgs&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- Few examples ... only pick the ones needed --&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.xml/com.sun.org.apache.xerces.internal.impl.dtd=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.xml/com.sun.org.apache.xerces.internal.xni.parser=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.net.www.protocol.http=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;jdk.unsupported/sun.misc=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.ssl=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.util=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/com.sun.net.ssl.internal.ssl=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.jca=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.net.util=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/jdk.internal.misc=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.internal.interfaces=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.provider.certpath=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.internal.spec=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.validator=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.action=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--add-exports&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&amp;lt;arg&amp;gt;&lt;/span&gt;java.base/sun.security.x509=ALL-UNNAMED&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/compilerArgs&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 3: Kotlin fix
&lt;/h3&gt;

&lt;p&gt;Kotlin does not have a compiler option to turn off specific module restrictions. You can however add an annotation at the beginning of your file to disable module restriction completely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;Suppress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.sun.org.apache.xerces.internal.util.SAXInputSource&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.sun.org.apache.xerces.internal.xni.parser.XMLParseException&lt;/span&gt;
&lt;span class="na"&gt;[...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;While those new module restrictions may seems drastic, they are great safe guard that will help long term maintainability. Before adding exception, take the time to investigate if you really need the internal API.&lt;/p&gt;

</description>
      <category>java</category>
      <category>module</category>
      <category>build</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Weird Unicode Behaviors </title>
      <dc:creator>Philippe Arteau</dc:creator>
      <pubDate>Tue, 04 Aug 2020 20:40:58 +0000</pubDate>
      <link>https://dev.to/h3xstream/weird-unicode-behaviors-lcc</link>
      <guid>https://dev.to/h3xstream/weird-unicode-behaviors-lcc</guid>
      <description>&lt;p&gt;So you know about Unicode codepoint and encoding (UTF-8, UTF-16), but are you aware that few standard conversions have surprising outcomes? In this short post, I'll list some of the most surprising behaviors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Case Mapping
&lt;/h2&gt;

&lt;p&gt;Case mapping is the behavior behind the uppercase and lowercase functions in your favorite language. Unexpected behaviors can sometimes lead to bugs, some of them affecting software security. &lt;/p&gt;

&lt;p&gt;While the strings &lt;code&gt;“go\u017Fecure”&lt;/code&gt; and &lt;code&gt;“gosecure”&lt;/code&gt; are not equal, a code that applies the uppercase transformation to both strings could mistakenly interpret both strings as being equal.&lt;/p&gt;

&lt;p&gt;Here is a demonstration in Python.&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;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"GO&lt;/span&gt;&lt;span class="se"&gt;\u017F&lt;/span&gt;&lt;span class="s"&gt;ECURE"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"GOSECURE"&lt;/span&gt;
&lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"GO&lt;/span&gt;&lt;span class="se"&gt;\u017F&lt;/span&gt;&lt;span class="s"&gt;ECURE"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"GOSECURE"&lt;/span&gt;
&lt;span class="bp"&gt;True&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same behavior applies to Java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"ADM\u0131N"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ADMIN"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This behavior occurs because the characters &lt;code&gt;ı (U+0131)&lt;/code&gt; and &lt;code&gt;ſ (U+017F)&lt;/code&gt; are converted to an ASCII characters as part of Unicode specification. Aside from a few exceptions, you can assume that your language apply these transformation by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Normalization
&lt;/h2&gt;

&lt;p&gt;The purpose of normalization is to simplify expressions to allow matching equal or equivalent “meaning”.&lt;/p&gt;

&lt;p&gt;Here is a demonstration using normalization functions in Ruby. The five unicode characters become six unicode characters (ASCII only).&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;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;003&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="s2"&gt;216E&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="s2"&gt;32CE&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="s2"&gt;FF0E&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="s2"&gt;209C&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="s2"&gt;2134"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unicode_normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:nfkc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"DeV.to"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;API can sometimes hide those transformations. For example in C#, the class Uri normalize the hostname from URI entered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://faceboo\u212A.com"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"facebook.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a &lt;a href="https://www.gosecure.net/blog/2020/08/04/unicode-for-security-professionals/"&gt;list of APIs with such behavior (see Section &lt;strong&gt;Auditing Source Code&lt;/strong&gt;)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing your application
&lt;/h2&gt;

&lt;p&gt;If you have an application that susceptible to issues related to Unicode, you can use &lt;a href="https://gosecure.github.io/unicode-pentester-cheatsheet/"&gt;this simple cheat sheet&lt;/a&gt;.&lt;br&gt;
This cheat sheet can be used by developers to build regression test cases to make sure no characters are being misinterpreted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n8u12vQz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wlbocnjj5ong7hg41z2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n8u12vQz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wlbocnjj5ong7hg41z2l.png" alt="Unicode Cheat sheet" width="880" height="618"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you are curious, you can read the &lt;a href="https://www.gosecure.net/blog/2020/08/04/unicode-for-security-professionals/"&gt;full article&lt;/a&gt; with a security focus.&lt;/p&gt;

</description>
      <category>unicode</category>
      <category>testing</category>
      <category>security</category>
    </item>
  </channel>
</rss>
