> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/conversion/web-html-to-pdf/hardening-security-html.md).

# Security best practices for Web/HTML to PDF

Review the hardening security guidelines for HTML to PDF conversion using the Apryse Server SDK.

This guide provides best practices for hardening the security of the HTML2PDF module within your deployment environment.

The HTML2PDF module opens the webpage it's pointed at, then converts it to a PDF when going through the HTML2PDF process. Maliciously crafted webpages can be a security problem during this process. Since the SDK browser instance doesn't include the ability for you to follow good web hygiene, we've constructed this guide to inform you of the risks involved and best practices you can follow.

HTML2PDF is based on headless Chromium. It is equipped with the same security features as the Chromium browser. In addition to that:

* HTML2PDF has no persistent storage for cookies or site data and no cache.
* Every HTML to PDF conversion runs in a separate isolated process.

HTML2PDF is frequently updated to include the latest security patches from the Chromium browser. Make sure to keep the module up to date.

## Sandboxing (Windows, macOS)

Sandboxing is a crucial security mechanism that restricts the privileges of various components within the module. However, two module options, when modified, can disable sandboxing:

* **Sandbox** – Setting this property to false disables sandboxing for all following conversions.
* **CompatibilityMode** – Setting this property to true deactivates sandboxing as well.

For maximum security do not change the defaults of the options above.

## Local file access

The Same-origin Policy (SOP) is always enabled. However, when converting files from the local file system using the `file://` protocol, the "origin" is considered to be the entire file system. The module does not provide any built-in mechanisms to restrict access to local files referenced by the source HTML files or scripts. Instead, it relies on the operating system's permission-based controls to enforce access restrictions.

If this level of isolation is not sufficient, we recommend setting up a basic static web server to serve the source HTML files. This way access to the file system is restricted by the web server.

For example, let your directory for source files be `/tmp/html-to-pdf-sources`. Then you can create a server with:

{% tabs %}
{% tab title="python" %}
{% code lineNumbers="true" %}

```python
//@data {"m":true}//
python3 -m http.server --bind 127.0.0.1 -d /tmp/html-to-pdf-source
```

{% endcode %}
{% endtab %}

{% tab title="sh" %}
{% code lineNumbers="true" %}

```sh
//@data {"m":true}//
npx http-server /tmp/html-to-pdf-sources -p 8000
```

{% endcode %}
{% endtab %}
{% endtabs %}

In the next step, create a subdirectory `my_dir` in `/tmp/html-to-pdf-sources`, then, put your source file, `my_file.html`, along with all related resources, in it and then start conversion:

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
//@data {"m":true}//
python3 -m http.server --bind 127.0.0.1 -d /tmp/html-to-pdf-sources
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
//@data {"m":true}//
converter.InsertFromURL("http://127.0.0.1:8000/my_dir/my_file.html");
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
//@data {"m":true}//
converter.InsertFromURL("http://127.0.0.1:8000/my_dir/my_file.html")
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
//@data {"m":true}//
converter.insertFromURL("http://127.0.0.1:8000/my_dir/my_file.html");
```

{% endcode %}
{% endtab %}

{% tab title="Javascript" %}
{% code lineNumbers="true" %}

```html
//@data {"m":true}//
html2pdf.insertFromUrl('http://127.0.0.1:8000/my_dir/my_file.html');
```

{% endcode %}
{% endtab %}

{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
//@data {"m":true}//
[converter InsertFromURL: @"http://127.0.0.1:8000/my_dir/my_file.html"];
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
//@data {"m":true}//
converter.InsertFromURL("http://127.0.0.1:8000/my_dir/my_file.html")
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
//@data {"m":true}//
converter.InsertFromURL('http://127.0.0.1:8000/my_dir/my_file.html')
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
//@data {"m":true}//
converter.InsertFromURL("http://127.0.0.1:8000/my_dir/my_file.html")
```

{% endcode %}
{% endtab %}
{% endtabs %}

The module will have no access to the files outside of the `/tmp/html-to-pdf-sources` directory.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.apryse.com/core/conversion/web-html-to-pdf/hardening-security-html.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
