<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[toolexo.net]]></title><description><![CDATA[toolexo.net]]></description><link>https://toolexo.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>toolexo.net</title><link>https://toolexo.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 18 Sep 2026 00:18:22 GMT</lastBuildDate><atom:link href="https://toolexo.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Percentage Difference Between Two Measurements]]></title><description><![CDATA[# Percentage Difference Between Two Measurements

Two measurements can differ by 5 units, but that number alone does not tell you whether the gap is trivial or large.

A 5 mm difference matters a lot ]]></description><link>https://toolexo.hashnode.dev/percentage-difference-between-two-measurements</link><guid isPermaLink="true">https://toolexo.hashnode.dev/percentage-difference-between-two-measurements</guid><category><![CDATA[data analysis]]></category><category><![CDATA[statistics]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Mathematics]]></category><dc:creator><![CDATA[郭雪林]]></dc:creator><pubDate>Wed, 16 Sep 2026 03:54:43 GMT</pubDate><content:encoded><![CDATA[<pre><code class="language-markdown"># Percentage Difference Between Two Measurements

Two measurements can differ by 5 units, but that number alone does not tell you whether the gap is trivial or large.

A 5 mm difference matters a lot when two parts are 10 mm and 15 mm. It matters far less when they are 1,000 mm and 1,005 mm. Percentage difference puts the gap in context.

The catch is that several formulas are called "percentage difference." The correct one depends on whether either value is a known baseline.

## Start with the question

Use percentage difference when you have two comparable measurements and neither should automatically be treated as the original, expected, or correct value.

For two positive measurements `A` and `B`, a common symmetric formula is:

