Skip to content

[APS-19017] fix: pin Semgrep CI image to sha256 digest - #1129

Open
Rohannagariya1 wants to merge 2 commits into
masterfrom
fix/APS-19017-supply-chain-hygiene
Open

Rohannagariya1 wants to merge 2 commits into
masterfrom
fix/APS-19017-supply-chain-hygiene

Conversation

@Rohannagariya1

@Rohannagariya1 Rohannagariya1 commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Security Fix: APS-19017 (Low, supply-chain hygiene)

Single-item PR — pins the Semgrep CI image from a mutable tag to its immutable digest. The other four items in APS-19017 were reviewed and are not included in this PR — reasoning at the bottom.

Actual diff

.github/workflows/Semgrep.yml:

- image: returntocorp/semgrep:1.166.0
+ image: returntocorp/semgrep:1.166.0@sha256:c180f0c93a17b420c0af5006214a29d3c747c5459c732b740191adf657dd0068

Why (INF-007)

A version tag (:1.166.0) can be re-published by whoever owns the Docker Hub account at any time. Attack chain:

  1. Return-to-corp's Docker Hub account gets compromised (credential leak, MFA phishing, insider).
  2. Attacker re-publishes returntocorp/semgrep:1.166.0 with malicious layers added.
  3. Every subsequent CI run of this repo pulls the compromised image on next Semgrep step.
  4. Attacker's code executes inside our CI runner with access to GitHub Actions secrets — including the npm publish token for browserstack-cypress-cli.
  5. Attacker publishes a malicious version of the CLI to every BrowserStack Cypress customer's install.

A sha256 digest is cryptographically immutable — Docker refuses to pull anything whose bytes don't hash to c180f0c9.... Even if Return-to-corp's account is compromised and the tag is re-published, Docker rejects the pull unless the digest matches the specific bytes we pinned to today.

Verification

  • Digest resolved via Docker Hub manifest API on 2026-09-16 — same image bytes master runs against today, just addressed by content-hash instead of tag.
  • CI green post-change: CodeQL x3, semgrep/ci, Semgrep OSS, CodeRabbit.

Other APS-19017 items — NOT in this PR

INF-001 (axios ≥ 1.15.0) — already on master

Confirmed via npm ls axios. No change needed.

INF-005 (mochadevDependencies) — REJECTED

Ticket proposed this to shed the transitive serialize-javascript CVE (GHSA-5c6j-r48x-rmvq). Two problems:

  1. CVE is already mitigated on master. package.json has "overrides": { "serialize-javascript": ">=7.0.5" } — npm respects this override during resolution, so mocha's transitive serialize-javascript resolves to the patched version regardless of mocha's dependency section. The scanner that generated the ticket didn't account for the existing override.

  2. The move would break TestObservability for every default-config Cypress ≥ 10 customer. bin/testObservability/reporter/index.js:12 has:

    const Runnable = require('mocha/lib/runnable'); // need to handle as this isn't present in older mocha versions

    This is a regular require, not the requireModule() helper. Regular require walks up from the file's own location — from a globally-installed CLI's /usr/local/lib/node_modules/browserstack-cypress-cli/bin/testObservability/reporter/, it cannot reach the customer's project node_modules. Combined with:

    • The CLI is globally installed per BS's official docs
    • TestObservability is enabled by default for Cypress ≥ 10

    → moving mocha to devDeps → npm install -g browserstack-cypress-cli uses --production → mocha not installed → next customer session → Runnable require throws MODULE_NOT_FOUND → TestObservability crashes on startup for every default-config Cypress ≥ 10 customer.

INF-008 (files allowlist in package.json) — REJECTED

The files this would hide from the npm tarball (.github/, CODEOWNERS, .eslintrc*, .editorconfig) are already public in this GitHub repo. Excluding them from the tarball doesn't protect any information that isn't already at github.com/browserstack/browserstack-cypress-cli. Framed as security in the ticket; is actually hygiene. Deferred as an optional hygiene PR if we want it later.

CSL-003 (constants.js:401 md5 → sha256) — DEFERRED

Changes the upload-dedup hash algorithm. A client-only bump would leave the CLI sending SHA-256 hashes that BS's server-side dedup (currently keyed on MD5 length/format) doesn't recognize → every next upload for every customer becomes a full re-upload until the SHA-256 cache warms. Needs client+server coordination and one-time bandwidth-spike acceptance. Separate ticket.

Jira Ticket

https://browserstack.atlassian.net/browse/APS-19017

@Rohannagariya1
Rohannagariya1 requested a review from a team as a code owner June 15, 2026 07:45
…mage, add files allowlist [APS-19017]

INF-005: remove mocha from dependencies (kept in devDependencies); CLI loads mocha from user project via requireModule(), prod copy unnecessary. npm ls mocha --omit=dev now empty.

INF-007: pin Semgrep CI image returntocorp/semgrep -> @sha256:f4791a54c891eabe1188248135574e6e03dfc31dfd3f3b747c7bec7079bfed1b (latest as of 2026-06-15).

INF-008: add package.json files allowlist [bin/, README.md, LICENSE.md] so npm pack no longer ships .github/, CODEOWNERS, .nycrc.yml, test/. Verified via npm pack --dry-run.

NOT applied: CSL-003 md5->sha256 (constants.js) — behavioral change to upload-dedup hash; needs human sign-off.

Resolves: APS-19017

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited), Workspace UI (inherited)

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: fdf8a7a9-4b32-4985-8221-bffd3f51ed36

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

Comment thread package.json Outdated
"description": "BrowserStack Cypress CLI for Cypress integration with BrowserStack's remote devices.",
"main": "index.js",
"files": [
"bin/",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove it

…ride; mocha bundling load-bearing for reporter/index.js:12 require
@Raghav11-11
Raghav11-11 force-pushed the fix/APS-19017-supply-chain-hygiene branch from 0025b72 to 38c4afd Compare September 17, 2026 10:26
@Raghav11-11 Raghav11-11 changed the title [APS-19017] fix: supply-chain hygiene (mocha->devDeps, pin Semgrep image, files allowlist) [APS-19017] fix: pin Semgrep CI image to sha256 digest Sep 17, 2026
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.

3 participants