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
11 changes: 8 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
name: Test on Node ${{ matrix.node-version }}
runs-on: ubuntu-latest

permissions:
contents: read

strategy:
fail-fast: false
matrix:
Expand All @@ -25,10 +28,12 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
Expand All @@ -53,7 +58,7 @@ jobs:

- name: Upload coverage to Codecov
if: matrix.node-version == '22.x'
uses: codecov/codecov-action@v6
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/lcov.info
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
queries: security-and-quality

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
with:
category: "/language:${{ matrix.language }}"
14 changes: 9 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ on:
type: string

permissions:
contents: write
id-token: write
contents: read

concurrency:
group: release-${{ github.ref }}
Expand All @@ -24,15 +23,20 @@ jobs:
name: Publish to npm
runs-on: ubuntu-latest

permissions:
contents: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.tag || github.ref }}
fetch-depth: 0
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22.x
registry-url: "https://registry.npmjs.org"
Expand Down Expand Up @@ -99,7 +103,7 @@ jobs:

- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.tag != '')
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
tag_name: ${{ inputs.tag || github.ref_name }}
name: ${{ inputs.tag || github.ref_name }}
Expand Down
19 changes: 14 additions & 5 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

permissions: read-all
Expand All @@ -24,25 +27,31 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Run analysis
uses: ossf/scorecard-action@v2.4.3
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true
# Only publish to the public OpenSSF database from main / scheduled
# runs; PR runs are gating-only so they don't pollute the score.
publish_results: ${{ github.event_name != 'pull_request' }}

- name: Upload artifact
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: SARIF file
path: results.sarif
retention-days: 5

# Code-scanning SARIF upload only runs on push/schedule. On PRs the
# token does not have `security-events: write` for fork PRs and the
# alert UI is meant to track main-branch state.
- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@v4
if: github.event_name != 'pull_request'
uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
with:
sarif_file: results.sarif
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## [Unreleased]

## [0.5.2] - 2026-05-05

### Security

- All GitHub Actions in every workflow are now pinned to immutable commit SHAs with a trailing `# vX.Y.Z` comment (`actions/checkout`, `actions/setup-node`, `actions/upload-artifact`, `codecov/codecov-action`, `github/codeql-action/*`, `ossf/scorecard-action`, `softprops/action-gh-release`). Addresses the Scorecard `Pinned-Dependencies` check and prevents tag-retag supply-chain attacks (`.github/workflows/ci.yml`, `.github/workflows/codeql.yml`, `.github/workflows/release.yml`, `.github/workflows/scorecard.yml`)
- `release.yml` no longer grants `contents: write` and `id-token: write` at the workflow level; both are scoped to the `publish` job only. Top-level token now defaults to `contents: read`. Addresses Scorecard `Token-Permissions` (`.github/workflows/release.yml`)
- Every `actions/checkout` step now passes `persist-credentials: false`, so the auth token is dropped from `.git/config` after checkout completes (`.github/workflows/ci.yml`, `.github/workflows/codeql.yml`, `.github/workflows/release.yml`, `.github/workflows/scorecard.yml`)
- `SECURITY.md` added at repo root with private vulnerability reporting instructions (GitHub private advisory + email), supported-versions matrix, response SLA, and out-of-scope notes. Addresses Scorecard `Security-Policy` (`SECURITY.md`)
- Added explicit job-level `permissions: contents: read` to the CI test job for least-privilege defense in depth (`.github/workflows/ci.yml`)
- Scorecard workflow now also runs on `pull_request` so it can be a required status check on protected branches. PR runs skip `publish_results` and the SARIF code-scanning upload — those remain `push` / `schedule` / `branch_protection_rule` only — so the public OpenSSF database and the security tab still reflect main-branch state (`.github/workflows/scorecard.yml`)

### Internal

- Dependabot configured for npm and `github-actions` ecosystems with weekly schedule and grouped updates so dev-only patch/minor bumps land as a single PR (`.github/dependabot.yml`)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ Runs the Jest test suite covering all modules.

Issues and PRs are welcome. Please include tests and keep the API surface small and focused.

## Security

Security vulnerabilities should be reported privately via [GitHub private advisories](https://github.com/Hiprax/errors/security/advisories/new) or by email — see [`SECURITY.md`](./SECURITY.md) for the full policy, supported versions, and response timeline. Please do not open public GitHub issues for security problems.

## License

MIT © Hiprax
59 changes: 59 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Security Policy

## Supported Versions

`@hiprax/errors` follows semantic versioning. Security fixes are applied to the
latest minor release line on the `main` branch. Older minor lines are not
patched separately; please upgrade to the latest version published on
[npm](https://www.npmjs.com/package/@hiprax/errors).

| Version | Supported |
| ------- | ------------------ |
| Latest minor on `main` | :white_check_mark: |
| Older minors | :x: |

## Reporting a Vulnerability

If you believe you have found a security vulnerability in `@hiprax/errors`,
please report it privately. **Do not open a public GitHub issue** for security
problems.

You can choose either of the following channels:

1. **GitHub private vulnerability report (preferred):**
<https://github.com/Hiprax/errors/security/advisories/new>

This opens a private advisory visible only to maintainers. GitHub will
notify the reporter as the report is triaged.

2. **Email:** `sajadkhmz@gmail.com` with the subject `SECURITY: @hiprax/errors`.

When reporting, please include as much of the following as you can:

- A description of the issue and its impact.
- The affected versions of `@hiprax/errors` (and Node.js / Express versions
used to reproduce, if relevant).
- A minimal reproduction (code snippet, repository, or steps).
- Any suggested mitigation, if known.

## What to Expect

- We aim to acknowledge new reports within **5 business days**.
- We will work with the reporter on a timeline for the fix and coordinated
disclosure.
- Once a fix is ready, we publish a patched version to npm and a GitHub
Security Advisory crediting the reporter (unless they ask to remain
anonymous).

## Out of Scope

The following are not considered vulnerabilities for this package:

- Misconfiguration in a consumer's Express application (for example, failing
to register `errorMiddleware` last, or leaking sensitive data through a
custom `cause` in production logs).
- Denial of service caused by extremely large payloads passed into helpers;
upstream input validation is the consumer's responsibility.
- Issues that require modifying the package's internal exports at runtime.

Thank you for helping keep `@hiprax/errors` and its users safe.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hiprax/errors",
"version": "0.5.1",
"version": "0.5.2",
"description": "A modular error handling solution for Express.js applications.",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
Expand Down
Loading