Skip to content

Security Headers

Optional: control CORS, framing, HSTS and Content-Security-Policy per deployment. All are unset by default — Boards behaves exactly as before when left blank.

CORS & framing

By default the API accepts cross-origin calls from any origin (needed for embedding Boards in unknown parent sites). Set CORS_ALLOWED_ORIGINS to lock Boards down to a known set of origins instead.

Key Description Default
global.env.CORS_ALLOWED_ORIGINS
Optional: Comma-separated list of origins allowed to embed or cross-origin-call Boards. When set, the API reflects only these origins (Boards' own URL is added automatically) and the frontend restricts framing (CSP frame-ancestors) to them. * matches a single sub-domain label, e.g. https://*.example.com.
Blank = open (any origin).
(open)

A single origin can be set inline. For a longer list, use a YAML folded block (>-) with one origin per line, each ending in a comma:

global:
  env:
    # inline
    CORS_ALLOWED_ORIGINS: https://connections.company.com

    # list
    CORS_ALLOWED_ORIGINS: >-
      https://teams.microsoft.com,
      https://*.teams.microsoft.com,
      https://connections.company.com

HSTS

Strict-Transport-Security is always sent (default max-age=15724800; includeSubDomains). Use these settings to override the default:

Key Description Default
global.env.HSTS_MAX_AGE Optional: max-age in seconds. Non-numeric values fall back to the default. 15724800
global.env.HSTS_INCLUDE_SUBDOMAINS Optional: Set false to drop the includeSubDomains directive. true
global.env.HSTS_PRELOAD Optional: Set true to add the preload directive. false

For example, a two-year policy with preload:

global:
  env:
    HSTS_MAX_AGE: 31536000
    HSTS_INCLUDE_SUBDOMAINS: 'true'
    HSTS_PRELOAD: 'true'

Content-Security-Policy

No CSP is enforced by default (aside from frame-ancestors, set via CORS_ALLOWED_ORIGINS above). Validate a policy in report-only mode first, then enforce it.

Key Description Notes
webfront.env.CSP_REPORT_ONLY
Optional: A candidate policy sent as Content-Security-Policy-Report-Only. The browser reports violations without blocking anything — use it to see what a policy would break before enforcing.
webfront.env.CSP
Optional: An enforced Content-Security-Policy (same syntax as CSP_REPORT_ONLY).
Do not set frame-ancestors here — control framing via CORS_ALLOWED_ORIGINS only, or the two policies intersect and can block framers you intended to allow.

Use a YAML folded block (>-) with one directive per line, each ending in a semicolon. Start in report-only mode, then move the same value to CSP to enforce it.

What Boards needs from a policy

In the table below, API host is where API_GATEWAY points, and Connections host is the Connections deployment Boards is configured against. When either shares the Boards domain, 'self' already covers it and the entry can be dropped.

Directive Value Why Boards needs it
default-src 'self' Safe fallback for anything not listed; Boards itself is served from its own origin.
script-src 'unsafe-inline' Connections/Collab banner only — it injects inline scripts. Drop it on deployments without the banner.
'unsafe-eval' Connections/Collab banner only (its Dojo toolkit) — drop it on deployments without the banner.
Connections host Banner scripts (only when Connections is on a different origin).
style-src 'unsafe-inline' Rich-text formatting (text colour, alignment) is rendered as inline styles; the Connections banner also injects styles.
Connections host Banner stylesheets.
img-src data: blob: Avatars and file thumbnails are fetched via the API and displayed from memory; placeholders and icons are inline data URLs.
https: User content (descriptions, comments) can reference images on any host. Replace with known hosts for a tighter policy — external images then show as broken.
connect-src API host + wss: API host All API calls, file/preview downloads and live updates (WebSocket).
Connections host Banner data requests and notifications.
media-src API host Video/audio file preview.
frame-src API host HTML file preview renders in an iframe served by the API.
form-action 'self' Restricts where forms may submit (prevents form-hijacking). Boards' own forms post to its own origin.
API host Form submits to the API (e.g. sign-in). Drop when the API shares the Boards origin.
Connections host Connections/Collab banner forms (e.g. its search box).
font-src data: Bundled fonts; some are inlined as data URLs.
Connections host Banner icon fonts.
https://static2.sharepointonline.com https://spoprod-a.akamaihd.net Microsoft 365 deployments only: the Microsoft 365 header loads its fonts and icon font from these Microsoft CDNs. Without them the header falls back to system fonts and icons render blank.
worker-src 'self' blob: Offline service worker and the PDF preview worker.
manifest-src 'self' The web-app manifest (install/pin metadata).
object-src 'none' Nothing uses plugins — lock it down.
base-uri 'self' Restricts the page <base> URL. This directive has no default-src fallback, so always set it explicitly.
frame-ancestors do not set Framing is controlled by CORS_ALLOWED_ORIGINS (see above), which emits its own frame-ancestors policy. Browsers enforce every policy — setting it here too means a parent must be allowed by both, which can block framers you meant to allow. It is also ignored in Report-Only mode, so it cannot be validated via CSP_REPORT_ONLY anyway.

Same domain as Connections

The usual Component Pack shape — Boards and its API served from the Connections domain (e.g. connections.example.com/boards and connections.example.com/api-boards). Everything is same-origin, so 'self' covers the API and the Connections banner:

webfront:
  env:
    CSP_REPORT_ONLY: >-
      default-src 'self';
      script-src 'self' 'unsafe-inline' 'unsafe-eval';
      style-src 'self' 'unsafe-inline';
      img-src 'self' data: blob: https:;
      connect-src 'self';
      media-src 'self';
      frame-src 'self';
      form-action 'self';
      font-src 'self' data:;
      worker-src 'self' blob:;
      manifest-src 'self';
      object-src 'none';
      base-uri 'self';

Separate host names

Boards on its own host names (e.g. boards.example.com with the API at api-boards.example.com, Connections at connections.example.com). https://*.example.com covers the API and Connections hosts in one entry — replace it with the explicit host names for a tighter policy:

webfront:
  env:
    CSP_REPORT_ONLY: >-
      default-src 'self';
      script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.example.com;
      style-src 'self' 'unsafe-inline' https://*.example.com;
      img-src 'self' data: blob: https:;
      connect-src 'self' https://*.example.com wss://*.example.com;
      media-src 'self' https://api-boards.example.com;
      frame-src 'self' https://api-boards.example.com;
      form-action 'self' https://*.example.com;
      font-src 'self' data: https://*.example.com;
      worker-src 'self' blob:;
      manifest-src 'self';
      object-src 'none';
      base-uri 'self';

Standalone (no Connections banner)

Without the Connections/Collab banner (e.g. DX deployments), script-src needs no 'unsafe-inline' or 'unsafe-eval' at all, and the Connections host entries go away. For a deployment at boards.example.com with the API at api-boards.example.com:

webfront:
  env:
    CSP_REPORT_ONLY: >-
      default-src 'self';
      script-src 'self';
      style-src 'self' 'unsafe-inline';
      img-src 'self' data: blob: https:;
      connect-src 'self' https://api-boards.example.com wss://api-boards.example.com;
      media-src 'self' https://api-boards.example.com;
      frame-src 'self' https://api-boards.example.com;
      form-action 'self' https://api-boards.example.com;
      font-src 'self' data:;
      worker-src 'self' blob:;
      manifest-src 'self';
      object-src 'none';
      base-uri 'self';

DX: no extra CSP entries. Embedding Boards inside DX pages is controlled by CORS_ALLOWED_ORIGINS (framing), not by this policy.

Whatever the shape, run report-only first — violations surface anything deployment-specific (integrations, customisations) before a policy blocks it.