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]

Reply via email to