```text
Percentage difference =
|A - B| ÷ ((A + B) ÷ 2) × 100
</code></pre>
<p>The numerator is the absolute difference. The denominator is the average of the two measurements.</p>
<p>NIST documents this average-based formula as one supported definition of percent difference. It also documents a maximum-based alternative, which is a useful reminder that the denominator must be stated when the result matters. <a href="https://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/percdif.htm">NIST: PERCDIF</a></p>
<h2>Worked example</h2>
<p>Suppose two instruments report the length of the same component:</p>
<pre><code class="language-text">Measurement A = 48 mm
Measurement B = 52 mm
</code></pre>
<p>First, find the absolute difference:</p>
<pre><code class="language-text">|48 - 52| = 4 mm
</code></pre>
<p>Then find the average measurement:</p>
<pre><code class="language-text">(48 + 52) ÷ 2 = 50 mm
</code></pre>
<p>Finally:</p>
<pre><code class="language-text">4 ÷ 50 × 100 = 8%
</code></pre>
<p>The two measurements differ by 8% using the average-based formula.</p>
<p>The calculation is symmetric. Switching the labels does not change the answer:</p>
<pre><code class="language-text">48 vs. 52 = 8%
52 vs. 48 = 8%
</code></pre>
<p>That symmetry is why this method works well when neither measurement is the obvious baseline.</p>
<h2>Percentage difference is not percentage change</h2>
<p>If one value is a baseline, use percentage change instead.</p>
<p>For example, if a process time changes from 48 seconds to 52 seconds:</p>
<pre><code class="language-text">Percentage change =
(new - old) ÷ old × 100
</code></pre>
<pre><code class="language-text">(52 - 48) ÷ 48 × 100 = 8.33%
</code></pre>
<p>This answer is different from the 8% percentage difference because it answers a different question.</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>Formula</th>
<th>Example result</th>
</tr>
</thead>
<tbody><tr>
<td>How far apart are 48 and 52, treating them equally?</td>
<td>`</td>
<td>A - B</td>
</tr>
<tr>
<td>How much did a value rise from 48 to 52?</td>
<td><code>(new - old) ÷ old × 100</code></td>
<td>8.33%</td>
</tr>
<tr>
<td>How far is a result from a known reference?</td>
<td><code>(observed - reference) ÷ reference × 100</code></td>
<td>depends on reference</td>
</tr>
</tbody></table>
<p>Do not label a percentage change as a percentage difference without naming the baseline. The missing baseline is where confusion begins.</p>
<h2>A practical software example</h2>
<p>Imagine two builds of the same API endpoint:</p>
<pre><code class="language-text">Build A median response time: 120 ms
Build B median response time: 150 ms
</code></pre>
<p>If you are comparing the builds as two peer measurements:</p>
<pre><code class="language-text">|120 - 150| ÷ ((120 + 150) ÷ 2) × 100
= 30 ÷ 135 × 100
= 22.22%
</code></pre>
<p>The measurements differ by about 22.22%.</p>
<p>If Build A is the accepted baseline and Build B is the new deployment, the more useful question is usually percentage change:</p>
<pre><code class="language-text">(150 - 120) ÷ 120 × 100 = 25%
</code></pre>
<p>That tells you the new build is 25% slower relative to the previous one.</p>
<p>The math is easy. Choosing the right interpretation is the real job.</p>
<h2>When the formula is useful</h2>
<p>Percentage difference is often useful for:</p>
<ul>
<li><p>comparing two manual measurements of the same quantity;</p>
</li>
<li><p>checking whether two sensors report similar values;</p>
</li>
<li><p>comparing independent estimates;</p>
</li>
<li><p>reviewing a calculated result against a separate calculation;</p>
</li>
<li><p>comparing two implementation benchmarks when neither is the baseline.</p>
</li>
</ul>
<p>It is less useful when the values describe different populations, different units, or different definitions.</p>
<p>For example, do not calculate percentage difference between:</p>
<ul>
<li><p>20% conversion rate and 20% profit margin;</p>
</li>
<li><p>5 kilograms and 5 pounds;</p>
</li>
<li><p>a monthly average and a single-day measurement;</p>
</li>
<li><p>two values produced under materially different test conditions.</p>
</li>
</ul>
<p>Convert units, align the population and time range, and document the measurement method before comparing values.</p>
<h2>What happens near zero?</h2>
<p>The average-based formula becomes unstable when both values are close to zero.</p>
<p>Consider:</p>
<pre><code class="language-text">A = 0.01
B = 0.03
</code></pre>
<p>The absolute difference is only <code>0.02</code>, but the percentage difference is:</p>
<pre><code class="language-text">0.02 ÷ 0.02 × 100 = 100%
</code></pre>
<p>That is mathematically correct under this formula. It may still be a poor way to communicate practical importance.</p>
<p>If both values are zero, the denominator is zero and percentage difference is undefined. If one or both values can be negative, decide whether a relative comparison is meaningful before applying a generic formula.</p>
<p>In engineering, laboratory, financial, and safety-critical work, report the raw difference and units alongside any percentage. A percentage alone can hide the scale of the measurement.</p>
<h2>Percentage points are different again</h2>
<p>If the values are already percentages, distinguish percentage difference from percentage points.</p>
<p>Suppose one rate is 40% and another is 50%:</p>
<pre><code class="language-text">Difference in percentage points = 50% - 40% = 10 percentage points
</code></pre>
<p>The relative increase from 40% to 50% is:</p>
<pre><code class="language-text">(50% - 40%) ÷ 40% × 100 = 25%
</code></pre>
<p>The average-based percentage difference is:</p>
<pre><code class="language-text">|40% - 50%| ÷ ((40% + 50%) ÷ 2) × 100
= 22.22%
</code></pre>
<p>All three results are valid calculations. They are not interchangeable.</p>
<p>Use percentage points when comparing rates directly. Use percentage change when one rate is a baseline. Use percentage difference when you are treating two comparable values symmetrically.</p>
<h2>A quick checking workflow</h2>
<p>Before reporting a percentage difference:</p>
<ol>
<li><p>Confirm that both values measure the same thing.</p>
</li>
<li><p>Confirm that they use the same unit and comparable conditions.</p>
</li>
<li><p>Decide whether one value is a baseline.</p>
</li>
<li><p>Use percentage difference only when neither value should dominate.</p>
</li>
<li><p>State the formula or denominator used.</p>
</li>
<li><p>Report the raw difference and units as well.</p>
</li>
<li><p>Flag zero and near-zero values instead of forcing a misleading percentage.</p>
</li>
</ol>
<p>You can use ToolExo's <a href="https://toolexo.net/percentage-calculator/">Percentage Calculator</a> to check the arithmetic, then document which interpretation applies to the decision you are making.</p>
<h2>The short version</h2>
<p>Percentage difference answers: "How far apart are these two comparable measurements?"</p>
<p>Percentage change answers: "How much did this value change from a known starting point?"</p>
<p>Pick the question first. Then choose the denominator that makes the result honest.</p>
<h2>Sources</h2>
<ul>
<li><p><a href="https://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/percdif.htm">NIST Dataplot: Percent Difference</a></p>
</li>
<li><p><a href="https://itl.nist.gov/div898/software/dataplot/refman2/auxillar/diperc.htm">NIST Dataplot: ISO 13528 Percentage Difference Score</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Average Percentages Without Ignoring Their Denominators]]></title><description><![CDATA[# How to Average Percentages Without Ignoring Their Denominators

A percentage is a ratio, not a standalone number.

That sounds obvious, but it is the reason simple averages often produce misleading ]]></description><link>https://toolexo.hashnode.dev/how-to-average-percentages-without-ignoring-their-denominators</link><guid isPermaLink="true">https://toolexo.hashnode.dev/how-to-average-percentages-without-ignoring-their-denominators</guid><category><![CDATA[Mathematics]]></category><category><![CDATA[statistics]]></category><category><![CDATA[data analysis]]></category><category><![CDATA[education]]></category><dc:creator><![CDATA[郭雪林]]></dc:creator><pubDate>Sat, 12 Sep 2026 04:41:08 GMT</pubDate><content:encoded><![CDATA[<pre><code class="language-markdown"># How to Average Percentages Without Ignoring Their Denominators

