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
47 changes: 47 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Dependabot — automated dependency PRs for paybot-sdk
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The PR title and description indicate that this PR adds a "security scanner bundle" including CodeQL (.github/workflows/codeql.yml) and OSV-Scanner (.github/workflows/osv-scanner.yml) workflows. However, these files are missing from the current diff. Please ensure all components of the bundle are included in the PR.

#
# What: Weekly version-update PRs for npm packages and GitHub Actions.
# Security updates (CVE fixes) are auto-enabled separately via the
# /repos/{owner}/{repo}/automated-security-fixes API and surface
# regardless of the schedule below.
# Why: Keep supply chain current; minimize lag between CVE disclosure and patch.
# paybot-sdk is published to npm — downstream consumer surface area
# makes timely security patching especially load-bearing.
# Gate: PRs run through CI + the SINKRA chain. @qa flags risk, @devops merges.
#
# Reference:
# - https://docs.github.com/en/code-security/dependabot
# - Precedent: paybot-core PR #3 (merged 6dc6f5aa, 2026-05-22)
version: 2
updates:
# ---------- npm ecosystem ----------
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "UTC"
open-pull-requests-limit: 10
commit-message:
prefix: "deps"
include: "scope"
labels:
- "dependencies"
- "npm"
Comment on lines +29 to +31
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Given the strict merge process described in the PR summary (requiring a 12-check matrix pass and manual merge by @devops), receiving multiple individual PRs for dependency updates every week could lead to significant process overhead. Consider using Dependabot's grouped updates feature to bundle these into a single PR. This would allow the team to run the QA matrix once for the entire set of weekly updates.

    labels:
      - "dependencies"
      - "npm"
    groups:
      npm-dependencies:
        patterns:
          - "*"


# ---------- GitHub Actions ecosystem ----------
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "UTC"
open-pull-requests-limit: 5
commit-message:
prefix: "ci"
include: "scope"
labels:
- "dependencies"
- "github-actions"
Comment on lines +45 to +47
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Similar to the npm ecosystem, grouping GitHub Actions updates can help reduce the number of PRs that need to go through the manual QA and merge process.

    labels:
      - "dependencies"
      - "github-actions"
    groups:
      action-dependencies:
        patterns:
          - "*"

65 changes: 65 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# CodeQL — SAST (Static Application Security Testing) for paybot-sdk
#
# What: GitHub's CodeQL engine analyzing JavaScript/TypeScript for SQL
# injection, unsafe regex, hardcoded crypto, taint flows, and other
# security issues.
# When: On PRs targeting main, on push to main, and weekly (Monday 06:00 UTC).
# Output: SARIF results uploaded natively to GitHub Code Scanning (Security tab).
# Public repo: SARIF upload to Security tab is free (no GHAS needed).
# Contrast with paybot-core (private personal-account) which required
# `upload: false` + artifact workaround — see paybot-core PR #3.
# Gate: Failed scans (any error severity finding) fail the job → PR blocked
# via branch protection once required_status_checks is updated to
# include "Analyze (javascript-typescript)" (verbatim from
# `gh pr checks` after first run).
#
# Reference:
# - https://docs.github.com/en/code-security/code-scanning
# - Precedent: paybot-core PR #3 (merged 6dc6f5aa, 2026-05-22)
name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Monday 06:00 UTC — weekly scheduled scan independent of PR activity
- cron: '0 6 * * 1'

permissions:
actions: read
contents: read
security-events: write

jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
timeout-minutes: 360

strategy:
fail-fast: false
matrix:
language: [javascript-typescript]

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

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended

- name: Autobuild
uses: github/codeql-action/autobuild@v3

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
Comment on lines +47 to +60
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Non-SHA pinned uses in CodeQL workflow:"
rg -nP '^\s*uses:\s*[^@]+@(?!(?:[0-9a-f]{40})\b).+$' .github/workflows/codeql.yml

Repository: RBKunnela/paybot-sdk

Length of output: 287


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Relevant section of .github/workflows/codeql.yml:"
nl -ba .github/workflows/codeql.yml | sed -n '35,80p'

Repository: RBKunnela/paybot-sdk

