[BUG] Codicon font blocked by webview CSP font-src — diff markers render as tofu on 2.1.116 (extends #26836)

Open 💬 2 comments Opened Apr 21, 2026 by mttzzz

Preflight Checklist

  • [x] I have searched existing issues — this extends #26836 which was auto-closed for inactivity but remains unfixed on current release
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code (2.1.116)

What's Wrong?

In the Claude Code VS Code Extension chat panel, every diff line renders with an empty tofu square (☐) in the gutter instead of the proper codicon + / glyphs. Root cause: the extension's webview bundles the codicon font as a data:font/ttf;base64,... source in @font-face, but the webview's Content Security Policy does not include data: in its font-src directive, so Chromium silently rejects the font.

This issue was originally reported in #26836 (auto-closed by the stale-bot despite multiple confirmations of it still reproducing). This report adds:

  • A definitive root-cause trace using DevTools FontFace API
  • Verification that the embedded codicon TTF is valid (all 462 PUA glyphs present via cmap fmt 12)
  • A verified, working workaround
  • Two concrete proposed fixes for the extension

What Should Happen?

.codicon-diff-insert / .codicon-diff-remove elements in the diff view render as + and glyphs from the embedded codicon font.

Error Messages/Logs

DevTools Issues tab shows 4 blocked directives on every diff render:

AFFECTED RESOURCES
4 directives
Resource    Status     Directive    Source location
data        blocked    font-src     index.html?id=4cedd4...:0
data        blocked    font-src     index.html?id=96853a...:0
data        blocked    font-src     index.html?id=b44a3b...:0
data        blocked    font-src     index.html?id=fe4090...:0

document.fonts reports the codicon font in error state:

[...document.fonts].filter(f => f.family === 'codicon')
// => [{ status: "error", family: "codicon" }]

The CSS injection itself works — .codicon-diff-insert::before { content: '<PUA char>' } is correctly applied at runtime (verified via getComputedStyle(el, '::before').content), the character is valid (U+EA60 / U+EB3B), but the font to render it failed to load.

Steps to Reproduce

  1. Install Claude Code VS Code Extension v2.1.116 on Windows 11.
  2. Open any project in VS Code, start Claude Code, ask it to edit a file (any Edit/Write tool call triggers the diff view in the chat panel).
  3. Every diff line in the result renders with a tofu square instead of +/ glyphs next to it.
  4. In VS Code: Ctrl+Shift+PDeveloper: Open Webview Developer ToolsIssues tab — see 4 font-src blocked data: violations.
  5. Console:

``js
[...document.fonts].filter(f => f.family === 'codicon').map(f => f.status)
// => ["error"]
``

Root Cause

File: C:\Users\<user>\.vscode\extensions\anthropic.claude-code-<ver>-win32-x64\webview\index.css

@font-face {
  font-family: codicon;
  font-display: block;
  src: url(data:font/ttf;base64,AAEAAAALAIAAAwAw...);  /* ← blocked by CSP font-src */
  font-weight: normal;
  font-style: normal;
}

The embedded TTF is valid (decoded and parsed: sfnt 0x00010000, 462 glyphs, cmap format 12 covers U+EA60 .. U+F101 with all expected codicon codepoints present). The problem is purely CSP — the webview's CSP meta tag defines font-src as an allowlist that excludes data:.

Proposed Fixes (either works)

Option A — Relax the webview CSP. Add data: to the font-src directive of the <meta http-equiv="Content-Security-Policy"> set when constructing the webview HTML. Minimal change, single-line diff.

Option B — Host the font as a webview-local resource. Ship codicon.ttf as an actual file under webview/ (or resources/) and reference it via vscode-resource: / asWebviewUri(), then add the corresponding path to font-src. This is the cleaner long-term solution and matches how VS Code Core serves codicons to its built-in webviews.

Working Workaround (verified)

Patch webview/index.css to prepend local() sources so Chromium uses a system-installed codicon font instead of the blocked data: URI:

@font-face {
  font-family: codicon;
  font-display: block;
  src: local('codicon'), url(data:font/ttf;base64,AAEA...);  /* ← added local() first */
  ...
}

Plus install the codicon font system-wide (decoded from the extension's own embedded @font-face%LOCALAPPDATA%\Microsoft\Windows\Fonts\codicon.ttf, registered in HKCU\Software\Microsoft\Windows NT\CurrentVersion\Fonts, loaded via Win32 AddFontResourceW + WM_FONTCHANGE broadcast).

After VS Code window reload, codicon glyphs render correctly in diff views. local() is not CSP-gated (it doesn't make a network request), so it bypasses the font-src restriction. But this patch is invasive and gets overwritten on every extension update — it's a workaround, not a fix.

Claude Model

N/A (UI rendering bug, not model behavior)

Is this a regression?

Yes — originally reported on 2.1.39 in #26836, still reproduces on 2.1.116.

Last Working Version

Per #26836: last confirmed working in VS Code 1.109.4. Claude Code extension version when it worked: unknown.

Claude Code Version

2.1.116

Platform

Claude.ai (Max subscription)

Operating System

Windows 11 Pro 10.0.26200

Terminal/Shell

VS Code integrated terminal (PowerShell 7)

Additional Information

  • Confirming users on the parent issue (#26836): @MtkN1 on 2.1.109, @jrynlds-pinc on 2.1.116 (2026-04-20).
  • Disabling the bundled CSP or switching to a strict CSP (both recommended by Chromium's Issues panel) would also resolve this, but Option A/B above are the minimal targeted fixes.
  • Unrelated but adjacent observation while inspecting the same webview: Uncaught TypeError: Cannot read properties of undefined (reading 'toUrl') thrown from kv.toUri → kv.asBrowserUri → nP.$loadForeignModule in webview/index.js. Surfaces regularly during diff view init. Filing as a separate issue if it doesn't go away after the font fix.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