Advanced
Data protection
Two independent, opt-in controls. pdfPassword encrypts the generated PDF; redact masks likely credentials and PII out of report content before it is written or streamed. Both default off: turn on what your environment needs.
Why it matters
Playwright captures whatever your tests touch: error messages, assertion diffs, step titles, console output, annotations. A failing request assertion can carry an API key in its URL. A debug console.log can print an auth header. A form-fill step title can carry a password typed during setup. None of that is a ReportForge bug, it is exactly what your test did, faithfully reported.
A generated PDF often ends up somewhere with broader read access than the pipeline that produced it: attached to an email, posted to Slack or Discord, sitting in a CI artifact bucket. redact and pdfPassword reduce what leaks if that happens.
Redact credentials & PII
Enable redact to mask likely secrets in report text: error messages and stack traces, step titles, captured console output, test and suite titles, annotations, failure-analysis text, and chart labels. The live watch stream is covered too, so redact and live compose safely.
reporter: [['@reportforge/playwright-pdf', { redact: { enabled: true, builtins: true, // built-in credential/PII patterns (default: true) patterns: ['MYCO_[A-Z0-9]+'], // your own regexes, always fully masked mask: '[REDACTED]', // replacement text (default) },}]]Redaction runs after failure analysis, so the classifier still scores the original text and category accuracy is unaffected; only the rendered and streamed output is masked.
Built-in patterns
With builtins: true (the default once redact.enabled is on), these patterns are masked automatically:
| Catches | Kept as-is | Example |
|---|---|---|
| key=value / "key": "value" credentials (password, secret, token, apiKey, auth, credential, privateKey, accessKey, clientSecret, …) | the key name | password: "hunter2" → password: "[REDACTED]" |
| Authorization: Bearer … / Basic … | the scheme word | Bearer eyJhbGc... → Bearer [REDACTED] |
| JWTs, anywhere in text | n/a | eyJhbGciOi... |
| Provider key prefixes | n/a | AWS AKIA…, GitHub ghp_/gho_/github_pat_, Slack xox*, OpenAI-style sk-, Razorpay rzp_live_/rzp_test_, Google AIza… |
| URLs with embedded credentials | the username | https://alice:hunter2@host → https://alice:[REDACTED]@host |
| Emails | first character + domain | jsmith@example.com → j***@example.com |
| High-entropy strings (20+ mixed letters/digits) | n/a | tokens and keys with no recognizable prefix |
The email pattern always partially masks to x***@domain, independent of mask. Every other match, built-in or custom, is replaced with mask.
Custom patterns
Add your own patterns for anything the built-ins do not cover: internal ticket IDs, project-specific token formats, customer identifiers.
redact: { enabled: true, patterns: [ 'MYCO_[A-Z0-9]{8,}', // internal token format 'CUST-\\d{6}', // customer ID ],}Patterns are regex source strings, compiled with the g flag (case-sensitive). Unlike the partial built-ins, every custom match is replaced with the full mask text, with no surrounding context kept. A pattern that throws at match time is disabled for the rest of the run and logged once; the rest keep working.
Password-protect the PDF
Set pdfPassword to encrypt the generated PDF with AES-256, applied in-process: no qpdf or other system tool to install.
reporter: [['@reportforge/playwright-pdf', { pdfPassword: process.env.RF_PDF_PASSWORD,}]]Source the password from an environment variable rather than committing it.
When a run has more failures than maxInlineFailures, the overflow is written to a sidecar JSON file next to the PDF. If pdfPassword is set, the sidecar is encrypted too, saved as {basename}-failures.json.enc instead of plain JSON. Decrypt it with the bundled CLI:
npx @reportforge/playwright-pdf decrypt-failures reports/2026-04-28-report-failures.json.enc --password=$RF_PDF_PASSWORD# or set RF_PDF_PASSWORD in the environment and drop --password# --out=<path> chooses where the decrypted JSON is written (default: input path minus .enc)Limitations
Screenshots are not redacted. redact operates on text; a screenshot is pixels, and a credential visible on screen (a filled-in password field, an API key pasted into a text box) stays visible in the image. Set includeScreenshots: false if your environment cannot tolerate that.
Redaction is best-effort. The built-in patterns and your own regexes catch known shapes; they cannot catch every secret format, and an unusual value can slip through. Treat redact as a second layer, not a substitute for controlling who can open the report in the first place.