Skip to content

feat(web): add ALLOW_INLINE_STYLES env var to opt-in inline CSS in Markdown rendering#34719

Merged
WTW0313 merged 2 commits intolanggenius:mainfrom
s-kawamura-upgrade:feature/allow-inline-styles
Apr 8, 2026
Merged

feat(web): add ALLOW_INLINE_STYLES env var to opt-in inline CSS in Markdown rendering#34719
WTW0313 merged 2 commits intolanggenius:mainfrom
s-kawamura-upgrade:feature/allow-inline-styles

Conversation

@s-kawamura-upgrade
Copy link
Copy Markdown
Contributor

Summary

Add a deployment-level environment variable ALLOW_INLINE_STYLES (default: false) that allows self-hosted operators to opt-in to inline style attributes in Markdown rendering.

The v1.13.1 streamdown migration (#32971) introduced rehype-sanitize with a whitelist-based schema that strips all style attributes. This broke existing production workflows using Jinja2 templates with styled HTML in Answer nodes.

This PR follows the simplified implementation approach suggested by @WTW0313:

  • No prop drillingALLOW_INLINE_STYLES is read directly from @/config in streamdown-wrapper.tsx
  • Same pattern as ALLOW_UNSAFE_DATA_SCHEME — env schema, config export, entrypoint mapping, docker-compose wiring
  • Default remains secure (false) — self-hosted opt-in only
  • Deployment wiring includedentrypoint.sh, docker-compose.yaml, docker-compose-template.yaml, .env.example

Files changed (8 files, +25 lines)

File Change
web/env.ts Add schema + experimental__runtimeEnv mapping
web/config/index.ts Export ALLOW_INLINE_STYLES
web/app/components/base/markdown/streamdown-wrapper.tsx Read config, append 'style' to sanitize schema
web/docker/entrypoint.sh Map ALLOW_INLINE_STYLESNEXT_PUBLIC_ALLOW_INLINE_STYLES
docker/docker-compose.yaml Add to x-shared-env and web service
docker/docker-compose-template.yaml Add to web service
docker/.env.example Document the variable with tradeoff notes
web/.env.example Document the variable

Core change (streamdown-wrapper.tsx)

if (ALLOW_INLINE_STYLES) {
  const globalAttrs = mergedAttributes['*'] ?? []
  mergedAttributes['*'] = [...globalAttrs, 'style']
}

Tradeoff

  • Default remains secure (false)
  • This is a self-hosted opt-in only
  • Enabling it intentionally broadens the markdown rendering surface
  • Operators who enable it accept the CSS/UI-injection risk as a deployment decision
  • The only realistic risk is url() for resource loading, which cannot execute JavaScript

Screenshots

Before (ALLOW_INLINE_STYLES=false, default)

All style attributes stripped — layout completely broken, rendered as plain text:

Chatbot (Web App): Card layout lost — "Project: Dify Test Project" and "Status Active" displayed as unstyled plain text without flex layout, colors, or borders.

DOM evidence: <div>\n Project: Dify Test Project\n </div> — no style attribute

After (ALLOW_INLINE_STYLES=true)

All style attributes preserved — card layout renders correctly:

Chatbot (Web App): Card rendered with display: flex, border-radius: 12px, font-weight: 700, colors applied.

Preview Panel (Console): Same card layout rendered correctly in the workflow debug/preview panel — confirmed that the fix applies to all rendering contexts (chatbot, preview, result panel) since they all use the same StreamdownWrapper component.

DOM evidence: <div style="display: flex; gap: 20px; padding: 24px; background: rgb(255, 255, 255); border-radius: 12px; border: 1px solid rgb(224, 230, 237);">

Verification

Tested on Dify 1.13.3 with Docker Compose (self-hosted):

  1. Deployed with ALLOW_INLINE_STYLES=false → styles stripped ✅
  2. Set ALLOW_INLINE_STYLES=true in .envdocker compose restart → styles preserved ✅
  3. Verified in both published chatbot and console preview panel

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran cd web && npx lint-staged (frontend) to appease the lint gods

@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Apr 8, 2026
@github-actions github-actions Bot added the web This relates to changes on the web. label Apr 8, 2026
@dosubot dosubot Bot added the javascript Pull requests that update javascript code label Apr 8, 2026
@s-kawamura-upgrade s-kawamura-upgrade force-pushed the feature/allow-inline-styles branch from 578c09f to d1f4e71 Compare April 8, 2026 05:01
@WTW0313
Copy link
Copy Markdown
Member

WTW0313 commented Apr 8, 2026

Hello, @s-kawamura-upgrade. The PR looks fine to me functionally, but CI is still failing on Main CI Pipeline / Style Check / Web Style.

It’s likely worth checking the Web style/lint output first before merging. From the current diff, the most likely candidates are:

  • key ordering in web/env.ts (clientSchema is marked with /// keep-sorted)
  • formatting/sorting expectations in the frontend config files

Also, this branch is currently out of date with main, so it would be better to update the branch and rerun CI before making a final decision.

@s-kawamura-upgrade s-kawamura-upgrade force-pushed the feature/allow-inline-styles branch from 8308da5 to 5ea248b Compare April 8, 2026 07:52
@s-kawamura-upgrade
Copy link
Copy Markdown
Contributor Author

Thanks for the review, @WTW0313.

I addressed both points:

  • Fixed key ordering/sorting issues (including web/env.ts with /// keep-sorted and related frontend config ordering).
  • Rebased this branch onto the latest main and force-pushed with lease.

The latest head now includes these fixes, and CI has been retriggered by the push.
Could you please take another look when you have a moment?

s-kawamura-upgrade and others added 2 commits April 8, 2026 17:02
…rkdown rendering

Add a deployment-level environment variable `ALLOW_INLINE_STYLES` (default: `false`)
that allows self-hosted operators to opt-in to inline style attributes in Markdown
rendering. This restores styled Jinja2 template support broken by the streamdown
migration in v1.13.1 (langgenius#32971), following the same pattern as `ALLOW_UNSAFE_DATA_SCHEME`.

When enabled, `style` is appended to the global attribute allowlist in
`rehype-sanitize`, so all HTML elements may carry inline styles.

Closes langgenius#34377

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@s-kawamura-upgrade s-kawamura-upgrade force-pushed the feature/allow-inline-styles branch from 5ea248b to 90ada72 Compare April 8, 2026 08:02
@s-kawamura-upgrade
Copy link
Copy Markdown
Contributor Author

Sorry for the extra update — after posting my previous comment, GitHub still showed "This branch is out-of-date with the base branch," so I rebased again onto the latest main and force-pushed with lease.

The branch should now be up to date.

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Apr 8, 2026
@WTW0313 WTW0313 added this pull request to the merge queue Apr 8, 2026
Merged via the queue into langgenius:main with commit 0e0bb35 Apr 8, 2026
35 checks passed
HanqingZ pushed a commit to HanqingZ/dify that referenced this pull request Apr 23, 2026
…rkdown rendering (langgenius#34719)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

javascript Pull requests that update javascript code lgtm This PR has been approved by a maintainer needs-revision size:S This PR changes 10-29 lines, ignoring generated files. web This relates to changes on the web.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Add NEXT_PUBLIC_ALLOW_INLINE_STYLES env var to opt-in inline CSS in Markdown rendering

2 participants