forme-ruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +35 -0
- data/CODE_OF_CONDUCT.md +18 -0
- data/CONTRIBUTING.md +67 -0
- data/LICENSE +21 -0
- data/NOTICE +5 -0
- data/README.md +71 -0
- data/SECURITY.md +17 -0
- data/THIRD_PARTY_LICENSES.txt +24354 -0
- data/docs/README.md +18 -0
- data/docs/github-setup.md +60 -0
- data/docs/installation.md +60 -0
- data/docs/rails.md +56 -0
- data/docs/releasing.md +83 -0
- data/docs/rendering.md +63 -0
- data/docs/security-exceptions.md +41 -0
- data/examples/hello.rb +6 -0
- data/ext/forme_pdf/Cargo.lock +1156 -0
- data/ext/forme_pdf/Cargo.toml +16 -0
- data/ext/forme_pdf/extconf.rb +31 -0
- data/ext/forme_pdf/src/lib.rs +191 -0
- data/lib/forme_pdf/errors.rb +7 -0
- data/lib/forme_pdf/native.rb +41 -0
- data/lib/forme_pdf/rails.rb +15 -0
- data/lib/forme_pdf/renderer.rb +40 -0
- data/lib/forme_pdf/result.rb +5 -0
- data/lib/forme_pdf/version.rb +6 -0
- data/lib/forme_pdf.rb +25 -0
- metadata +126 -0
data/docs/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Forme Ruby Guides
|
|
2
|
+
|
|
3
|
+
These guides introduce native PDF rendering, then cover application integration,
|
|
4
|
+
development and release. Each guide states its prerequisites and includes runnable
|
|
5
|
+
examples. Begin with [installation](installation.md).
|
|
6
|
+
|
|
7
|
+
| Guide | You will learn |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| [Installation](installation.md) | Runtime requirements, Git/source installs and native packages. |
|
|
10
|
+
| [Rendering](rendering.md) | Binary results, CSS, fonts, diagnostics and errors. |
|
|
11
|
+
| [Rails](rails.md) | Explicit controller rendering and ownership of responses. |
|
|
12
|
+
| [Contributing](../CONTRIBUTING.md) | Build, test and review changes. |
|
|
13
|
+
| [GitHub setup](github-setup.md) | Repository protections, security and publishing setup. |
|
|
14
|
+
| [Security exceptions](security-exceptions.md) | Reviewed, inaccessible upstream advisory paths. |
|
|
15
|
+
| [Releasing](releasing.md) | Qualify packages and prepare trusted publishing. |
|
|
16
|
+
|
|
17
|
+
See [README](../README.md) for a quick example and [CHANGELOG](../CHANGELOG.md)
|
|
18
|
+
for version-specific changes. The gem remains independent of consumer applications.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Setting Up the GitHub Repository
|
|
2
|
+
|
|
3
|
+
After reading this guide, you will know what is checked in and which GitHub and
|
|
4
|
+
RubyGems settings a maintainer must enable. These instructions prepare
|
|
5
|
+
`clearstackio/forme-ruby`; they do not authorize pushing or publishing.
|
|
6
|
+
|
|
7
|
+
## Repository files
|
|
8
|
+
|
|
9
|
+
The repository includes an MIT license, contributor and security guides, issue
|
|
10
|
+
forms, a pull-request template, CODEOWNERS, Dependabot, CodeQL, dependency review,
|
|
11
|
+
and build/release workflows. Actions are pinned to full commit SHAs; Dependabot
|
|
12
|
+
proposes updates. CI runs on pull requests, main pushes and a weekly schedule.
|
|
13
|
+
PR jobs do not receive publishing credentials. Checkout does not persist tokens.
|
|
14
|
+
|
|
15
|
+
## Configure GitHub after an authorized push
|
|
16
|
+
|
|
17
|
+
1. Set the description to “Native HTML and print CSS to PDF for Ruby and Rails,
|
|
18
|
+
powered by Forme.” Use topics `ruby`, `rails`, `pdf`, `rust`, `html-to-pdf`.
|
|
19
|
+
2. Enable Issues and private vulnerability reporting. Enable the dependency
|
|
20
|
+
graph, Dependabot alerts, secret scanning and push protection where available.
|
|
21
|
+
CodeQL is provided as an advanced workflow for Ruby, Rust and GitHub Actions; do not also enable
|
|
22
|
+
CodeQL default setup.
|
|
23
|
+
3. After the first successful run, protect `main` with a ruleset requiring pull
|
|
24
|
+
requests, one approving review, resolved conversations, current branches and
|
|
25
|
+
the `CI required`, CodeQL matrix and dependency-review checks. Select the
|
|
26
|
+
actual check names from GitHub. Block deletion and force pushes. Require code
|
|
27
|
+
owner review for changes; add another trusted maintainer so the sole owner's
|
|
28
|
+
pull requests can be reviewed. Do not silently bypass review to unblock them.
|
|
29
|
+
4. Allow only reviewed Actions, keep the default workflow token read-only, and
|
|
30
|
+
disable Actions creating or approving pull requests. Keep fork approval on.
|
|
31
|
+
5. Create environment `rubygems`, restrict deployment to `main`, and configure a
|
|
32
|
+
trusted maintainer as required reviewer with self-review prevented. Confirm
|
|
33
|
+
an eligible second reviewer exists before enabling this requirement.
|
|
34
|
+
6. Configure RubyGems trusted publishing exactly as [releasing](releasing.md)
|
|
35
|
+
specifies. Do not store a long-lived publishing key in repository secrets.
|
|
36
|
+
|
|
37
|
+
The existing remote has older history. The prepared local root commit replaces
|
|
38
|
+
that history only after explicit authorization and consumer coordination. Enable
|
|
39
|
+
force-push protection after that authorized initial transition. A backup local
|
|
40
|
+
branch preserves the prior history. Never force-push just to make CI pass.
|
|
41
|
+
|
|
42
|
+
## Release evidence
|
|
43
|
+
|
|
44
|
+
`CI required` fails if any Ruby test, package build, distribution installation or
|
|
45
|
+
audit fails or is skipped. Linux packages are built against glibc 2.28 and checked
|
|
46
|
+
for newer symbol requirements. Compatibility jobs install the same artifact,
|
|
47
|
+
not a newly rebuilt library. Rolling Arch is deliberately retested weekly.
|
|
48
|
+
|
|
49
|
+
The manual release workflow accepts only a successful CI run from this repository,
|
|
50
|
+
for the exact main commit. It validates package names, versions, platforms and
|
|
51
|
+
license files before trusted publication, and records an attestation for the
|
|
52
|
+
promotion workflow. Keep the successful CI URL with release notes. GitHub
|
|
53
|
+
settings, hosted matrix success and RubyGems setup must be confirmed separately;
|
|
54
|
+
local tests do not establish any of them.
|
|
55
|
+
|
|
56
|
+
See GitHub's [secure Actions guidance](https://docs.github.com/en/actions/reference/security/secure-use)
|
|
57
|
+
and RubyGems' [trusted publishing guide](https://guides.rubygems.org/trusted-publishing/).
|
|
58
|
+
|
|
59
|
+
Rust scanning uses CodeQL’s supported `none` build mode with the pinned Rust
|
|
60
|
+
toolchain; see [GitHub’s Rust scanning requirements](https://docs.github.com/en/code-security/reference/code-scanning/codeql/build-options-for-compiled-languages#building-rust).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Installing Forme Ruby
|
|
2
|
+
|
|
3
|
+
After reading this guide, you will know how installation differs between Git,
|
|
4
|
+
source and native packages, and how to check the installed renderer.
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
|
|
8
|
+
Use CRuby 3.2 or later. CI covers Ruby 3.2, 3.3, 3.4 and 4.0 on Linux AMD64 and
|
|
9
|
+
macOS ARM64. The core has no Rails dependency. JRuby, Windows, musl and other
|
|
10
|
+
architectures are not qualified release targets.
|
|
11
|
+
|
|
12
|
+
| Package | Requirement |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| Git checkout or `ruby` source gem | Rust/Cargo 1.94.0 (qualified toolchain), linker, make, network access to pinned Git and crates.io dependencies. |
|
|
15
|
+
| `arm64-darwin` | Apple Silicon, macOS 15 or later. |
|
|
16
|
+
| `x86_64-linux-gnu` | AMD64 Linux, glibc 2.28 or later. |
|
|
17
|
+
|
|
18
|
+
## Native qualification
|
|
19
|
+
|
|
20
|
+
The Linux library is built inside pinned Red Hat UBI 8 with a baseline x86-64
|
|
21
|
+
CPU target. CI rejects symbols requiring glibc newer than 2.28. The same gem
|
|
22
|
+
is installed and renders a PDF in UBI 8, 9 and 10, Ubuntu 24.04 and 26.04,
|
|
23
|
+
and current Arch Linux, without Rust installed. UBI testing exercises the
|
|
24
|
+
RHEL userspace baseline; it is not a certification of every RHEL deployment.
|
|
25
|
+
Use a Ruby 3.2+ installation even when a distribution defaults to older Ruby.
|
|
26
|
+
|
|
27
|
+
The macOS gem is built on Apple Silicon macOS 15 with a 15.0 deployment target
|
|
28
|
+
and installed on macOS 15 and 26. Both native artifacts are also installed
|
|
29
|
+
across CRuby 3.2, 3.3, 3.4 and 4.0. Hosted qualification of this prepared commit
|
|
30
|
+
is pending. These tests establish installation/rendering compatibility, not
|
|
31
|
+
identical pagination for every font and document.
|
|
32
|
+
|
|
33
|
+
## Install before the first release
|
|
34
|
+
|
|
35
|
+
Version 0.1.0 is not yet published to RubyGems. Add the Git dependency shown in
|
|
36
|
+
[README](../README.md) and run `bundle install`. Commit `Gemfile.lock` so builds
|
|
37
|
+
use a reviewed revision. Compilation happens during installation; no compiler
|
|
38
|
+
or dependency download runs during `require` or rendering.
|
|
39
|
+
|
|
40
|
+
## Install a released version later
|
|
41
|
+
|
|
42
|
+
After publication is confirmed, use:
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
gem "forme-ruby", "~> 0.1.0", require: "forme_pdf"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Bundler selects a matching native package where available. A source fallback
|
|
49
|
+
requires the build tools above; it is not a promise of support for every platform.
|
|
50
|
+
Native packages load their own shared library without a system Forme install.
|
|
51
|
+
|
|
52
|
+
## Verify the installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
bundle exec ruby -rforme_pdf -e 'FormePDF.verify!; abort "Invalid PDF" unless FormePDF.render_html("<h1>Hello</h1>").start_with?("%PDF-")'
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`verify!` checks loading and ABI compatibility; the render exercises the engine.
|
|
59
|
+
For `FormePDF::LoadError`, check the installed platform and library permissions.
|
|
60
|
+
Reinstall the matching gem instead of copying a library from another platform.
|
data/docs/rails.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Rendering PDFs in Rails
|
|
2
|
+
|
|
3
|
+
After reading this guide, you will know how to render ERB to PDF while retaining
|
|
4
|
+
control of permissions, templates and HTTP responses. The core gem does not
|
|
5
|
+
require Rails; these examples assume an existing Rails application.
|
|
6
|
+
|
|
7
|
+
## Render explicitly
|
|
8
|
+
|
|
9
|
+
Select and authorize records in your application's controller before rendering.
|
|
10
|
+
Supply a dedicated HTML template and layout:
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
html = render_to_string(template: "invoices/pdf", layout: "pdf", formats: [:html])
|
|
14
|
+
pdf = FormePDF.render_html(html)
|
|
15
|
+
send_data pdf, type: "application/pdf", disposition: "inline", filename: "invoice.pdf"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Use `attachment` instead of `inline` when the application's download contract
|
|
19
|
+
requires it. Application code owns routes, record scopes, filenames, asset
|
|
20
|
+
selection and member-data masking. Keep browser print templates separate if
|
|
21
|
+
PDF styling needs different behavior.
|
|
22
|
+
|
|
23
|
+
## Use the optional adapter
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
require "forme_pdf/rails"
|
|
27
|
+
|
|
28
|
+
class InvoicesController < ApplicationController
|
|
29
|
+
include FormePDF::Rails
|
|
30
|
+
end
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
From an already authorized action:
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
pdf = render_forme_pdf(template: "invoices/pdf", layout: "pdf", locals: {invoice: @invoice})
|
|
37
|
+
send_data pdf, type: "application/pdf", disposition: "inline", filename: "invoice.pdf"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`render_forme_pdf` returns bytes; it does not send a response. It passes
|
|
41
|
+
`formats: [:html]` to Rails and forwards rendering options to FormePDF. It does
|
|
42
|
+
not prepare assets, select records, install middleware, add routes or register
|
|
43
|
+
a Railtie. The host application supplies Rails and controls its lifecycle.
|
|
44
|
+
|
|
45
|
+
## Verify at startup
|
|
46
|
+
|
|
47
|
+
Applications that require PDF availability can add this initializer:
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
FormePDF.verify!
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Load failure then prevents startup instead of silently disabling PDF reports.
|
|
54
|
+
Test actual rendering in the deployment image too. The adapter spec uses an
|
|
55
|
+
isolated controller double; consumers must test their actual Rails stack and
|
|
56
|
+
report routes. No specific Rails version matrix is claimed by this gem.
|
data/docs/releasing.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Preparing and Releasing Forme Ruby
|
|
2
|
+
|
|
3
|
+
After reading this guide, you will know how to qualify source/native artifacts
|
|
4
|
+
and which steps publish externally. **Current status: 0.1.0 is unreleased.**
|
|
5
|
+
Local preparation does not authorize a push, tag or RubyGems publication.
|
|
6
|
+
|
|
7
|
+
## Prepare locally
|
|
8
|
+
|
|
9
|
+
1. Review README, guides, AGENTS, CHANGELOG, gemspec metadata, LICENSE, NOTICE
|
|
10
|
+
and generated third-party notices. Keep public examples free of private data.
|
|
11
|
+
2. Run the contributor checks and package-install checks. Inspect package files:
|
|
12
|
+
source gems contain the locked Rust sources/build hook; native gems contain
|
|
13
|
+
their library and no build hook. Confirm guides and all notices are included.
|
|
14
|
+
3. Keep `lib/forme_pdf/version.rb` and CHANGELOG aligned. Do not date an unreleased
|
|
15
|
+
entry as if it were published. Review the tested Forme revision and platform
|
|
16
|
+
minimums whenever native dependencies change.
|
|
17
|
+
4. If history is explicitly squashed, record old/new refs and keep a backup.
|
|
18
|
+
Previously successful CI does not qualify the new commit. Consumers must not
|
|
19
|
+
lock to an unpublished SHA. Do not change remote history during local preparation.
|
|
20
|
+
|
|
21
|
+
## Qualify the release commit later
|
|
22
|
+
|
|
23
|
+
After a separately authorized GitHub push, require successful `ci.yml` for that
|
|
24
|
+
exact `main` commit. CI tests CRuby 3.2, 3.3, 3.4 and 4.0 on Ubuntu 24.04 and
|
|
25
|
+
macOS 15, builds source/native packages and clean-installs them. The same Linux
|
|
26
|
+
artifact renders on UBI 8/9/10, Ubuntu 24.04/26.04 and Arch rolling; the macOS
|
|
27
|
+
artifact renders on macOS 15/26. See [installation](installation.md). Review the three intended artifacts: `ruby`,
|
|
28
|
+
`arm64-darwin`, and `x86_64-linux-gnu`. No Windows or musl binary is claimed.
|
|
29
|
+
|
|
30
|
+
The repository already has published history. Replacing it after a local root
|
|
31
|
+
squash would be a remote history rewrite, requiring separate authorization and
|
|
32
|
+
coordination with consumers. Keep the existing reachable consumer pin until then.
|
|
33
|
+
|
|
34
|
+
Review [GitHub repository setup](github-setup.md) before enabling releases.
|
|
35
|
+
|
|
36
|
+
## Configure trusted publishing later
|
|
37
|
+
|
|
38
|
+
Under the `ajaya` RubyGems account, configure a pending publisher for the new gem:
|
|
39
|
+
|
|
40
|
+
| Field | Value |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| Gem | `forme-ruby` |
|
|
43
|
+
| GitHub owner | `clearstackio` |
|
|
44
|
+
| Repository | `forme-ruby` |
|
|
45
|
+
| Workflow | `release.yml` |
|
|
46
|
+
| Environment | `rubygems` |
|
|
47
|
+
|
|
48
|
+
Use the matching GitHub environment and review its protections. A pending
|
|
49
|
+
publisher becomes associated with the gem after its first successful upload.
|
|
50
|
+
See the [official RubyGems trusted publishing guide](https://guides.rubygems.org/trusted-publishing/)
|
|
51
|
+
for setup. No long-lived RubyGems API key is required by this workflow.
|
|
52
|
+
|
|
53
|
+
## Publish only with explicit authorization
|
|
54
|
+
|
|
55
|
+
The manual `release.yml` workflow takes a successful CI run ID and verifies its
|
|
56
|
+
commit, branch and workflow path against the release invocation. It downloads
|
|
57
|
+
those tested artifacts and publishes them; it does not rebuild them at release
|
|
58
|
+
time. Package validation requires exactly the three intended platforms and
|
|
59
|
+
matching names/versions. A provenance attestation records the release workflow
|
|
60
|
+
that promotes those artifacts; it does not replace the linked CI build evidence.
|
|
61
|
+
Treat dispatching it as publication, not a dry run.
|
|
62
|
+
|
|
63
|
+
Before dispatch, confirm the version is available, the package inventory is
|
|
64
|
+
correct and all three tested artifacts belong to the intended commit. Afterward,
|
|
65
|
+
verify all platforms on RubyGems, install from RubyGems in clean environments and
|
|
66
|
+
record the release date/tag. Partial publication cannot be overwritten: inspect
|
|
67
|
+
which platforms succeeded before deciding how to recover. Update consumer
|
|
68
|
+
Gemfiles only after the version is available and qualified.
|
|
69
|
+
|
|
70
|
+
## Evidence and remaining gates
|
|
71
|
+
|
|
72
|
+
The earlier `b6d287c` commit passed hosted Linux/macOS CI, including AlmaLinux 10.
|
|
73
|
+
That is historical evidence, not approval of a new local squashed SHA. Hosted CI,
|
|
74
|
+
trusted-publisher configuration and actual publication remain pending for the
|
|
75
|
+
prepared release. No release workflow is run by local package tasks.
|
|
76
|
+
|
|
77
|
+
Local preparation on 2026-09-18 verified macOS source/native installations and
|
|
78
|
+
native Linux rendering in UBI 8/9, Ubuntu 24.04/26.04 and Arch. The UBI 8 build
|
|
79
|
+
passed the glibc 2.28 symbol check. Arch's local QEMU run needed pacman's sandbox
|
|
80
|
+
disabled; the committed hosted job uses its normal sandbox. UBI 10 could not
|
|
81
|
+
start under the local emulator because it requires an x86-64-v3 CPU. Its hosted
|
|
82
|
+
x86 check remains mandatory. These local results do not qualify the complete
|
|
83
|
+
hosted matrix or authorize publication.
|
data/docs/rendering.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Rendering PDFs
|
|
2
|
+
|
|
3
|
+
After reading this guide, you will know how to render trusted HTML, register
|
|
4
|
+
fonts and inspect diagnostics. Install the gem before running these examples.
|
|
5
|
+
|
|
6
|
+
## Render HTML
|
|
7
|
+
|
|
8
|
+
```ruby
|
|
9
|
+
require "forme_pdf"
|
|
10
|
+
|
|
11
|
+
pdf = FormePDF.render_html("<h1>Invoice</h1>", css: "@page { size: Letter; margin: 0.75in; }")
|
|
12
|
+
File.binwrite("invoice.pdf", pdf)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Input must be a String containing valid text. Valid non-UTF-8 encodings are
|
|
16
|
+
transcoded; binary input is interpreted as UTF-8. The result is a frozen binary
|
|
17
|
+
ASCII-8BIT String. Always write with `File.binwrite`.
|
|
18
|
+
|
|
19
|
+
## Style pages and supply assets
|
|
20
|
+
|
|
21
|
+
Forme supports a subset of HTML and print CSS, not browser layout or JavaScript.
|
|
22
|
+
Use dedicated print styles and inspect the resulting pages. Inline CSS or pass
|
|
23
|
+
`css:`; embed images as data URIs. The binding does not fetch remote stylesheets
|
|
24
|
+
or fonts. Local image paths are possible, so use trusted input only.
|
|
25
|
+
|
|
26
|
+
Supply TTF font bytes explicitly:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
pdf = FormePDF.render_html(
|
|
30
|
+
'<p style="font-family: Report">A document</p>',
|
|
31
|
+
fonts: [{family: "Report", data: File.binread("report.ttf"), weight: 400, italic: false}]
|
|
32
|
+
)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`css:` and `fonts:` are the supported rendering keywords. Font entries accept
|
|
36
|
+
`family`, `data`, `weight` (default 400) and `italic` (default false). Unknown
|
|
37
|
+
options fail. Register the weights/styles your document needs and check the PDF.
|
|
38
|
+
|
|
39
|
+
## Inspect diagnostics
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
result = FormePDF.render_html_result("<p>Report</p>")
|
|
43
|
+
File.binwrite("report.pdf", result.pdf)
|
|
44
|
+
puts result.passes
|
|
45
|
+
result.warnings.each { |warning| warn warning }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The result and its warning array/strings are frozen. Unsupported CSS can produce
|
|
49
|
+
warnings without a failed render. Review warnings using synthetic input; do not
|
|
50
|
+
send sensitive document content or diagnostics to public logs.
|
|
51
|
+
|
|
52
|
+
## Handle errors and concurrency
|
|
53
|
+
|
|
54
|
+
`FormePDF::LoadError` and `FormePDF::RenderError` inherit `FormePDF::Error`.
|
|
55
|
+
Invalid caller arguments can raise `ArgumentError` or encoding errors. Avoid
|
|
56
|
+
rescuing everything and returning an HTML success response as if it were a PDF.
|
|
57
|
+
|
|
58
|
+
Each render owns independent native result storage. Ruby copies the bytes and
|
|
59
|
+
frees that result even when copying or decoding fails. Native calls release the
|
|
60
|
+
Ruby lock; concurrent callers do not share output buffers. Ruby interruption is
|
|
61
|
+
masked during native ownership, so thread cancellation is not a render deadline.
|
|
62
|
+
Use process-level resource limits for large or hostile inputs. The API is not a
|
|
63
|
+
sandbox and exposes no per-render timeout.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Reviewing Native Dependency Advisories
|
|
2
|
+
|
|
3
|
+
After reading this guide, you will understand the current audit exceptions and
|
|
4
|
+
when they must be reconsidered. Review date: 2026-09-18.
|
|
5
|
+
|
|
6
|
+
## Scope
|
|
7
|
+
|
|
8
|
+
These exceptions acknowledge vulnerable dependencies; they do not patch them.
|
|
9
|
+
They apply only to Forme revision `f408920e632c59da0651b5b6d32f8c1397477673`,
|
|
10
|
+
the locked dependency graph and the HTML-only Ruby API. Rendering is not a
|
|
11
|
+
sandbox for arbitrary HTML. See [SECURITY](../SECURITY.md).
|
|
12
|
+
|
|
13
|
+
| Advisory | Locked package | Why the affected path is inaccessible |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| [RUSTSEC-2026-0195](https://rustsec.org/advisories/RUSTSEC-2026-0195.html) | quick-xml 0.37.5 | The engine uses plain `Reader`, never `NsReader` or its namespace resolver. |
|
|
16
|
+
| [RUSTSEC-2026-0194](https://rustsec.org/advisories/RUSTSEC-2026-0194.html) | quick-xml 0.37.5 | Duplicate-attribute handling is vulnerable in upstream SVG parsing, but the HTML mapper never constructs SVG nodes. |
|
|
17
|
+
| [RUSTSEC-2023-0071](https://rustsec.org/advisories/RUSTSEC-2023-0071.html) | rsa 0.9.10 | Private-key operations occur only in certification, which HTML conversion leaves disabled. |
|
|
18
|
+
|
|
19
|
+
## Verify the boundaries
|
|
20
|
+
|
|
21
|
+
`ext/forme_pdf/src/lib.rs` accepts only CSS and fonts, rejects unknown options,
|
|
22
|
+
and calls `forme_pdf_html::render_html` with default HTML options. In the pinned
|
|
23
|
+
upstream tree, `html/src/dom.rs` parses with html5ever. `html/src/map.rs` has no
|
|
24
|
+
`NodeKind::Svg` construction and initializes `certification: None`.
|
|
25
|
+
`engine/src/image_loader.rs` accepts JPEG, PNG and WebP, so an SVG image cannot
|
|
26
|
+
enter the XML parser through an image URL. Font registration does not parse XML.
|
|
27
|
+
Only `forme-pdf` consumes quick-xml and rsa in the locked dependency graph.
|
|
28
|
+
|
|
29
|
+
The exceptions are configured in `.cargo/audit.toml`. Scheduled CI continues to
|
|
30
|
+
report other advisories, including unmaintained dependency warnings. Re-review
|
|
31
|
+
all exceptions when the engine pin, options schema, Cargo features or exports
|
|
32
|
+
change, especially SVG, raw document/JSON, imports or signing. Check the exact
|
|
33
|
+
new call paths; do not carry exceptions forward automatically.
|
|
34
|
+
|
|
35
|
+
## Remove exceptions when possible
|
|
36
|
+
|
|
37
|
+
Prefer an upstream update to quick-xml 0.41+ or feature-gating unused SVG and
|
|
38
|
+
certification dependencies. The current upstream 0.37 constraint prevents a
|
|
39
|
+
lockfile-only upgrade. RustSec lists no patched RSA version at review time;
|
|
40
|
+
a version bump alone is not remediation. Track upstream fixes during the weekly
|
|
41
|
+
dependency review and remove an exception once the dependency is fixed or removed.
|