Skip to content

fix(security): remove injected api.js loader and revert its dev-script wiring - #1

Open
polylane[bot] wants to merge 1 commit into
mainfrom
polylane/autofix/9uoij9il1bu2
Open

polylane[bot] wants to merge 1 commit into
mainfrom
polylane/autofix/9uoij9il1bu2

Conversation

@polylane

@polylane polylane Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Fixes: Obfuscated loader wired into phoenixdahdev/executor's dev script and marketing build

Developer and CI machines that ran this public fork's documented development command first executed an obfuscated program, which also ran during the marketing site's build. The program had access to environment secrets on those machines, and anyone could clone the repository. After this merges, both commands run only the project's own code.

flowchart TD
  DEV["Developer runs bun run dev"] --> PKG["package.json dev: node api.js first"]
  PUSH["Push to main"] --> DEP["deploy.yml builds apps/marketing"]
  PKG --> API["api.js loader on main (blob af5d04e3)"]
  DEP --> ASTRO["loader appended to astro.config.mjs"]
  API --> EXEC["Attacker code runs with host secrets"]
  ASTRO --> EXEC
  FIX["Fix: delete api.js, restore 3 files to pre-injection 30cfb4d"] -.-> API
  FIX -.-> ASTRO
Loading
Detection evidence

Affected: int_1321d6e42001abbn5dq5um86

Why this fix

The injected commit is the decisive evidence: it does not exist upstream, it adopts upstream pull request UsefulSoftwareCo#1763's message and author, and it wires the payload into the commands a developer or the deploy workflow runs. The payload decodes with the same accessor name and dynamic-execution construct as the campaign's other copies. Restoring the three touched files to their pre-injection state and deleting the payload closes every entry point on the default branch. The injector is still unidentified, so re-infection and the credentials already exposed on any machine that ran these commands remain open. Exact times, blobs, and references are in the linked investigation.

Fix walkthrough

Watch the fix walkthrough

Watch the fix explained (2:35). Recorded for commit a73d75c07d49a4474a5eabea61bbdb80221d0f54.

Causal chain
  • Signal (alert): Second api.js payload variant on phoenixdahdev/executor (public fork), executed by the dev script
  • Surfacing site: GitHub: phoenixdahdev/executor (integration int_1321d6e42001abbn5dq5um86) at phoenixdahdev/executor:api.js and phoenixdahdev/executor:apps/marketing/astro.config.mjs
  • Mechanism: The default branch main carries an obfuscated loader in api.js and appended to apps/marketing/astro.config.mjs. The root package.json dev script runs node api.js before turbo, and the deploy workflow builds the marketing app, so the loader executes when a developer runs bun run dev or the marketing build runs on push to main. Both files carry the same accessor name F$FsRLfhVq_nVmBU and dynamic-execution construct as the campaign's tracked payload.
  • Producer: Obfuscated loader injected into phoenixdahdev/executor, instance commit ef91489, at phoenixdahdev/executor:api.js
  • Trigger: commit ef91489 (adopts upstream PR Connect dialog: search the integrations.sh catalog UsefulSoftwareCo/executor#1763 metadata) added the loader and wired it into the dev script and marketing config
  • What happens to the failed unit today: package.json dev script (documented in README.md and RUNNING.md as bun run dev); .github/workflows/deploy.yml deploy-marketing job runs bun run --cwd apps/marketing build
  • Blast radius: unknown other resource(s), unknown other tenant(s); data at risk: Environment secrets on developer machines that run bun run dev and the CI build credentials for the marketing deploy; the repository is public, so any clone is exposed.
  • Producer evidence:
    • GET /repos/phoenixdahdev/executor/contents/api.js returns sha af5d04e37c0fecb9a49ba22df617a4e940feb10a, size 29135; the same endpoint upstream returns 404
    • git show ef91489 --stat: adds api.js (+1), edits package.json dev (+1 -1), edits apps/marketing/astro.config.mjs (+4 -1), adds 3 .gitignore lines
    • git diff upstream/main -- apps/marketing/astro.config.mjs shows the gap; upstream copy is 1248 bytes with no createRequire
    • The injector's identity is not established; the commit forges upstream PR Connect dialog: search the integrations.sh catalog UsefulSoftwareCo/executor#1763's message and author and is unsigned (verified=false).
4 files changed (+2/-9)
  • .gitignore: modified, +0/-3
  • api.js: removed, +0/-1
  • apps/marketing/astro.config.mjs: modified, +1/-4
  • package.json: modified, +1/-1

View thread View autofix


Generated by Polylane. You can ask follow-ups by mentioning @polylane in a comment.

…t wiring

Co-authored-by: polylane[bot] <277585245+polylane[bot]@users.noreply.github.com>
@polylane polylane Bot added polylane severity:high Polylane autofix severity: high labels Oct 17, 2026
@polylane
polylane Bot requested a review from phoenixdahdev October 17, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

polylane severity:high Polylane autofix severity: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant