Skip to content

Release: develop -> main#3951

Merged
davidleomay merged 4 commits into
mainfrom
develop
Jun 23, 2026
Merged

Release: develop -> main#3951
davidleomay merged 4 commits into
mainfrom
develop

Conversation

@github-actions

Copy link
Copy Markdown

Automatic Release PR

This PR was automatically created after changes were pushed to develop.

Commits: 1 new commit(s)

Checklist

  • Review all changes
  • Verify CI passes
  • Approve and merge when ready for production

…urce (#3953)

Azure App Service and Front Door are no longer in the path. The origin
now listens only on localhost:6200 behind Cloudflare Tunnel, so
CF-Connecting-IP is guaranteed to be set by Cloudflare — no spoofing
risk. Also removes the unused Config/Environment import.
…t flow (#3960)

`UnverifiedTxIdBlockchains` (Monero, Zano, Tron, Cardano) accept payer-
submitted tx-ids without on-chain confirmation — by design, because
point-of-sale payments cannot wait for block confirmation. Until now
the API marked the quote `TX_MEMPOOL` with zero validation: any string
was accepted.

A node-side existence check is not feasible across these chains today
(Tatum-backed Tron/Cardano don't expose mempool txs; Monero/Zano on
own daemons do, but a check that returns "not found" for a legitimate
just-broadcast tx would break the feature). Instead, validate the
structural format: all four chains use a 64-character hex hash, so
require `/^[0-9a-f]{64}$/i`. Blocks typos and obvious nonsense; does
not stop a fraudster from generating a random valid-looking hash —
risk accepted because the feature is scoped to on-premises retail.

Also document the mempool-accept design choice and its risk profile
inline above `UnverifiedTxIdBlockchains` so the rationale is co-located
with the list.
)

* fix(security): killswitch for gs db/debug endpoints + JWT address denylist

Two complementary controls for the gs admin/debug endpoints and any leaked
JWT-signing material:

1. Process-based killswitch (`Process.GS_DB`, `Process.GS_DEBUG`) on the
   four sensitive gs endpoints (`/db`, `/db/custom`, `/debug`, `/debug/logs`).
   Gate fires before any service work; ops toggle via the existing disabled-
   processes setting, no redeploy.

2. JWT address denylist. Setting `user.status = BLOCKED` alone does NOT
   revoke active JWTs because UserActiveGuard reads status from the JWT
   payload, not the DB — so any token issued before the block remains valid
   until expiry (~2 days). New `jwtAddressDenylist` setting (lowercase
   string[]) is loaded into a module-level Set by `ProcessService` on the
   same 30s cron as the disabled-processes map, exposed via the sync
   `IsJwtAddressDenied(address)` function and checked at the end of
   `JwtStrategy.validate`. Hot path stays sync; no DB hit per request.

Also removes the literal admin mnemonic from `scripts/kyc/upload-kyc-files.js`
in favour of `process.env.UPLOAD_ADMIN_SEED`. The mnemonic is in git history
forever, so the JWT denylist above is what actually revokes it operationally.

* fix(security): await first JWT denylist refresh before HTTP accepts traffic

`IsJwtAddressDenied` defaults to false on an empty Set, unlike DisabledProcess
which is fail-closed by undefined sentinel. Without awaiting the first
resync, the denylist would be fail-open for the boot window — a JWT we
intend to deny could slip through during that gap.
@davidleomay davidleomay merged commit eaa4b2e into main Jun 23, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants