Skip to content

fix(ci): pin build-metrics action tags to full commit SHAs - #1842

Open
JohnMabas wants to merge 2 commits into
Smartdevs17:mainfrom
JohnMabas:fix/pin-action-shas-build-metrics
Open

JohnMabas wants to merge 2 commits into
Smartdevs17:mainfrom
JohnMabas:fix/pin-action-shas-build-metrics

Conversation

@JohnMabas

Copy link
Copy Markdown
Contributor

Summary

Resolves the Semgrep / GitHub Advanced Security findings flagged in PRs #1336, #1337, and #1338.

All three PRs that added the build-metrics job received the same two security alerts:

Mutable tags can be silently repointed by the action owner, enabling supply-chain attacks (as seen in the trivy-action and kics-github-action compromises).

Changes

Pins the three actions used in the build-metrics job to their full 40-character commit SHAs:

Action Mutable tag SHA (pinned)
actions/checkout @v7 → v7.0.1 3d3c42e5aac5ba805825da76410c181273ba90b1
pnpm/action-setup @v4 → v4.4.0 fc06bc1257f339d1d5d8b3a19a8cae5388b55320
actions/setup-node @v4 → v4.4.0 49933ea5288caeca8642d1e84afbd3f7d6820020

No other jobs are modified. Pre-existing mutable tags in the rest of the workflow are a separate concern and out of scope for this targeted fix.

Testing

No functional change — the workflow behaviour is identical. The pinned SHAs resolve to the same releases as the mutable tags they replace.

@drips-wave

drips-wave Bot commented Oct 19, 2026

Copy link
Copy Markdown

Hey @JohnMabas! 👋 It looks like this PR isn't linked to any issue.

If this PR is for one of the issues assigned to you as part of a Wave, please link it to ensure your contribution is tracked properly. You can do this by adding a keyword to the PR description (e.g., Closes #123), or by clicking a button below:

Issue Title
#1713 Add payment link generation with configurable expiry Link to this issue
#1712 Add sponsored transaction (fee-bump) support at checkout Link to this issue
#1715 Add multi-signature approval for charges above a threshold Link to this issue
#1714 Add QR code payment requests for in-person checkout Link to this issue

ℹ️ Learn more about linking PRs to issues

@JohnMabas
JohnMabas deployed to security-review October 19, 2026 15:17 — with GitHub Actions Active
@JohnMabas

Copy link
Copy Markdown
Contributor Author

Hi @drips-wave 👋 — thanks for the heads-up!

This PR is an independent security fix and is intentionally not linked to any Wave issue. It pins the GitHub Actions tags in the build-metrics job to full commit SHAs, addressing Semgrep/GitHub Advanced Security findings #541 and #542 (mutable action tags) that were flagged across PRs #1336, #1337, and #1338. The fix is purely a CI/supply-chain hardening change with no functional impact.

The four Wave issues you listed (#1712, #1713, #1714, #1715) are separate features I am working on — each will have its own dedicated PR once implemented.

JohnMabas added a commit to JohnMabas/SubTrackr that referenced this pull request Oct 19, 2026
…martdevs17#1842

Addresses all 14 critical-severity findings that were blocking merge of
the fix/pin-action-shas-build-metrics PR:

Dockerfile missing USER (5 findings):
- docker/seed.Dockerfile: add non-root appuser
- ml-service/Dockerfile: add non-root appuser
- ml-service/onnx-serving/Dockerfile: add non-root appuser
- services/feature-pipeline/Dockerfile: add non-root appuser
- services/notification/Dockerfile: add non-root appuser in final stage

GCM auth tag length not specified (4 findings):
- backend/pci/cardDataHandler.ts: pass authTagLength:16 to createDecipheriv
- backend/services/shared/encryption/ColumnEncryptionService.ts: same fix
- backend/services/shared/encryption/KmsProvider.ts: same fix
- backend/services/shared/encryption/VaultProvider.ts: same fix

Unparameterized SQL (3 findings):
- backend/analytics/jobs/mvRefreshJob.ts: validate viewName against allowlist
  before interpolating into REFRESH MATERIALIZED VIEW (DDL, no param support)
- backend/services/shared/poolMonitor.ts: cast to safe integer + nosemgrep
- backend/shared/db/connectionPool.ts: cast to safe integer + nosemgrep
  (SET statement_timeout requires numeric literal, not a parameterized value)

GitHub Actions shell injection (2 findings):
- .github/actions/build-contracts/action.yml: assign inputs to env vars,
  read env vars in shell instead of interpolating ${{inputs.*}} directly
- .github/workflows/api-changelog.yml: same pattern

Suppressions register updated in .semgrep/semgrep-suppressions.yml.
Comment thread backend/services/shared/poolMonitor.ts Fixed
Comment thread backend/shared/db/connectionPool.ts Fixed
@JohnMabas
JohnMabas deployed to security-review October 19, 2026 21:33 — with GitHub Actions Active
Semgrep / GitHub Advanced Security flagged mutable action tags in the
build-metrics job (findings Smartdevs17#541 and Smartdevs17#542) across PRs Smartdevs17#1336, Smartdevs17#1337 and
Smartdevs17#1338. Mutable tags can be silently repointed by the action owner,
enabling supply-chain attacks.

Pin all three actions used exclusively by the build-metrics job to their
current full 40-character commit SHAs:

  actions/checkout  v7.0.1  → 3d3c42e5aac5ba805825da76410c181273ba90b1
  pnpm/action-setup v4.4.0  → fc06bc1257f339d1d5d8b3a19a8cae5388b55320
  actions/setup-node v4.4.0 → 49933ea5288caeca8642d1e84afbd3f7d6820020

No other jobs are changed; pre-existing mutable tags in the rest of the
workflow are a separate concern and out of scope for this targeted fix.
…martdevs17#1842

Addresses all 14 critical-severity findings that were blocking merge of
the fix/pin-action-shas-build-metrics PR:

Dockerfile missing USER (5 findings):
- docker/seed.Dockerfile: add non-root appuser
- ml-service/Dockerfile: add non-root appuser
- ml-service/onnx-serving/Dockerfile: add non-root appuser
- services/feature-pipeline/Dockerfile: add non-root appuser
- services/notification/Dockerfile: add non-root appuser in final stage

GCM auth tag length not specified (4 findings):
- backend/pci/cardDataHandler.ts: pass authTagLength:16 to createDecipheriv
- backend/services/shared/encryption/ColumnEncryptionService.ts: same fix
- backend/services/shared/encryption/KmsProvider.ts: same fix
- backend/services/shared/encryption/VaultProvider.ts: same fix

Unparameterized SQL (3 findings):
- backend/analytics/jobs/mvRefreshJob.ts: validate viewName against allowlist
  before interpolating into REFRESH MATERIALIZED VIEW (DDL, no param support)
- backend/services/shared/poolMonitor.ts: cast to safe integer + nosemgrep
- backend/shared/db/connectionPool.ts: cast to safe integer + nosemgrep
  (SET statement_timeout requires numeric literal, not a parameterized value)

GitHub Actions shell injection (2 findings):
- .github/actions/build-contracts/action.yml: assign inputs to env vars,
  read env vars in shell instead of interpolating ${{inputs.*}} directly
- .github/workflows/api-changelog.yml: same pattern

Suppressions register updated in .semgrep/semgrep-suppressions.yml.
@JohnMabas
JohnMabas force-pushed the fix/pin-action-shas-build-metrics branch from e7cde6a to bb888b9 Compare October 19, 2026 22:00

try {
await this.db.query(`REFRESH MATERIALIZED VIEW CONCURRENTLY ${viewName}`);
await this.db.query(`REFRESH MATERIALIZED VIEW CONCURRENTLY ${viewName}`); // nosemgrep: semgrep.subtrackr.sql.unparameterized-query -- reason: REFRESH MATERIALIZED VIEW is DDL and does not support parameterized identifiers; viewName is validated against an internal allowlist and an identifier-safe regex above
// supported for SET commands. The value is cast to a safe integer from a
// validated config field (not user input).
const timeoutMs = Math.max(0, Math.trunc(Number(this.cfg.queryTimeoutMs)));
await client.query(`SET statement_timeout = ${timeoutMs}`); // nosemgrep: semgrep.subtrackr.sql.unparameterized-query -- reason: SET statement_timeout requires a numeric literal; parameterised queries are not supported for SET commands; value is an integer-cast config field, not user input
// parameterised values. The timeout comes from a validated config field
// (not user input) and is explicitly cast to a safe integer.
const timeoutMs = Math.max(0, Math.trunc(Number(config.statementTimeout ?? 30_000)));
await client.query(`SET statement_timeout = ${timeoutMs}`); // nosemgrep: semgrep.subtrackr.sql.unparameterized-query -- reason: SET statement_timeout requires a numeric literal; parameterised queries are not supported for SET commands; value is an integer-cast config field, not user input
@JohnMabas
JohnMabas deployed to security-review October 19, 2026 22:04 — with GitHub Actions Active

This branch was successfully deployed

1 active deployment
security-review — bb888b90 Deployed Oct 19, 2026 by JohnMabas via Security Dashboard #1412
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants