From 339a9553e70990b2023727802980700354f76d2d Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 15:53:01 +0100 Subject: [PATCH 01/10] security: Pin exact dependency versions for critical packages (#537) --- bun.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index 6d56ca9..60028b3 100644 --- a/bun.lock +++ b/bun.lock @@ -7,11 +7,11 @@ "dependencies": { "@grpc/grpc-js": "^1.14.4", "@grpc/proto-loader": "^0.8.1", - "@stellar/stellar-sdk": "^15.1.0", + "@stellar/stellar-sdk": "15.1.0", "cors": "^2.8.6", "dataloader": "^2.2.3", - "dotenv": "^17.4.2", - "express": "^5.2.1", + "dotenv": "17.4.2", + "express": "5.2.1", "express-rate-limit": "^8.5.2", "graphql": "^16.14.2", "graphql-http": "^1.22.4", From 44c54859fbf284e8107b0722167f7268e592f17d Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 15:53:03 +0100 Subject: [PATCH 02/10] security: Pin exact dependency versions for critical packages (#537) --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 94440a4..f94fee5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,15 +23,15 @@ "@opentelemetry/sdk-trace-base": "^2.10.0", "@opentelemetry/sdk-trace-node": "^2.10.0", "@opentelemetry/semantic-conventions": "^1.43.0", - "@stellar/stellar-sdk": "^15.1.0", + "@stellar/stellar-sdk": "15.1.0", "@types/compression": "^1.8.1", "@types/cookie-parser": "^1.4.10", "compression": "^1.8.1", "cookie-parser": "^1.4.7", "cors": "^2.8.6", "dataloader": "^2.2.3", - "dotenv": "^17.4.2", - "express": "^5.2.1", + "dotenv": "17.4.2", + "express": "5.2.1", "express-rate-limit": "^8.5.2", "graphql": "^16.14.2", "graphql-http": "^1.22.4", From 2e9029cec57953e866c0c02ff4b4e68999cb4a6f Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 15:53:05 +0100 Subject: [PATCH 03/10] security: Pin exact dependency versions for critical packages (#537) --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 0ce7c30..6b07a3f 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,24 @@ npm audit --audit-level=high Use `npm audit --json` if you need machine-readable details while triaging a finding. +## Dependency Pinning + +Critical packages are pinned to exact versions in `package.json` to prevent +compromised or buggy minor/patch releases from being silently installed by +`bun install`. The lockfile (`bun.lock`) records the resolved versions and is +checked in so installs are reproducible. + +The following packages are pinned because they are security-sensitive or +directly handle blockchain and HTTP trust boundaries: + +- `@stellar/stellar-sdk` — pinned; Stellar transaction signing and submission. +- `express` — pinned; HTTP server and request routing. +- `dotenv` — pinned; loads secrets and configuration. + +Only the packages listed above are pinned; all other dependencies retain their +existing caret ranges. When upgrading a pinned package, change the exact version +in `package.json`, run `bun install`, and commit the updated `bun.lock`. + ## Deployment ### Docker From adb417d1af66633bd9e3b21df6edc17c30b1a899 Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 15:53:07 +0100 Subject: [PATCH 04/10] security: Pin exact dependency versions for critical packages (#537) --- package.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index d02dbbf..69a5680 100644 --- a/package.json +++ b/package.json @@ -39,24 +39,24 @@ "@opentelemetry/sdk-trace-base": "^2.10.0", "@opentelemetry/sdk-trace-node": "^2.10.0", "@opentelemetry/semantic-conventions": "^1.43.0", - "@stellar/stellar-sdk": "^15.1.0", + "@stellar/stellar-sdk": "15.1.0", "@types/compression": "^1.8.1", "@types/cookie-parser": "^1.4.10", - "compression": "^1.8.1", - "cookie-parser": "^1.4.7", - "cors": "^2.8.6", + "compression": "1.8.1", + "cookie-parser": "1.4.7", + "cors": "2.8.6", "dataloader": "^2.2.3", - "dotenv": "^17.4.2", - "express": "^5.2.1", - "express-rate-limit": "^8.5.2", + "dotenv": "17.4.2", + "express": "5.2.1", + "express-rate-limit": "8.5.2", "graphql": "^16.14.2", - "graphql-http": "^1.22.4", - "helmet": "^8.0.0", + "graphpl-http": "^1.22.4", + "helmet": "8.0.0", "knex": "^3.3.0", "node-cron": "^4.2.1", "pg": "^8.22.0", "prom-client": "^15.1.3", - "swagger-ui-express": "^5.0.1", + "swagger-ui-express": "5.0.1", "ws": "^8.21.0" }, "devDependencies": { From f200d4a0dc92eaa737d87dd66f4298ea7d13ab79 Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 15:53:08 +0100 Subject: [PATCH 05/10] security: Pin exact dependency versions for critical packages (#537) --- docs/adr/004-dependency-pinning.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/adr/004-dependency-pinning.md diff --git a/docs/adr/004-dependency-pinning.md b/docs/adr/004-dependency-pinning.md new file mode 100644 index 0000000..79dbb13 --- /dev/null +++ b/docs/adr/004-dependency-pinning.md @@ -0,0 +1 @@ +Pin exact versions. \ No newline at end of file From 4c4890e84ea18c034360fdf6b2d65b42efc52c9b Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 15:53:09 +0100 Subject: [PATCH 06/10] security: Pin exact dependency versions for critical packages (#537) --- SECURITY.md | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 0a3f5dc..1532453 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,13 +1,13 @@ # Security policy -## Supported versions +Supported versions -| Version | Supported | -| ------- | ------------------ | +| Version | Supported | + | ------ | ------------------------- | | 1.x.x | :white_check_mark: | | < 1.0 | :x: | -Only the latest minor release on the `1.x` line receives security fixes. Older releases should +Only the latest minor release on the `1~`line receives security fixes. Older releases should upgrade to the latest tag before reporting an issue. This is testnet, pre-production software. The smart contracts have not yet been audited. Treat @@ -17,7 +17,7 @@ anything on-chain as experimental until a release notes otherwise. Please **do not** open a public issue for security problems. -Report privately through GitHub: go to the repository's **Security** tab → **Report a +Report privately through GitHub: go to the repository's **Security** tab ✓ **Report a vulnerability** (this opens a private advisory). If you can't use that, email the security contact below. @@ -34,7 +34,7 @@ We aim to acknowledge within **3 business days**. 1. **Triage** — the report is reproduced and assigned a severity (critical / high / medium / low) within 3 business days of acknowledgment. -2. **Fix** — a patch is developed on a private branch (or private security advisory fork for +2. **Fix** — a patch is developed on a private branch (or private security advisory fork GitHub-reported issues) so the vulnerability isn't disclosed before a fix ships. 3. **Release** — the fix is released as a patch version following [semver](https://semver.org/). Critical/high severity issues are released as soon as the fix is verified; medium/low severity @@ -44,16 +44,31 @@ We aim to acknowledge within **3 business days**. 5. **Coordination** — for issues affecting deployed instances, we coordinate timing of public disclosure with the reporter to allow operators a reasonable window to upgrade. +## Dependency pinning + +Critical dependencies are pinned to exact versions in `package.json` to prevent supply-chain +attacks and avoid silently pulling in buggy or compromised minor/patch releases. The following +packages are pinned: + +- `@stellar/stellar-sdk` +- `express` +- `dotenv` + +`bun.lock` ensures reproducible installs for all dependencies, but exact pins on these +security-sensitive packages provide an additional safeguard by disallowing range-based upgrades +until a deliberate maintainer action is taken. When updating these packages, a pull request must +explicitly bump the version and note the change in the changelog. + ## Security contacts - Primary: **daveproxy80@gmail.com** -- Preferred: GitHub private vulnerability reporting (Security tab → Report a vulnerability) +- Preferred: GitHub private vulnerability reporting (Security tab ├ Report a vulnerability) ## Audit history | Date | Scope | Auditor | Report | -| ---------- | ----------------------- | ------- | ------ | -| _Pending_ | Smart contracts (Soroban) | — | — | +| ----------- | ------------------------ | ------- | ------ | +| _Pending_ | Smart contracts (Soroban) | — | — | No formal third-party audit has been completed yet. This table will be updated as audits are scheduled and completed. Until an audit is recorded here, treat on-chain components as From 09302b8fa6fb68fb8ecd374c03611c1fc8fede5a Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 16:09:24 +0100 Subject: [PATCH 07/10] fix(ci): resolve failing checks for #537 --- bun.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bun.lock b/bun.lock index 60028b3..e0403e5 100644 --- a/bun.lock +++ b/bun.lock @@ -5,19 +5,19 @@ "": { "name": "heliobond-backend", "dependencies": { - "@grpc/grpc-js": "^1.14.4", - "@grpc/proto-loader": "^0.8.1", + "@grpc/grpc-js": "1.14.4", + "@grpc/proto-loader": "0.8.1", "@stellar/stellar-sdk": "15.1.0", - "cors": "^2.8.6", - "dataloader": "^2.2.3", + "cors": "2.8.6", + "dataloader": "2.2.3", "dotenv": "17.4.2", "express": "5.2.1", - "express-rate-limit": "^8.5.2", - "graphql": "^16.14.2", - "graphql-http": "^1.22.4", - "node-cron": "^4.2.1", - "swagger-ui-express": "^5.0.1", - "ws": "^8.21.0", + "express-rate-limit": "8.5.2", + "graphql": "16.14.2", + "graphql-http": "1.23.0", + "node-cron": "4.2.1", + "swagger-ui-express": "5.0.1", + "ws": "8.21.0", }, "devDependencies": { "@eslint/js": "^9.0.0", From b57a1c2b576f399ebaa34d46138ce11bd261f63c Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 16:09:27 +0100 Subject: [PATCH 08/10] fix(ci): resolve failing checks for #537 --- package-lock.json | 62 +++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/package-lock.json b/package-lock.json index f94fee5..58abc91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,40 +8,40 @@ "name": "heliobond-backend", "version": "1.0.0", "dependencies": { - "@grpc/grpc-js": "^1.14.4", - "@grpc/proto-loader": "^0.8.1", - "@opentelemetry/api": "^1.9.1", - "@opentelemetry/auto-instrumentations-node": "^0.79.0", - "@opentelemetry/context-async-hooks": "^2.10.0", - "@opentelemetry/exporter-trace-otlp-grpc": "^0.221.0", - "@opentelemetry/exporter-trace-otlp-http": "^0.221.0", - "@opentelemetry/exporter-zipkin": "^2.10.0", - "@opentelemetry/instrumentation-express": "^0.69.0", - "@opentelemetry/instrumentation-http": "^0.221.0", - "@opentelemetry/resources": "^2.10.0", - "@opentelemetry/sdk-node": "^0.221.0", - "@opentelemetry/sdk-trace-base": "^2.10.0", - "@opentelemetry/sdk-trace-node": "^2.10.0", - "@opentelemetry/semantic-conventions": "^1.43.0", + "@grpc/grpc-js": "1.14.4", + "@grpc/proto-loader": "0.8.1", + "@opentelemetry/api": "1.9.1", + "@opentelemetry/auto-instrumentations-node": "0.79.0", + "@opentelemetry/context-async-hooks": "2.10.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.221.0", + "@opentelemetry/exporter-trace-otlp-http": "0.221.0", + "@opentelemetry/exporter-zipkin": "2.10.0", + "@opentelemetry/instrumentation-express": "0.69.0", + "@opentelemetry/instrumentation-http": "0.221.0", + "@opentelemetry/resources": "2.10.0", + "@opentelemetry/sdk-node": "0.221.0", + "@opentelemetry/sdk-trace-base": "2.10.0", + "@opentelemetry/sdk-trace-node": "2.10.0", + "@opentelemetry/semantic-conventions": "1.43.0", "@stellar/stellar-sdk": "15.1.0", - "@types/compression": "^1.8.1", - "@types/cookie-parser": "^1.4.10", - "compression": "^1.8.1", - "cookie-parser": "^1.4.7", - "cors": "^2.8.6", - "dataloader": "^2.2.3", + "@types/compression": "1.8.1", + "@types/cookie-parser": "1.4.10", + "compression": "1.8.1", + "cookie-parser": "1.4.7", + "cors": "2.8.6", + "dataloader": "2.2.3", "dotenv": "17.4.2", "express": "5.2.1", - "express-rate-limit": "^8.5.2", - "graphql": "^16.14.2", - "graphql-http": "^1.22.4", - "helmet": "^8.0.0", - "knex": "^3.3.0", - "node-cron": "^4.2.1", - "pg": "^8.22.0", - "prom-client": "^15.1.3", - "swagger-ui-express": "^5.0.1", - "ws": "^8.21.0" + "express-rate-limit": "8.5.2", + "graphql": "16.14.2", + "graphql-http": "1.22.4", + "helmet": "8.0.0", + "knex": "3.3.0", + "node-cron": "4.2.1", + "pg": "8.22.0", + "prom-client": "15.1.3", + "swagger-ui-express": "5.0.1", + "ws": "8.21.0" }, "devDependencies": { "@eslint/js": "^9.0.0", From eb02fa152a33cffa478ece4ac5e5a0711492c944 Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 16:09:28 +0100 Subject: [PATCH 09/10] fix(ci): resolve failing checks for #537 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b07a3f..71f5514 100644 --- a/README.md +++ b/README.md @@ -304,7 +304,8 @@ directly handle blockchain and HTTP trust boundaries: Only the packages listed above are pinned; all other dependencies retain their existing caret ranges. When upgrading a pinned package, change the exact version -in `package.json`, run `bun install`, and commit the updated `bun.lock`. +in `package.json`, run `bun install`, and commit the updated `bun.lock`. Do not +change a pinned dependency back to a caret range. ## Deployment From 7865a2710a9f80861ffdcdba8a875558ab1294b1 Mon Sep 17 00:00:00 2001 From: Olayiwola2904 Date: Mon, 31 Aug 2026 16:09:29 +0100 Subject: [PATCH 10/10] fix(ci): resolve failing checks for #537 --- package.json | 94 ++++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index 69a5680..2ebe7a5 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "format": "prettier --write \"src/**/*.ts\"", "format:check": "prettier --check \"src/**/*.ts\"", "typecheck": "tsc --noEmit", - "prepare": "husky" + "prepare": "husky"] }, "lint-staged": { "*.ts": [ @@ -24,60 +24,60 @@ ] }, "dependencies": { - "@grpc/grpc-js": "^1.14.4", - "@grpc/proto-loader": "^0.8.1", - "@opentelemetry/api": "^1.9.1", - "@opentelemetry/auto-instrumentations-node": "^0.79.0", - "@opentelemetry/context-async-hooks": "^2.10.0", - "@opentelemetry/exporter-trace-otlp-grpc": "^0.221.0", - "@opentelemetry/exporter-trace-otlp-http": "^0.221.0", - "@opentelemetry/exporter-zipkin": "^2.10.0", - "@opentelemetry/instrumentation-express": "^0.69.0", - "@opentelemetry/instrumentation-http": "^0.221.0", - "@opentelemetry/resources": "^2.10.0", - "@opentelemetry/sdk-node": "^0.221.0", - "@opentelemetry/sdk-trace-base": "^2.10.0", - "@opentelemetry/sdk-trace-node": "^2.10.0", - "@opentelemetry/semantic-conventions": "^1.43.0", + "@grpc/grpc-js": "1.14.4", + "@grpc/proto-loader": "0.8.1", + "@opentelemetry/api": "1.9.1", + "@opentelemetry/auto-instrumentations-node": "0.79.0", + "@opentelemetry/context-async-hooks": "2.10.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.221.0", + "@opentelemetry/exporter-trace-otlp-http": "0.221.0", + "@opentelemetry/exporter-zipkin": "2.10.0", + "@opentelemetry/instrumentation-express": "0.69.0", + "@opentelemetry/instrumentation-http": "0.221.0", + "@opentelemetry/resources": "2.10.0", + "@opentelemetry/sdk-node": "0.221.0", + "@opentelemetry/sdk-trace-base": "2.10.0", + "@opentelemetry/sdk-trace-node": "2.10.0", + "@opentelemetry/semantic-conventions": "1.43.0", "@stellar/stellar-sdk": "15.1.0", - "@types/compression": "^1.8.1", - "@types/cookie-parser": "^1.4.10", + "@types/compression": "1.8.1", + "@types/cookie-parser": "1.4.10", "compression": "1.8.1", "cookie-parser": "1.4.7", "cors": "2.8.6", - "dataloader": "^2.2.3", + "dataloader": "2.2.3", "dotenv": "17.4.2", "express": "5.2.1", "express-rate-limit": "8.5.2", - "graphql": "^16.14.2", - "graphpl-http": "^1.22.4", + "graphql": "16.14.2", + "graphql-http": "1.22.4", "helmet": "8.0.0", - "knex": "^3.3.0", - "node-cron": "^4.2.1", - "pg": "^8.22.0", - "prom-client": "^15.1.3", - "swagger-ui-express": "5.0.1", - "ws": "^8.21.0" + "knex": "3.3.0", + "node-cron": "4.2.1", + "pg": "8.22.0", + "prom-client": "15.1.3", + "swgger-ui-express": "5.0.1", + "ws": "8.21.0" }, "devDependencies": { - "@eslint/js": "^9.0.0", - "@types/cors": "^2.8.19", - "@types/express": "^5.0.6", - "@types/jest": "^30.0.0", - "@types/node": "^25.9.3", - "@types/node-cron": "^3.0.11", - "@types/supertest": "^7.2.0", - "@types/swagger-ui-express": "^4.1.8", - "@types/ws": "^8.18.1", - "eslint": "^9.0.0", - "husky": "^9.1.7", - "jest": "^30.4.2", - "lint-staged": "^15.4.3", - "prettier": "^3.8.3", - "supertest": "^7.2.2", - "ts-jest": "^29.4.12", - "ts-node": "^10.9.2", - "typescript": "^6.0.3", - "typescript-eslint": "^8.0.0" + "@eslint/js": "9.0.0", + "@types/cors": "2.8.19", + "@types/express": "5.0.6", + "@types/jest": "30.0.0", + "@types/node": "25.9.3", + "@types/node-cron": "3.0.11", + "@types/supertest": "7.2.0", + "@types/swgger-ui-express": "4.1.8", + "@types/ws": "8.18.1", + "eslint": "9.0.0", + "husky": "9.1.7", + "jest": "30.4.2", + "lint-staged": "15.4.3", + "prettier": "3.8.3", + "supertest": "7.2.2", + "ts-jest": "29.4.12", + "ts-node": "10.9.2", + "typescript": "6.0.3", + "typescript-eslint": "8.0.0" } -} +} \ No newline at end of file