apache / apache/fineract-backoffice-ui
The production CSP blocks Angular's critical-CSS onload and the federation blob: module, so the main stylesheet never applies in the container
- Dominant language
- TypeScript
- Stars
- 15
- Forks
- 60
- Avg merge
- 10h 15m
- Merged PRs (30d)
- 108
Description
Found while verifying the removal of the Google Fonts dependency. **Neither defect is caused by that work** — both reproduce on `main` @ `82e9a209`. Filing separately so the font change stays scoped.
Both are the same class of problem: `deploy/nginx.conf` sets a strict `script-src 'self'`, and Angular's production output depends on script execution that the policy correctly refuses. The CSP is right; the build output is what does not fit it.
## 1. The main stylesheet never applies — `media` stays `print`
Angular's `inlineCritical` optimisation emits a deferred stylesheet:
```html
```
`script-src 'self'` carries no `'unsafe-inline'` and no `'unsafe-hashes'`, so the inline `onload` handler is blocked and `media` never flips to `all`:
```
[error] Executing inline event handler violates the following Content Security Policy
directive 'script-src 'self''. Either the 'unsafe-inline' keyword, a hash
('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.
... The action has been blocked.
```
Measured in Chrome against a container built from `deploy/Dockerfile`, and against the same build served without the CSP header:
| | behind the production CSP | same build, no CSP |
| --- | --- | --- |
| `link[rel=stylesheet].media` | `print` | `all` |
With JavaScript enabled the `` fallback does not apply either, so only the inlined critical CSS takes effect on screen — the Ionic bundle and the compiled component styles do not.
## 2. The federation `blob:` module is blocked
```
[error] Loading the script 'blob:http://.../' violates the following Content Security
Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly
set, so 'script-src' is used as a fallback. The action has been blocked.
[error] Uncaught TypeError: Failed to fetch dynamically imported module: blob:http://.../
```
`es-module-shims` / `@angular-architects/native-federation` builds a module as a `blob:` URL and imports it. `script-src 'self'` does not cover `blob:`, so the dynamic import fails.
## Reproduce
```bash
docker build -f deploy/Dockerfile -t fbui:csp-check .
docker run --rm -d --name fbui-csp -p 8080:80 fbui:csp-check
# open http://127.0.0.1:8080/ and read the browser console
```
On `82e9a209` the console shows 39 errors. 35 of them were blocked Google Fonts requests and are gone once the webfont is removed; **these 4 remain**.
## Possible directions
Deliberately not proposing a fix — each option trades away part of a CSP the project configured on purpose, so the choice deserves its own discussion:
1. `"optimization": { "styles": { "inlineCritical": false } }` in the production configuration of `angular.json`. Removes the `onload` pattern entirely at the cost of a small first-paint regression. Addresses defect 1 only, and is the smallest change.
2. Admitting `blob:` to `script-src` for defect 2. This widens the policy, and is worth weighing against whether native federation needs to be active in the shipped artifact at all.
3. A nonce-based CSP via `ngCspNonce`, which requires the static nginx server to inject a per-response nonce. Largest change, and the only one that keeps both the strict policy and the current build output.
Whichever is chosen, `scripts/ga-check.mjs` is the natural place to gate it, alongside the existing `headers` gate — a rendering defect that only appears behind the production CSP is exactly the kind that survives review otherwise.
## References
- `security.md` §4 — the trust boundary the CSP sits on
- `deploy/nginx.conf` — the policy in question
- `DOCS/FONTS.md` — the font change during which this surfaced
Contributor guide
Research direction
Start by building and running deploy/Dockerfile as described, then compare the browser console and stylesheet media behavior behind the CSP. Read angular.json, deploy/nginx.conf, scripts/ga-check.mjs, and security.md §4 before choosing among the listed directions. Done means the production container no longer exhibits the four remaining CSP-related failures and the regression is covered by the existing gate.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, docker, nginx, typescript
- Domain
- devops, frontend, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100