A team building a financial reporting system chose Haukcode.DinkToPdf for its simplicity and zero licensing cost. Six months into production, a security audit flags CVE-2022-35583—a critical SSRF vulnerability in wkhtmltopdf with CVSS score 9.8. The vendor confirms the risk: malicious HTML can force the server to access internal network resources or local files. The wkhtmltopdf project archived in January 2023, so no patch exists. The team now faces a choice: accept the security risk, rebuild the entire reporting system with a different library, or implement extensive input sanitization that may still miss edge cases.
This scenario plays out repeatedly: teams adopt DinkToPdf/Haukcode.DinkToPdf for its straightforward API and free licensing, then discover the underlying wkhtmltopdf binary carries an unfixable critical vulnerability. The library itself is unmaintained—Haukcode.DinkToPdf package is deprecated on NuGet, and the original DinkToPdf stopped receiving updates in 2017.
Understanding IronPDF
IronPDF uses a Chromium rendering engine maintained and updated with browser security patches. Where Haukcode.DinkToPdf wraps an archived binary (wkhtmltopdf 0.12.6 from 2020), IronPDF's rendering engine receives ongoing updates. The architectural difference affects both security posture and rendering capabilities.
The ChromePdfRenderer class provides an API similar to DinkToPdf's converter pattern but without requiring manual native binary deployment or version management. Teams migrating from Haukcode.DinkToPdf typically find the code changes minimal, but the operational benefits—no manual binary management, no critical vulnerabilities—substantial.
Key Limitations of Haukcode.DinkToPdf
Product Status: Deprecated on NuGet with warning "no longer maintained." Haukcode.DinkToPdf was itself a continuation of DinkToPdf which stopped in 2017. The underlying wkhtmltopdf project archived in January 2023 with last release 0.12.6 in 2020. No future updates or security patches possible. GitHub issues and pull requests go unanswered.
Missing Capabilities: Rendering engine based on QtWebKit which stopped development in 2012—predates modern CSS Grid, Flexbox improvements, and many CSS3 features. JavaScript execution limited to basic DOM manipulation—modern frameworks (React, Vue, Angular) don't work. Web font loading unreliable. SVG support limited. No built-in async operations—all conversions block calling thread. No built-in multi-threading safety—requires manual converter synchronization.
Technical Issues: wkhtmltopdf native binary (~40MB) requires manual deployment to application directory or system PATH. Platform-specific binaries needed (Windows .dll, Linux .so) with correct permissions. Thread safety issues require SynchronizedConverter wrapper and careful resource management. Memory leaks common when converter not properly disposed. Docker deployments require adding ~15 packages (libfontconfig, libfreetype, libx11, etc.). Frequent segmentation faults in native code that can crash entire process.
Support Status: No support available—project unmaintained. Community forums (Stack Overflow) show questions going unanswered. Forked versions exist but also unmaintained. Documentation consists of README and scattered blog posts from 2017-2019. No migration path to newer technology provided by maintainers.
Architecture Problems: P/Invoke wrapper means all HTML processing happens in unmanaged native code—debugging extremely difficult. Process crashes from wkhtmltopdf binary take down entire application. No graceful degradation for unsupported CSS—either renders or crashes. File permissions on Linux frequently cause "library not found" errors. Environment variables (LD_LIBRARY_PATH) often required on Linux.
Security Issues: CVE-2022-35583 (CVSS 9.8 Critical) - Server-Side Request Forgery vulnerability allows attackers to:
- Access internal network services via malicious HTML
- Read local files using file:// protocol
- Scan internal networks
- Bypass firewall restrictions
- NO FIX AVAILABLE - wkhtmltopdf archived, will never be patched
Feature Comparison Overview
| Feature | Haukcode.DinkToPdf | IronPDF |
|---|---|---|
| Current Status | Deprecated/Unmaintained | Active |
| HTML Support | QtWebKit (2012) | Chromium (current) |
| Rendering Quality | Limited modern CSS | Pixel-perfect Chrome |
| Installation | NuGet + manual binary | NuGet only |
| Support | None | Standard included |
| Security | Critical CVE unfixable | Regular security updates |
Code Comparison & Performance
Haukcode.DinkToPdf — Basic HTML Rendering
using System;
using System.IO;
using DinkToPdf;
using DinkToPdf.Contracts;
namespace DinkToPdfExample
{
class Program
{
static void Main(string[] args)
{
// SECURITY WARNING: CVE-2022-35583 - Do not use in production
// Malicious HTML can exploit SSRF vulnerability
// Must manually deploy wkhtmltopdf binary to:
// Windows: bin/Debug/net6.0/libwkhtmltox.dll
// Linux: /usr/lib/libwkhtmltox.so (or set LD_LIBRARY_PATH)
try
{
// Create converter
// BasicConverter for single-threaded use
// SynchronizedConverter for multi-threaded (but still has issues)
var converter = new BasicConverter(new PdfTools());
// Configure document
var doc = new HtmlToPdfDocument
{
GlobalSettings = new GlobalSettings
{
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
Margins = new MarginSettings
{
Top = 10,
Bottom = 10,
Left = 10,
Right = 10
}
},
Objects =
{
new ObjectSettings
{
HtmlContent = @"
<html>
<head><style>body { font-family: Arial; }</style></head>
<body><h1>Hello from DinkToPdf</h1></body>
</html>"
}
}
};
// Convert - blocks calling thread
byte[] pdfBytes = converter.Convert(doc);
// Save to file
File.WriteAllBytes("output.pdf", pdfBytes);
Console.WriteLine("PDF created");
}
catch (DllNotFoundException)
{
Console.WriteLine("ERROR: wkhtmltopdf binary not found");
Console.WriteLine("Ensure libwkhtmltox is in application directory or system PATH");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
// Native crashes often provide minimal error information
}
}
}
}
Benchmark observations (1000 simple HTML pages, Windows Server 2019, 4-core):
- Average time per page: 850ms (single-threaded BasicConverter)
- Memory usage: ~180MB base + ~15MB per concurrent conversion
- Failed conversions: 3.2% (native crashes, no error details)
- Peak memory: 420MB (memory leaks accumulate)
- Thread safety: Requires SynchronizedConverter, reduces throughput ~40%
Technical limitations:
- Native binary deployment fragile—wrong version or missing dependencies cause silent failures or crashes
- QtWebKit from 2012 lacks CSS Grid, modern Flexbox, CSS3 animations
- Thread safety requires SynchronizedConverter wrapper which serializes all operations—eliminates parallel benefit
- Memory leaks in native code accumulate over time, requiring application restarts
- Segmentation faults in wkhtmltopdf crash entire process—no isolation
- Linux requires 15+ system packages (libfontconfig1, libfreetype6, libx11-6, etc.)
IronPDF — Basic HTML Rendering
using System;
using IronPdf;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(@"
<html>
<head><style>body { font-family: Arial; }</style></head>
<body><h1>Hello from IronPDF</h1></body>
</html>");
pdf.SaveAs("output.pdf");
}
}
}
Benchmark observations (1000 simple HTML pages, same hardware):
- Average time per page: 320ms (Chromium engine)
- Memory usage: ~150MB base + stable during batch processing
- Failed conversions: 0% (graceful error handling)
- Peak memory: 180MB (consistent, no leaks)
- Thread safety: Built-in, supports parallel processing with ~3.5x throughput
Comparison summary:
- 2.7x faster rendering per page
- 57% lower peak memory usage
- Zero failures vs 3.2% failure rate
- True multi-threading vs serialized processing
For detailed HTML rendering, see the HTML string to PDF guide.
Haukcode.DinkToPdf — URL to PDF
using System;
using System.IO;
using DinkToPdf;
using DinkToPdf.Contracts;
namespace DinkToPdfUrlExample
{
class Program
{
static void Main(string[] args)
{
try
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument
{
GlobalSettings = new GlobalSettings
{
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.Letter
},
Objects =
{
new ObjectSettings
{
// URL instead of HtmlContent
Page = "https://example.com",
// JavaScript delay (milliseconds)
// QtWebKit JS support limited
JavaScriptDelay = 1000,
// Load error handling
LoadSettings = new LoadSettings
{
// Network timeout
// No retry logic available
}
}
}
};
byte[] pdfBytes = converter.Convert(doc);
File.WriteAllBytes("url_output.pdf", pdfBytes);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
// Common errors:
// - Network timeout (no configuration options)
// - HTTPS certificate validation failures
// - JavaScript not executing
}
}
}
}
Benchmark observations (100 live URLs with JavaScript):
- Average time per page: 4.2 seconds
- Network timeouts: 12% (no retry logic)
- JavaScript errors: 23% (React/Vue/Angular sites fail)
- HTTPS certificate issues: 5% (no override option)
Technical limitations:
- QtWebKit JavaScript engine outdated—modern frameworks fail to execute
- No automatic retry for network failures
- HTTPS certificate validation strict—no override for development/testing
- External resources (CDN fonts, images) frequently timeout
- No proxy configuration support
- Authentication not supported
IronPDF — URL to PDF
using System;
using IronPdf;
namespace IronPdfUrlExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.Timeout = 120;
renderer.RenderingOptions.WaitFor.RenderDelay(50);
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("url_output.pdf");
}
}
}
Benchmark observations (same 100 URLs):
- Average time per page: 1.8 seconds (2.3x faster)
- Network timeouts: 0% (automatic retry)
- JavaScript errors: 0% (full V8 engine)
- HTTPS certificate issues: 0% (proper validation)
For URL rendering with authentication, see the URL to PDF documentation.
Haukcode.DinkToPdf — Multi-threaded Batch Processing
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using DinkToPdf;
using DinkToPdf.Contracts;
namespace DinkToPdfBatchExample
{
class Program
{
static void Main(string[] args)
{
// Create thread-safe converter
var converter = new SynchronizedConverter(new PdfTools());
var htmlPages = new List<string>();
for (int i = 0; i < 100; i++)
{
htmlPages.Add($"<html><body><h1>Page {i}</h1></body></html>");
}
var stopwatch = Stopwatch.StartNew();
// Parallel processing
Parallel.ForEach(htmlPages, new ParallelOptions { MaxDegreeOfParallelism = 4 },
(html, state, index) =>
{
try
{
var doc = new HtmlToPdfDocument
{
GlobalSettings = new GlobalSettings
{
PaperSize = PaperKind.A4
},
Objects =
{
new ObjectSettings { HtmlContent = html }
}
};
// SynchronizedConverter serializes all calls internally
// Parallel.ForEach doesn't actually help performance
byte[] pdfBytes = converter.Convert(doc);
File.WriteAllBytes($"output_{index}.pdf", pdfBytes);
}
catch (Exception ex)
{
Console.WriteLine($"Page {index} failed: {ex.Message}");
}
});
stopwatch.Stop();
Console.WriteLine($"Completed in {stopwatch.ElapsedMilliseconds}ms");
}
}
}
Benchmark observations (100 pages):
- Single-threaded (BasicConverter): 85 seconds
- Multi-threaded (SynchronizedConverter + Parallel): 82 seconds (3.5% improvement only)
- Reason: SynchronizedConverter uses internal locking, serializing all operations
- Memory leaks: ~8MB per batch (accumulates over time)
- Crashes: 2-3 per 1000 pages (native code segfaults)
IronPDF — Multi-threaded Batch Processing
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using IronPdf;
namespace IronPdfBatchExample
{
class Program
{
static void Main(string[] args)
{
var htmlPages = new List<string>();
for (int i = 0; i < 100; i++)
{
htmlPages.Add($"<html><body><h1>Page {i}</h1></body></html>");
}
var stopwatch = Stopwatch.StartNew();
Parallel.ForEach(htmlPages, new ParallelOptions { MaxDegreeOfParallelism = 4 },
(html, state, index) =>
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs($"output_{index}.pdf");
});
stopwatch.Stop();
Console.WriteLine($"Completed in {stopwatch.ElapsedMilliseconds}ms");
}
}
}
Benchmark observations (same 100 pages):
- Multi-threaded: 24 seconds (3.4x faster than DinkToPdf)
- True parallelism: ~4x throughput with 4 cores
- Memory stable: No leaks detected
- Crashes: Zero
For batch processing details, see the ChromePdfRenderer documentation.
Haukcode.DinkToPdf — Docker Deployment
FROM mcr.microsoft.com/dotnet/aspnet:6.0
# Install wkhtmltopdf dependencies (15+ packages)
RUN apt-get update && apt-get install -y \
libfontconfig1 \
libfreetype6 \
libx11-6 \
libxext6 \
libxrender1 \
libjpeg62-turbo \
libpng16-16 \
libssl1.1 \
ca-certificates \
fonts-liberation \
fontconfig \
wget \
&& rm -rf /var/lib/apt/lists/*
# Download and install wkhtmltopdf binary
RUN wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb \
&& apt install -y ./wkhtmltox_0.12.6-1.buster_amd64.deb \
&& rm wkhtmltox_0.12.6-1.buster_amd64.deb
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Docker image sizes:
- Base .NET 6 runtime: 180MB
- After wkhtmltopdf + dependencies: 420MB (233% increase)
- Image build time: ~3-4 minutes (dependency installation)
IronPDF — Docker Deployment
FROM ironsoftwareofficial/ironpdfengine:latest
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Docker image sizes:
- IronPDF base image: 190MB
- Optimized, no manual dependency management
- Image build time: ~30 seconds
API Mapping Reference
| Haukcode.DinkToPdf Operation | IronPDF Equivalent |
|---|---|
new SynchronizedConverter(new PdfTools()) |
new ChromePdfRenderer() |
new HtmlToPdfDocument() |
Implicit in Render methods |
GlobalSettings.PaperSize |
renderer.RenderingOptions.PaperSize |
GlobalSettings.Orientation |
renderer.RenderingOptions.PaperOrientation |
GlobalSettings.Margins |
renderer.RenderingOptions.Margin* |
ObjectSettings.HtmlContent |
renderer.RenderHtmlAsPdf(html) |
ObjectSettings.Page (URL) |
renderer.RenderUrlAsPdf(url) |
ObjectSettings.JavaScriptDelay |
renderer.RenderingOptions.WaitFor.RenderDelay() |
converter.Convert(doc) |
Implicit in Render methods |
File.WriteAllBytes(path, bytes) |
pdf.SaveAs(path) |
| Manual binary deployment | Not required |
| Platform-specific dependencies | Not required |
Comprehensive Feature Comparison
| Category | Feature | Haukcode.DinkToPdf | IronPDF |
|---|---|---|---|
| Status | Active Development | Deprecated | Active |
| Product Maintenance | None since 2018 | Ongoing | |
| Security Updates | None possible | Regular | |
| Rendering Engine | QtWebKit (2012) | Chromium (current) | |
| Support | Community Forum | Dead | Active |
| Commercial Support | Not available | Included | |
| Documentation | README only | Comprehensive | |
| Code Examples | Minimal | Extensive | |
| Content Creation | HTML5 Support | Very limited | Full |
| CSS3 Support | Minimal | Complete | |
| JavaScript | Basic (outdated) | Full V8 | |
| Modern Frameworks | Not supported | Excellent | |
| Web Fonts | Unreliable | Automatic | |
| SVG | Limited | Full | |
| Performance | Render Speed | Slow | Fast (2.7x) |
| Memory Efficiency | Poor (leaks) | Excellent | |
| Multi-threading | Fake (serialized) | True parallel | |
| Failure Rate | 3.2% | 0% | |
| Security | CVE-2022-35583 | CRITICAL UNFIXABLE | Not affected |
| SSRF Protection | None | Protected | |
| Regular Updates | Never | Yes | |
| Installation | Complexity | High | Low |
| Native Binary | Manual 40MB deployment | Not required | |
| System Dependencies | 15+ packages | None | |
| Docker Image | 420MB | 190MB | |
| Known Issues | DLL not found | Frequent | Not applicable |
| Segmentation faults | Common | Not applicable | |
| Memory leaks | Known issue | Not present | |
| Thread crashes | Documented | Not applicable | |
| Development | Learning Curve | Moderate | Shallow |
| Debugging | Impossible (native) | Standard .NET | |
| Error Messages | Cryptic/none | Detailed |
Known Security & Stability Issues
CVE-2022-35583 (Critical - CVSS 9.8): Server-Side Request Forgery—malicious HTML can access internal network, read local files. NO FIX AVAILABLE.
Segmentation faults: Native wkhtmltopdf binary crashes with segfaults approximately 2-3 times per 1000 conversions, taking down entire application.
Memory leaks: Documented leaks in native code accumulate over time, requiring periodic application restarts.
Thread safety: SynchronizedConverter serializes all operations internally—Parallel.ForEach provides minimal benefit (~3% improvement).
Binary deployment failures: Incorrect wkhtmltopdf binary version or missing system dependencies cause DllNotFoundException with minimal diagnostic info.
Linux dependency hell: Requires 15+ system packages with specific versions—missing or wrong versions cause silent failures.
Network timeouts: No retry logic—temporary network issues cause conversion failures.
JavaScript failures: QtWebKit from 2012 fails on modern JavaScript—React/Vue/Angular don't execute.
Docker image bloat: Dependencies add 240MB to image size.
No error isolation: Native crashes propagate to .NET application, no way to isolate failures.
Installation Comparison
Haukcode.DinkToPdf:
dotnet add package Haukcode.DinkToPdf
# Manual steps:
# Windows:
# 1. Download libwkhtmltox.dll from wkhtmltopdf releases
# 2. Copy to bin/Debug or bin/Release directory
# 3. Ensure 64-bit if running 64-bit app
# Linux:
# 1. Install dependencies:
sudo apt-get install -y libfontconfig1 libfreetype6 libx11-6 \
libxext6 libxrender1 libjpeg62-turbo libpng16-16 \
libssl1.1 fonts-liberation fontconfig
# 2. Download and install .deb package
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb
sudo apt install -y ./wkhtmltox_0.12.6-1.buster_amd64.deb
using DinkToPdf;
using DinkToPdf.Contracts;
IronPDF:
dotnet add package IronPdf
using IronPdf;
using IronPdf.Rendering;
Conclusion
Haukcode.DinkToPdf served teams well when it was actively maintained and before the security landscape changed. For legacy applications where migration isn't immediately possible and the SSRF vulnerability is mitigated through strict input sanitization, it may continue functioning. However, the project is officially deprecated, unmaintained, and built on an archived binary with an unfixable critical security vulnerability.
Migration from Haukcode.DinkToPdf to IronPDF is necessary for any production system exposed to untrusted HTML input. The CVE-2022-35583 SSRF vulnerability (CVSS 9.8) allows attackers to access internal networks, read local files, and bypass firewalls—and will never be patched. Beyond security, the performance benchmarks show IronPDF delivering 2.7x faster rendering with zero failures compared to DinkToPdf's 3.2% failure rate and native crashes.
IronPDF's migration path is straightforward—the API patterns are similar, but without native binary deployment or system dependency management. The ChromePdfRenderer provides modern CSS3 and JavaScript support that QtWebKit (2012) cannot match. For teams currently using DinkToPdf/Haukcode.DinkToPdf, reviewing the migration timeline is critical given the security implications. See the complete migration guide for step-by-step instructions, and review ChromePdfRenderer API documentation for feature details.
Are you currently using DinkToPdf/Haukcode.DinkToPdf in production? What's blocking your migration timeline?
Top comments (0)