<?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: Manumattam</title>
    <description>The latest articles on DEV Community by Manumattam (@manumattam).</description>
    <link>https://dev.to/manumattam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F99mvlsfu5tfj9m7ku25d.png</url>
      <title>DEV Community: Manumattam</title>
      <link>https://dev.to/manumattam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manumattam"/>
    <language>en</language>
    <item>
      <title>Why Drawing a Black Box on a PDF Doesn't Redact It (And How I Built a True Client-Side PDF Redactor with Canvas &amp; WebAssembly)</title>
      <dc:creator>Manumattam</dc:creator>
      <pubDate>Fri, 06 Nov 2026 18:01:34 +0000</pubDate>
      <link>https://dev.to/manumattam/why-drawing-a-black-box-on-a-pdf-doesnt-redact-it-and-how-i-built-a-true-client-side-pdf-redactor-4ok4</link>
      <guid>https://dev.to/manumattam/why-drawing-a-black-box-on-a-pdf-doesnt-redact-it-and-how-i-built-a-true-client-side-pdf-redactor-4ok4</guid>
      <description>&lt;p&gt;One of the most common document security mistakes on the web is "black-box PDF redaction."&lt;/p&gt;

&lt;p&gt;When people need to hide an Aadhaar number, PAN, SSN, or bank account balance on a PDF, they often open a free online PDF editor, draw a black rectangle over the text, and hit save.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem: The Text Stream Is Still There
&lt;/h3&gt;

&lt;p&gt;In the PDF specification (ISO 32000), drawing a rectangle annotation or vector path over existing text only changes the visual stacking order (z-index). The original &lt;code&gt;BT ... ET&lt;/code&gt; text object remains untouched in the underlying content stream. Anyone who opens the PDF can simply press &lt;code&gt;Ctrl+A&lt;/code&gt;, &lt;code&gt;Ctrl+C&lt;/code&gt;, and paste the "redacted" text into Notepad.&lt;/p&gt;

&lt;p&gt;Even worse, using a traditional online PDF tool means uploading your unredacted confidential document to a third-party server first.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I Solved Both in the Browser
&lt;/h3&gt;

&lt;p&gt;While building &lt;strong&gt;&lt;a href="https://sahuliyat.com" rel="noopener noreferrer"&gt;Sahuliyat&lt;/a&gt;&lt;/strong&gt; (a privacy-first platform of 46 client-side tools), I wanted to build a &lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/pdf-redactor" rel="noopener noreferrer"&gt;PDF Redactor&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/unlock-pdf" rel="noopener noreferrer"&gt;PDF Unlocker&lt;/a&gt;&lt;/strong&gt; where &lt;strong&gt;0 bytes&lt;/strong&gt; ever leave the user's browser.&lt;/p&gt;

&lt;p&gt;Here is the client-side pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Local Rendering via &lt;code&gt;pdfjs-dist&lt;/code&gt;:&lt;/strong&gt; Each PDF page is parsed locally in a Web Worker and rendered at high DPI onto an HTML5 &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pixel-Buffer Destruction:&lt;/strong&gt; When you draw redaction boxes over sensitive areas, those coordinates are burned directly into the 2D canvas bitmap—overwriting the original RGB pixels completely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flattened Reconstruction via &lt;code&gt;pdf-lib&lt;/code&gt;:&lt;/strong&gt; The modified canvas frames are exported and assembled into a fresh PDF document with zero underlying text streams or metadata left behind.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local AES-256 Encryption / Decryption via QPDF WebAssembly:&lt;/strong&gt; For &lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/unlock-pdf" rel="noopener noreferrer"&gt;Unlock PDF&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/protect-pdf" rel="noopener noreferrer"&gt;Protect PDF&lt;/a&gt;&lt;/strong&gt;, we run &lt;code&gt;@neslinesli93/qpdf-wasm&lt;/code&gt; inside a Web Worker so passwords and financial PDFs never touch the network.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Try It Out (Open Your DevTools Network Tab!)
&lt;/h3&gt;

&lt;p&gt;You can test the full suite here: &lt;strong&gt;&lt;a href="https://sahuliyat.com" rel="noopener noreferrer"&gt;https://sahuliyat.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alongside the PDF &amp;amp; image privacy tools, it also includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/pdf-compressor" rel="noopener noreferrer"&gt;PDF Compressor&lt;/a&gt;&lt;/strong&gt; &amp;amp; &lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/merge-pdf" rel="noopener noreferrer"&gt;Merge PDF&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/image-metadata-remover" rel="noopener noreferrer"&gt;Image EXIF Metadata Remover&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/json-formatter" rel="noopener noreferrer"&gt;JSON Formatter&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/cron-expression-parser" rel="noopener noreferrer"&gt;Cron Expression Parser&lt;/a&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/text-diff-checker" rel="noopener noreferrer"&gt;Text Diff Checker&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/income-tax-estimator" rel="noopener noreferrer"&gt;Income Tax Calculator (AY 2026-27)&lt;/a&gt;&lt;/strong&gt; &amp;amp; &lt;strong&gt;&lt;a href="https://sahuliyat.com/tools/loan-prepayment-calculator" rel="noopener noreferrer"&gt;Home Loan Prepayment Calculator&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Would love feedback from fellow developers on the WebAssembly worker architecture and UX!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