Length of output: 175


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Relevant section of .github/workflows/codeql.yml (lines 35-80):"
awk 'NR>=35 && NR<=80 {printf "%d:%s\n", NR, $0}' .github/workflows/codeql.yml

Repository: RBKunnela/paybot-sdk

Length of output: 1073


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Searching for persist-credentials / permissions in .github/workflows/codeql.yml:"
rg -n --hidden -S "persist-credentials|permissions:" .github/workflows/codeql.yml

Repository: RBKunnela/paybot-sdk

Length of output: 161


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Relevant section of .github/workflows/codeql.yml (lines 15-45):"
awk 'NR>=15 && NR<=45 {printf "%d:%s\n", NR, $0}' .github/workflows/codeql.yml

Repository: RBKunnela/paybot-sdk

Length of output: 836


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n --hidden "persist-credentials" .github/workflows/codeql.yml || true

Repository: RBKunnela/paybot-sdk

Length of output: 46


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Non-SHA pinned uses in CodeQL workflow:"
rg -nP '^\s*uses:\s*[^@]+@(?!(?:[0-9a-f]{40})\b).+$' .github/workflows/codeql.yml

Repository: RBKunnela/paybot-sdk

Length of output: 287


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Non-SHA pinned uses in CodeQL workflow:"
rg -nP '^\s*uses:\s*[^@]+@(?!(?:[0-9a-f]{40})\b).+$' .github/workflows/codeql.yml

Repository: RBKunnela/paybot-sdk

Length of output: 287


Pin CodeQL workflow GitHub Actions to immutable commit SHAs (and harden checkout credentials)

  • .github/workflows/codeql.yml uses mutable action tags: actions/checkout@v4, github/codeql-action/{init,autobuild,analyze}@v3``; pin each to its 40-char commit SHA to prevent supply-chain drift.
  • The actions/checkout step does not set with: persist-credentials: false; add it to avoid persisting the default token in git config.
Suggested hardening diff
-      - name: Checkout
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@<40-char-commit-sha>

-      - name: Initialize CodeQL
-        uses: github/codeql-action/init@v3
+      - name: Initialize CodeQL
+        uses: github/codeql-action/init@<40-char-commit-sha>

-      - name: Autobuild
-        uses: github/codeql-action/autobuild@v3
+      - name: Autobuild
+        uses: github/codeql-action/autobuild@<40-char-commit-sha>

-      - name: Perform CodeQL Analysis
-        uses: github/codeql-action/analyze@v3
+      - name: Perform CodeQL Analysis
+        uses: github/codeql-action/analyze@<40-char-commit-sha>
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 47-48: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 48-48: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 51-51: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 57-57: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 60-60: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/codeql.yml around lines 47 - 60, Update the workflow steps
that use mutable action tags: replace uses: actions/checkout@v4 and uses:
github/codeql-action/init@v3, github/codeql-action/autobuild@v3,
github/codeql-action/analyze@v3 with their corresponding immutable 40-character
commit SHAs, and in the Checkout step add with: persist-credentials: false to
avoid persisting the default token; specifically edit the steps named
"Checkout", "Initialize CodeQL", "Autobuild", and "Perform CodeQL Analysis" to
pin the uses: fields to exact commit SHAs and add the persist-credentials: false
key under the Checkout step's with block.