A percentage is a ratio, not a standalone number.

That sounds obvious, but it is the reason simple averages often produce misleading dashboards, reports, grades, and conversion summaries. If one percentage comes from 10 observations and another comes from 10,000, treating them as equal can badly distort the result.

The practical rule is:

&gt; Average percentages directly only when they have equal denominators or when you deliberately want to give each percentage equal weight.

Otherwise, reconstruct the underlying counts and calculate one percentage from the combined total.

## The tempting calculation that can be wrong

Suppose two landing pages have these conversion rates:

| Landing page | Conversions | Visitors | Conversion rate |
| --- | ---: | ---: | ---: |
| A | 9 | 10 | 90% |
| B | 50 | 100 | 50% |

A simple average says:

```text
(90% + 50%) ÷ 2 = 70%
</code></pre>
<p>That answer gives each landing page equal influence. It does not give each visitor equal influence.</p>
<p>The combined result is:</p>
<pre><code class="language-text">Total conversions = 9 + 50 = 59
Total visitors = 10 + 100 = 110

Combined conversion rate = 59 ÷ 110 × 100
                         = 53.64%
</code></pre>
<p>The 70% figure answers a different question: "What is the average rate across two equally weighted pages?" The 53.64% figure answers: "What percentage of all visitors converted?"</p>
<p>For a site-wide conversion rate, the second question is usually the one that matters.</p>
<h2>Use the combined numerator and denominator</h2>
<p>When each percentage has the form:</p>
<pre><code class="language-text">percentage = numerator ÷ denominator × 100
</code></pre>
<p>the combined percentage is:</p>
<pre><code class="language-text">combined percentage =
(sum of numerators ÷ sum of denominators) × 100
</code></pre>
<p>For several groups:</p>
<pre><code class="language-text">combined percentage =
(n₁ + n₂ + ... + nₖ) ÷ (d₁ + d₂ + ... + dₖ) × 100
</code></pre>
<p>where:</p>
<ul>
<li><p><code>n</code> is the count represented by the percentage;</p>
</li>
<li><p><code>d</code> is its denominator, such as visitors, orders, students, bytes, or tests;</p>
</li>
<li><p>each numerator must be part of the corresponding denominator.</p>
</li>
</ul>
<p>This is equivalent to a weighted average where the denominators are the weights. NIST gives the general weighted-mean formula as the sum of each value times its weight, divided by the sum of weights. <a href="https://www.itl.nist.gov/div898/software/dataplot/refman2/ch2/weigmean.pdf">NIST: weighted mean</a></p>
<h2>When a simple average is correct</h2>
<p>A plain average is not always a mistake.</p>
<p>It is appropriate when every percentage should carry the same weight, regardless of its denominator.</p>
<p>For example, imagine a course grade with three equally weighted categories:</p>
<table>
<thead>
<tr>
<th>Category</th>
<th>Score</th>
<th>Weight</th>
</tr>
</thead>
<tbody><tr>
<td>Assignments</td>
<td>80%</td>
<td>1</td>
</tr>
<tr>
<td>Project</td>
<td>90%</td>
<td>1</td>
</tr>
<tr>
<td>Presentation</td>
<td>70%</td>
<td>1</td>
</tr>
</tbody></table>
<pre><code class="language-text">(80% + 90% + 70%) ÷ 3 = 80%
</code></pre>
<p>That is correct because the grading rule explicitly gives each category equal weight.</p>
<p>It is also correct when denominators are equal. If two surveys each include 100 respondents, averaging their percentages gives the same result as combining their counts.</p>
<p>Before calculating, ask one question:</p>
<blockquote>
<p>Should each group count equally, or should each underlying observation count equally?</p>
</blockquote>
<p>That choice determines the formula.</p>
<h2>A grade example with unequal weights</h2>
<p>Now consider a course with this grading policy:</p>
<table>
<thead>
<tr>
<th>Category</th>
<th>Score</th>
<th>Course weight</th>
</tr>
</thead>
<tbody><tr>
<td>Homework</td>
<td>92%</td>
<td>20%</td>
</tr>
<tr>
<td>Midterm</td>
<td>75%</td>
<td>30%</td>
</tr>
<tr>
<td>Final exam</td>
<td>80%</td>
<td>50%</td>
</tr>
</tbody></table>
<p>The correct calculation is:</p>
<pre><code class="language-text">92% × 0.20 = 18.4%
75% × 0.30 = 22.5%
80% × 0.50 = 40.0%

Final grade = 18.4% + 22.5% + 40.0%
            = 80.9%
</code></pre>
<p>Here, the category weights are not denominators. They are an explicit policy decision. The weighted-average structure is still the same, but the weights come from the syllabus rather than raw counts.</p>
<h2>Do not average percentages with incompatible meanings</h2>
<p>Sometimes neither a simple average nor a weighted average is meaningful.</p>
<p>Do not combine percentages when the underlying definitions differ. Examples include:</p>
<ul>
<li><p>a conversion rate based on visitors and a conversion rate based on sessions;</p>
</li>
<li><p>an email open rate and a click-through rate;</p>
</li>
<li><p>a tax rate and a discount rate;</p>
</li>
<li><p>two survey results that use different questions or populations;</p>
</li>
<li><p>a gross-margin percentage and a net-margin percentage.</p>
</li>
</ul>
<p>The arithmetic may work, but the result may not describe anything useful.</p>
<p>Write down the numerator, denominator, population, time range, and definition for every rate before combining it. If they do not match, report them separately or redesign the metric.</p>
<h2>Percentage points are not percent changes</h2>
<p>This is another common source of bad summaries.</p>
<p>If a rate rises from 2% to 3%, it increased by:</p>
<pre><code class="language-text">3% - 2% = 1 percentage point
</code></pre>
<p>Relative to the original 2%, it increased by:</p>
<pre><code class="language-text">(3% - 2%) ÷ 2% × 100 = 50%
</code></pre>
<p>Both statements are mathematically correct. They answer different questions.</p>
<p>Use percentage points when comparing rates directly. Use relative percentage change when you want to describe change relative to the original value. Do not average the two concepts together.</p>
<h2>What if you only know the percentages?</h2>
<p>If you know only that one group had a 90% rate and another had a 50% rate, you cannot calculate their overall rate unless you also know the denominators or the intended weights.</p>
<p>The overall rate could be close to 90%, close to 50%, or somewhere between them. It depends on the group sizes.</p>
<p>In that situation, do not invent an overall percentage. You can:</p>
<ol>
<li><p>request the underlying counts;</p>
</li>
<li><p>state that the simple average assumes equal group weight;</p>
</li>
<li><p>keep the rates separate;</p>
</li>
<li><p>report a weighted result only when the weights are documented.</p>
</li>
</ol>
<h2>A quick workflow for reports and dashboards</h2>
<p>Before publishing an average percentage:</p>
<ol>
<li><p>Write every percentage as a numerator and denominator.</p>
</li>
<li><p>Confirm that the groups measure the same thing over compatible periods.</p>
</li>
<li><p>Decide whether observations or groups should have equal influence.</p>
</li>
<li><p>Sum counts when observations should have equal influence.</p>
</li>
<li><p>Use documented weights when a policy assigns them.</p>
</li>
<li><p>Label the result clearly: combined rate, equally weighted average, or weighted score.</p>
</li>
<li><p>Keep enough detail for someone else to reproduce the result.</p>
</li>
</ol>
<p>For a quick check of percentage differences, reversals, and related calculations, use ToolExo's <a href="https://toolexo.net/percentage-calculator/">Percentage Calculator</a>. For a weighted average, first make the weights explicit rather than treating a list of percentages as interchangeable.</p>
<h2>The short version</h2>
<p>You can directly average percentages when their denominators are equal or when equal group weighting is the intended rule.</p>
<p>When group sizes differ and you need one overall rate, add the numerators, add the denominators, and divide once. That keeps the result tied to the people, items, visits, or observations the percentage is supposed to represent.</p>
<h2>Sources</h2>
<ul>
<li><p><a href="https://www.itl.nist.gov/div898/software/dataplot/refman2/ch2/weigmean.pdf">NIST: Weighted Mean</a></p>
</li>
<li><p><a href="https://openstax.org/books/principles-finance/pages/13-1-measures-of-center">OpenStax: Measures of Center and Weighted Mean</a></p>
</li>
<li><p><a href="https://openstax.org/books/contemporary-mathematics/pages/6-1-understanding-percent">OpenStax: Understanding Percent</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Double decoding URLs: bugs between proxy and app]]></title><description><![CDATA[# Double decoding URLs: the bug hiding between your proxy and app

**Subtitle:** A percent-encoded value can become a different value after a second decode. That matters when validation and routing ha]]></description><link>https://toolexo.hashnode.dev/double-decoding-urls-bugs-between-proxy-and-app</link><guid isPermaLink="true">https://toolexo.hashnode.dev/double-decoding-urls-bugs-between-proxy-and-app</guid><category><![CDATA[Web Security]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[backend]]></category><category><![CDATA[api]]></category><category><![CDATA[url]]></category><dc:creator><![CDATA[郭雪林]]></dc:creator><pubDate>Fri, 11 Sep 2026 14:24:41 GMT</pubDate><content:encoded><![CDATA[<pre><code class="language-markdown"># Double decoding URLs: the bug hiding between your proxy and app

**Subtitle:** A percent-encoded value can become a different value after a second decode. That matters when validation and routing happen in different layers.

**Tags:** web-security, javascript, backend, api, url

Percent encoding looks simple until the same value crosses a proxy, framework, middleware, and application handler.

A URL component may contain `%2F`, the percent-encoded form of `/`. Decode it once and it becomes a slash. Encode the percent sign itself first, and `%2F` becomes `%252F`. After one decode, it is still the three-character string `%2F`. After a second decode, it becomes `/`.

That second step can change meaning.

[RFC 3986](https://www.rfc-editor.org/info/rfc3986/) treats characters such as `/`, `?`, `#`, and `&amp;` as reserved because they can delimit parts of a URI. Decoding one of those characters is not cosmetic normalization. It can change how a router, authorization check, cache key, or file lookup interprets the request.

## The bug is usually a disagreement between layers

Consider a download endpoint that accepts a path-like value:

```text
GET /download?file=reports%252F2026.csv
</code></pre>
<p>Suppose the query parser decodes it once:</p>
<pre><code class="language-text">reports%2F2026.csv
</code></pre>
<p>A validation function sees no literal slash and accepts it. Later, another helper calls <code>decodeURIComponent()</code> before joining the value to a directory:</p>
<pre><code class="language-text">reports/2026.csv
</code></pre>
<p>The validator approved one representation. The file operation used another.</p>
<p>The risk is larger with path traversal input:</p>
<pre><code class="language-text">%252E%252E%252Fsecrets.txt
</code></pre>
<p>One decode produces:</p>
<pre><code class="language-text">%2E%2E%2Fsecrets.txt
</code></pre>
<p>A second decode produces:</p>
<pre><code class="language-text">../secrets.txt
</code></pre>
<p>OWASP documents double encoding as a way to bypass filters that inspect input before a later layer decodes it again. The technique can affect traversal checks, redirect validation, and output handling. <a href="https://owasp.org/www-community/Double_Encoding">OWASP: Double Encoding</a></p>
<h2>Decide who owns decoding</h2>
<p>Every request path should have an explicit representation boundary:</p>
<ol>
<li><p>Raw request target or raw form body.</p>
</li>
<li><p>Parsed query, route parameter, or form field.</p>
</li>
<li><p>Validated application value.</p>
</li>
<li><p>Context-specific use, such as a database lookup or generated URL.</p>
</li>
</ol>
<p>The key rule is simple: decode once for each documented format boundary, then validate the same representation that the sensitive operation will use.</p>
<p>That does not mean "never decode twice" in every situation. A URL can legitimately contain another URL as a query parameter. In that case, parse the outer URL first, then treat the extracted inner value as a separate URL with its own parsing and allowlist rules.</p>
<p>What causes trouble is repeatedly decoding one untyped string until it looks readable.</p>
<h2>Do not add a second decode because a percent sign remains</h2>
<p>A remaining <code>%</code> is not proof that something is broken.</p>
<p>For example, a system may intentionally store <code>%2F</code> as data, or an outer URL may contain an encoded inner URL. Calling <code>decodeURIComponent()</code> again without understanding the format changes the value and may create a delimiter that did not exist at the validation boundary.</p>
<p>The same caution applies to framework helpers. Some routers and query parsers already return decoded values. Before decoding a route parameter or a parsed query value manually, verify whether the framework has already done it.</p>
<p>Malformed sequences should also fail visibly. In JavaScript, <code>decodeURIComponent()</code> throws a <code>URIError</code> for invalid percent escapes or invalid UTF-8 sequences. Catch that error and return a clear client error rather than silently repairing the value. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Malformed_URI">MDN: malformed URI sequence</a></p>
<pre><code class="language-ts">function decodeOneComponent(raw: string): string {
  try {
    return decodeURIComponent(raw);
  } catch {
    throw new Error("Invalid percent-encoded input");
  }
}
</code></pre>
<p>Use a function like this only when <code>raw</code> is known to be an encoded component. Do not pass an already-parsed route value to it by habit.</p>
<h2>Validate for the destination, not for appearance</h2>
<p>URL decoding is not a security control by itself. The final validation must match the destination.</p>
<p>For a file identifier, use an allowlist grammar such as:</p>
<pre><code class="language-text">^[A-Za-z0-9._-]+$
</code></pre>
<p>Then resolve the final path with platform path APIs and verify that the resolved path remains inside the intended directory.</p>
<p>For redirects, parse the final URL and allow only approved origins. A string check such as <code>startsWith("https://example.com")</code> is not enough.</p>
<p>For generated links, encode the individual query value or path segment. Do not encode an entire URL after assembling it, because that can escape structural delimiters that need to remain structural.</p>
<h2>A small test set catches most ownership mistakes</h2>
<p>Add tests that preserve both the raw input and the value at each boundary:</p>
<table>
<thead>
<tr>
<th>Raw input</th>
<th>Expected after one decode</th>
<th>Why it matters</th>
</tr>
</thead>
<tbody><tr>
<td><code>hello%20world</code></td>
<td><code>hello world</code></td>
<td>ordinary space</td>
</tr>
<tr>
<td><code>a%2Bb</code></td>
<td><code>a+b</code></td>
<td>literal plus</td>
</tr>
<tr>
<td><code>%252F</code></td>
<td><code>%2F</code></td>
<td>nested encoding</td>
</tr>
<tr>
<td><code>%252E%252E%252F</code></td>
<td><code>%2E%2E%2F</code></td>
<td>traversal probe</td>
</tr>
<tr>
<td><code>%</code></td>
<td>error</td>
<td>malformed escape</td>
</tr>
<tr>
<td><code>%E0%A4%A</code></td>
<td>error</td>
<td>malformed UTF-8</td>
</tr>
</tbody></table>
<p>When a production bug appears, log the representation safely at each owned boundary. Avoid logging secrets, tokens, or personal data. The useful question is not "what did the input look like?" It is "which layer turned it into the value used by the application?"</p>
<p>For a quick local check of one decode pass, you can use ToolExo's <a href="https://toolexo.net/url-encoder/">URL Encoder &amp; Decoder</a>. It keeps the conversion in the browser and is useful for comparing component and form-style encoding.</p>
<h2>Keep the rule boring</h2>
<p>Most URL decoding bugs come from unclear ownership, not exotic encoding.</p>
<p>Name the boundary. Decode once at that boundary. Validate the resulting value for its actual destination. Then pass typed, validated data forward instead of another string that a later helper may decode again.</p>
<p>That approach makes <code>%252F</code> less mysterious. More importantly, it makes the authorization check and the final operation agree on what the request means.</p>
]]></content:encoded></item></channel></rss>