Aman-Mittal opened a new issue, #363:
URL: https://github.com/apache/fineract-backoffice-ui/issues/363
The `build` job runs with full network access:
```yaml
build:
name: Production Build
needs: dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@...
- uses: actions/setup-node@...
- run: npm ci
- run: npm run build
```
Nothing asserts that `npm run build` itself reaches the network. It always
has it, so a build step that quietly fetches a remote resource passes CI and
looks identical to one that does not.
That is not hypothetical: it is exactly how the Google Fonts dependency
survived. Angular's font inlining downloaded `fonts.googleapis.com` during
every production build and hard-failed without it — and CI was green
throughout, because CI is never offline. It was found by an audit, not by a
check. #362 / #361 fix that one instance; **nothing stops the next one.**
## Why it matters
ASF release policy expects a release to be buildable from its source
package. A build that silently depends on a third-party host is not
reproducible by a verifier working from the tarball, and the dependency is
invisible until someone builds in a restricted environment — typically after a
release, not before.
Ways a build-time fetch can reappear, none of which CI would currently
notice:
- any webfont `<link>` in `src/index.html`, via `optimization.fonts.inline`
(the original case)
- a remote `@import` or `url()` in a stylesheet
- a `curl`/`fetch` in a build script under `scripts/`
- a dependency `postinstall` that downloads a binary
- a remote asset URL resolved at build time
## Proposal
Add a CI job that installs dependencies **with** network and then runs the
production build **without** it.
The distinction matters and should be stated explicitly wherever this lands:
`npm ci` legitimately needs the registry, and a mirror or cache satisfies it.
The build must not need anything.
```yaml
offline-build:
name: Offline Production Build
needs: dependencies
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@...
- uses: actions/setup-node@...
- run: npm ci # network allowed: registry only
- name: Build with no network access
run: <isolation mechanism> npm run build -- --configuration
production
```
### Isolation mechanism — needs deciding, and verifying on the runner
Listed with the caveats rather than a recommendation, because the first one
has a real question mark over it:
1. **`unshare -rn npm run build`** — what the audit used locally, and the
smallest change. But `ubuntu-latest` is now Ubuntu 24.04, which restricts
unprivileged user namespaces via
`kernel.apparmor_restrict_unprivileged_userns`. **This needs testing on the
runner before being adopted**; it may need `sudo sysctl -w
kernel.apparmor_restrict_unprivileged_userns=0` first, which weakens the case
for it being the "small" option.
2. **`docker run --network none`** with the workspace and `node_modules`
mounted, e.g. against `node:24-alpine` to match `deploy/Dockerfile`'s builder
stage. Most robust and unambiguous — no network namespace tricks, no sysctl.
Costs an image pull and a mount.
3. **`sudo iptables` egress block** after `npm ci`. Runners have
passwordless sudo. Blunt, and needs care to keep loopback up.
Option 2 is the least likely to break silently. Whatever is chosen, the job
must fail loudly and surface the underlying error — the original failure was
legible (`Inlining of fonts failed … over the internet`) and that legibility is
the point.
### Optional: a matching `ga:check` gate
`scripts/ga-check.mjs` already has a precedent for this shape in the
`headers` gate, which inspects `deploy/nginx.conf` statically rather than
making HTTP requests. A gate asserting that `.github/workflows/ci.yml` contains
an offline build job would keep the invariant visible in `npm run ga:check`
alongside `external-fonts`, without making the script itself run a build.
Worth doing only if the CI job is added first; the gate is documentation of
the guard, not the guard.
## Acceptance
- A CI job proves `npm run build -- --configuration production` succeeds
with no network access, after `npm ci`.
- Reintroducing a build-time fetch fails that job. Verifiable by temporarily
restoring a Google Fonts `<link>` in `src/index.html` and confirming the job
goes red — the same negative test used for the `external-fonts` gate in #361.
- `DOCS/CI_CHECKS.md` documents the job and, explicitly, why `npm ci` is
exempt.
## Context
- #362 — the Google Fonts dependency this would have caught
- #361 — the fix, and the `external-fonts` gate that guards the *source* but
not the *build*
- `audit/GOOGLE-FONTS-ASF-AUDIT.md` §6 — the online/offline build results,
and why an unpinned build-time fetch is a reproducibility problem distinct from
the offline failure itself
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]