with:
category: "/language:${{ matrix.language }}"
# Public repo: SARIF upload to Security tab is free (no GHAS needed).
# `upload: true` is the default; declared explicitly for clarity.
upload: true
64 changes: 64 additions & 0 deletions .github/workflows/osv-scanner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# OSV-Scanner — vulnerability scanning against Google's OSV.dev database
#
# What: Scans lockfiles + manifests against the Open Source Vulnerabilities
# database. Broader coverage than Dependabot alone (npm advisories +
# GHSA + GitHub-specific feeds + ecosystem-specific feeds).
# When: On PRs targeting main, on push to main, and weekly (Tuesday 06:00 UTC).
# Tuesday cadence intentionally offsets from CodeQL (Monday) to spread
# CI load and produce two independent weekly signals.
# Output: SARIF uploaded natively to GitHub Code Scanning (Security tab).
# Public repo: third-party SARIF upload is free (no GHAS needed).
# Contrast with paybot-core (private personal-account) which required
# `upload-sarif: false` — see paybot-core PR #3.
# Gate: Failed scans block PR via branch protection once added to required
# status checks (verbatim context name from `gh pr checks` after
# first run).
#
# Note on design: we use the single (non-PR-diff) reusable workflow for ALL
# events. The PR-diff reusable variant requires both branches
# to have scannable lockfiles to compute a diff, which is
# brittle for short-lived branches. The full-scan flavor is
# more robust and gives identical signal for our gating purposes.
#
# Anti-patterns avoided (from paybot-core PR #3):
# - AP #2: OSV-Scanner publishes only EXACT version tags. `@v2` is NOT a
# valid alias — must pin to `@v2.2.1` (Dependabot github-actions
# will surface upgrades).
# - AP #3: Reusable-workflow callers cannot set per-job `permissions:`
# overrides — they are silently dropped. Permissions MUST be at
# workflow level (top of file, before `jobs:`).
#
# Reference:
# - https://github.com/google/osv-scanner-action
# - Precedent: paybot-core PR #3 (merged 6dc6f5aa, 2026-05-22)
name: OSV-Scanner

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Tuesday 06:00 UTC — offset from CodeQL (Monday) to spread CI load
- cron: '0 6 * * 2'

# Workflow-level permissions are inherited by reusable workflow calls.
# Per-job `permissions:` on a reusable-workflow `uses:` is silently dropped
# (paybot-core PR #3, AP #3).
permissions:
actions: read
contents: read
security-events: write

jobs:
scan:
# AP #2: exact tag, not `@v2` major alias.
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v2.2.1"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Non-SHA pinned uses in OSV workflow:"
rg -nP '^\s*uses:\s*[^@]+@(?!(?:[0-9a-f]{40})\b).+$' .github/workflows/osv-scanner.yml

Repository: RBKunnela/paybot-sdk

Length of output: 192


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "osv-scanner workflow context (lines 40-80):"
nl -ba .github/workflows/osv-scanner.yml | sed -n '40,80p'

echo
echo "All non-SHA pinned `uses:` in this workflow:"
rg -nP '^\s*uses:\s*[^@]+@(?!(?:[0-9a-f]{40})\b).+$' .github/workflows/osv-scanner.yml

Repository: RBKunnela/paybot-sdk

Length of output: 169


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/osv-scanner.yml"

echo "File line count:"
wc -l "$FILE"

echo
echo "osv-scanner workflow context (lines 45-70):"
awk 'NR>=45 && NR<=70 {printf "%d:%s\n", NR, $0}' "$FILE"

echo
echo "All non-SHA pinned `uses:` in this workflow:"
rg -nP '^\s*uses:\s*[^@]+@(?!(?:[0-9a-f]{40})\b).+$' "$FILE"

Repository: RBKunnela/paybot-sdk

Length of output: 1073


Pin OSV reusable workflow uses: to an immutable commit SHA (not @v2.2.1).

The workflow calls:
google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v2.2.1
Tags are mutable, so the referenced workflow content can change without this repo updating.

Suggested hardening diff
-    uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v2.2.1"
+    uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@<40-char-commit-sha>"
🧰 Tools
🪛 zizmor (1.25.2)

[error] 56-56: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/osv-scanner.yml at line 56, The workflow references the
OSV reusable workflow using a mutable tag in the uses string
("google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v2.2.1");
replace that tag with the corresponding immutable commit SHA for the
google/osv-scanner-action repository (e.g.,
.github/workflows/osv-scanner-reusable.yml@<COMMIT_SHA>) so the action content
is pinned; locate the uses line in .github/workflows/osv-scanner.yml and update
it to the commit SHA obtained from the upstream repo (ensure the SHA matches the
desired v2.2.1 state).

with:
scan-args: |-
--recursive
--skip-git
./
# Public repo: SARIF upload to Security tab is free (no GHAS needed).
# `upload-sarif: true` is the default; declared explicitly for clarity.
upload-sarif: true
Loading