Redaction Fixture
+Fixture used by Playwright to verify BugDrop screenshot redaction behavior.
+ +diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c539699..0a076ec 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,6 +12,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- uses: actions/setup-node@v4
with:
@@ -141,6 +143,8 @@ jobs:
PLAYWRIGHT_BASE_URL: https://bugdrop-widget-test-git-preview-jermwatts-projects.vercel.app
steps:
- uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- uses: actions/setup-node@v4
with:
@@ -197,6 +201,28 @@ jobs:
env:
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
+ - name: Record expected preview widget asset
+ run: |
+ VERSION=$(git describe --tags --abbrev=0) npm run build:widget
+ echo "EXPECTED_WIDGET_ORIGIN=https://bugdrop-preview.neonwatty.workers.dev" >> "$GITHUB_ENV"
+ echo "EXPECTED_WIDGET_SHA256=$(shasum -a 256 public/widget.js | awk '{print $1}')" >> "$GITHUB_ENV"
+
+ - name: Wait for expected preview widget asset
+ run: |
+ WIDGET_URL="https://bugdrop-preview.neonwatty.workers.dev/widget.js"
+ echo "Waiting for $WIDGET_URL to serve $EXPECTED_WIDGET_SHA256..."
+ for i in $(seq 1 30); do
+ ACTUAL_SHA="$(curl -sSf "$WIDGET_URL" | shasum -a 256 | awk '{print $1}')"
+ if [ "$ACTUAL_SHA" = "$EXPECTED_WIDGET_SHA256" ]; then
+ echo "Preview widget asset matched after $((i * 5))s"
+ exit 0
+ fi
+ echo "Attempt $i/30 served $ACTUAL_SHA; waiting 5s..."
+ sleep 5
+ done
+ echo "Preview widget did not serve expected asset $EXPECTED_WIDGET_SHA256"
+ exit 1
+
- name: Run live E2E tests
run: npx playwright test --project=chromium-live --workers=1
env:
diff --git a/.github/workflows/live-tests.yml b/.github/workflows/live-tests.yml
index c7cb5f8..c6f69be 100644
--- a/.github/workflows/live-tests.yml
+++ b/.github/workflows/live-tests.yml
@@ -24,6 +24,8 @@ jobs:
PLAYWRIGHT_BASE_URL: https://bugdrop-widget-test-git-preview-jermwatts-projects.vercel.app
steps:
- uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- uses: actions/setup-node@v4
with:
@@ -64,6 +66,33 @@ jobs:
env:
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
+ - name: Record expected widget asset
+ run: |
+ if [ "$LIVE_TARGET" = "preview" ]; then
+ VERSION=$(git describe --tags --abbrev=0) npm run build:widget
+ echo "EXPECTED_WIDGET_ORIGIN=https://bugdrop-preview.neonwatty.workers.dev" >> "$GITHUB_ENV"
+ echo "EXPECTED_WIDGET_SHA256=$(shasum -a 256 public/widget.js | awk '{print $1}')" >> "$GITHUB_ENV"
+ else
+ echo "EXPECTED_WIDGET_ORIGIN=https://bugdrop.neonwatty.workers.dev" >> "$GITHUB_ENV"
+ fi
+
+ - name: Wait for expected preview widget asset
+ if: env.LIVE_TARGET == 'preview'
+ run: |
+ WIDGET_URL="https://bugdrop-preview.neonwatty.workers.dev/widget.js"
+ echo "Waiting for $WIDGET_URL to serve $EXPECTED_WIDGET_SHA256..."
+ for i in $(seq 1 30); do
+ ACTUAL_SHA="$(curl -sSf "$WIDGET_URL" | shasum -a 256 | awk '{print $1}')"
+ if [ "$ACTUAL_SHA" = "$EXPECTED_WIDGET_SHA256" ]; then
+ echo "Preview widget asset matched after $((i * 5))s"
+ exit 0
+ fi
+ echo "Attempt $i/30 served $ACTUAL_SHA; waiting 5s..."
+ sleep 5
+ done
+ echo "Preview widget did not serve expected asset $EXPECTED_WIDGET_SHA256"
+ exit 1
+
- name: Run live E2E tests
run: npx playwright test --project=chromium-live --workers=1
env:
diff --git a/README.md b/README.md
index d7775d4..9bfa6c2 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ That's it! Users can now click the bug button to submit feedback as GitHub Issue
> **Important:** Do not add `async` or `defer` to the script tag — the widget needs synchronous loading to read its configuration.
-> **CSP note:** If your site uses a Content Security Policy, add `https://cdn.jsdelivr.net` to your `script-src` directive to enable screenshot capture.
+> **CSP note:** If your site uses a Content Security Policy, add `https://bugdrop.neonwatty.workers.dev` to your `script-src` directive to enable the widget.
> **Branch protection:** BugDrop works with repos that have branch protection rules (required PRs, merge queues). Screenshots are stored on a dedicated `bugdrop-screenshots` branch that is auto-created on first use — no manual setup needed.
@@ -39,7 +39,7 @@ That's it! Users can now click the bug button to submit feedback as GitHub Issue
## Features
-- 🔒 **Privacy masking** — tag sensitive elements with `data-bugdrop-mask` and BugDrop covers them in the screenshot before it's submitted. Passwords and credit-card inputs are masked automatically.
+- 🔒 **Privacy masking** — tag sensitive elements with `data-bugdrop-mask` and BugDrop visually covers them in supported screenshot modes before submission. Passwords and credit-card inputs are masked automatically.
## Widget Options
@@ -75,7 +75,7 @@ User clicks bug button → Widget captures screenshot → Worker authenticates v
```
1. **Widget** loads in a Shadow DOM (isolated from your page styles)
-2. **Screenshot** captured client-side using html2canvas
+2. **Screenshot** captured client-side using html-to-image
3. **Worker** (Cloudflare) exchanges GitHub App credentials for an installation token
4. **GitHub API** creates the issue with the screenshot stored in `.bugdrop/` on a dedicated `bugdrop-screenshots` branch (auto-created on first use)
diff --git a/docs/website/configuration.mdx b/docs/website/configuration.mdx
index 7c8244b..524cad9 100644
--- a/docs/website/configuration.mdx
+++ b/docs/website/configuration.mdx
@@ -218,7 +218,27 @@ Control how screenshots are collected during the feedback flow.
- **`auto`** -- Automatically captures a full-page screenshot after the form is submitted, without showing the manual screenshot picker or redaction step.
- **`required`** -- Requires a screenshot before submission. Users can choose full page, element, or area, then annotate or redact before submitting.
-Manual redaction is controlled by the person submitting feedback. Use developer-configured masking for fields that should never appear in screenshots, especially with automatic screenshots.
+Manual redaction is controlled by the person submitting feedback. Use developer-configured masking for fields that should be visually covered in supported screenshot modes, especially with automatic screenshots. Auto mode warns users that a full-page screenshot will be attached, but it does not show the manual picker or annotation review step.
+
+### Developer-configured screenshot masking
+
+BugDrop can visually mask fields that your app marks as private before a screenshot is uploaded:
+
+```html
+
+
Fixture used by Playwright to verify BugDrop screenshot redaction behavior.
+ +- 📸 A screenshot will be attached automatically without preview or manual redaction. + This site will attach a full-page screenshot when you submit without showing a preview. Review your page for sensitive information before sending.${redactionNote}
`; } @@ -1280,6 +1310,12 @@ function showScreenshotOptions( const fullPageDisabled = isFullPageDisabled(); const nativeViewportAvailable = fullPageDisabled && canCaptureViewportNatively(); const allowSkip = opts?.allowSkip !== false; + const redactionNote = + nativeViewportAvailable && fullPageDisabled + ? 'Browser viewport capture cannot apply automatic private-field masks. Select Element to preserve automatic masking, or review and cover sensitive areas before sending.
' + : getRedactionCount() > 0 + ? 'This site marked some fields for redaction. Review the screenshot before sending.
' + : ''; return new Promise(resolve => { const complexNote = fullPageDisabled @@ -1297,6 +1333,7 @@ function showScreenshotOptions( `Choose what to capture:
${complexNote} + ${redactionNote}This browser viewport capture could not apply automatic private-field masks. Review and cover any sensitive areas before sending.
` + : redactionCount > 0 + ? `${redactionCount} private ${redactionCount === 1 ? 'item was' : 'items were'} marked for redaction in this screenshot. Review before sending.
` + : ''; const modal = createModal( root, 'Review Screenshot', ` + ${redactionNote}- Cover sensitive areas before submitting. Redactions are baked into the uploaded image. + Check that no sensitive information is visible before sending. Cover sensitive areas before submitting. Redactions are baked into the uploaded image.