From 3186143e917a734b43def3dd58cedd00245f5ce2 Mon Sep 17 00:00:00 2001 From: artylobos Date: Wed, 27 May 2026 10:01:12 +1000 Subject: [PATCH 1/2] docs: add security disclosure policy --- README.md | 6 ++++++ SECURITY.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 SECURITY.md diff --git a/README.md b/README.md index b4ec8ebf..cf7d0bd9 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,12 @@ We welcome contributions from developers of all skill levels! Please see our [CO 4. Push to your branch (`git push origin feature/amazing-feature`). 5. Open a Pull Request. +## Security + +Please review [SECURITY.md](SECURITY.md) before reporting vulnerabilities. It +lists the supported versions, private disclosure process, expected response +timeline, project scope, and reward policy. + ## 📄 License This project is licensed under the ISC License. See the `LICENSE` file for details.. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..d2ea04d5 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,55 @@ +# Security Policy + +## Supported Versions + +Security reports should target the current `main` branch and the latest tagged +release. Older tags are not actively maintained unless a maintainer explicitly +states otherwise in the release notes. + +## Reporting a Vulnerability + +Please report suspected vulnerabilities privately before opening a public issue. +Include the affected component, impact, reproduction steps, and any relevant +transaction IDs or logs. + +Primary reporting channel: + +- Open a private security advisory on GitHub if available. + +Fallback channel: + +- Contact the maintainers through the contributor Telegram linked from current + Stellar Wave issues, and ask for a private disclosure channel before sharing + exploit details. + +Do not post working exploits, private keys, seed phrases, or user data in a +public issue, pull request, or chat. + +## Response Timeline + +The maintainers aim to acknowledge valid reports within 5 business days. For +confirmed issues, we use a 90-day coordinated disclosure window unless active +exploitation or user risk requires a faster public fix. + +## Scope + +In scope: + +- Smart contracts under `contracts/` +- Backend services under `backend/` +- Frontend code under `frontend/` +- Repository deployment and configuration files + +Out of scope: + +- Third-party services, wallets, RPC providers, and infrastructure not owned by + this repository +- Social engineering, phishing, spam, or physical attacks +- Denial-of-service testing that degrades public services +- Reports that require access to private keys, seed phrases, or user data + +## Rewards + +RemitLend does not operate a standing paid security bounty program unless a +specific issue, campaign, or maintainer announcement says otherwise. Reward +eligibility, if any, is defined by the linked issue or external program. From a5f4e5b459399d936d09c96e376759906f778f29 Mon Sep 17 00:00:00 2001 From: artylobos Date: Wed, 27 May 2026 10:52:30 +1000 Subject: [PATCH 2/2] style: format e2e specs --- frontend/e2e/borrower-repay-flow.spec.ts | 16 +++++++++++----- frontend/e2e/lender-withdraw-flow.spec.ts | 19 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/frontend/e2e/borrower-repay-flow.spec.ts b/frontend/e2e/borrower-repay-flow.spec.ts index c87e7b0a..87ad5ca1 100644 --- a/frontend/e2e/borrower-repay-flow.spec.ts +++ b/frontend/e2e/borrower-repay-flow.spec.ts @@ -102,7 +102,11 @@ test.describe("Borrower Repayment Flow", () => { await expect(page.locator("text=4,500")).toBeVisible(); }); - test("rejects a repayment greater than the outstanding balance", async ({ page }: { page: Page }) => { + test("rejects a repayment greater than the outstanding balance", async ({ + page, + }: { + page: Page; + }) => { await page.goto("/en"); const repayBtn = page.getByRole("button", { name: /Repay/i }).first(); @@ -115,9 +119,11 @@ test.describe("Borrower Repayment Flow", () => { const review = page.getByRole("button", { name: /Review Repayment/i }); // The flow should not allow proceeding to confirmation with an invalid amount. - await expect(review).toBeDisabled().catch(async () => { - await review.click(); - await expect(page.locator("text=/exceeds|too (large|high)|maximum/i")).toBeVisible(); - }); + await expect(review) + .toBeDisabled() + .catch(async () => { + await review.click(); + await expect(page.locator("text=/exceeds|too (large|high)|maximum/i")).toBeVisible(); + }); }); }); diff --git a/frontend/e2e/lender-withdraw-flow.spec.ts b/frontend/e2e/lender-withdraw-flow.spec.ts index 946578f8..ed04fabe 100644 --- a/frontend/e2e/lender-withdraw-flow.spec.ts +++ b/frontend/e2e/lender-withdraw-flow.spec.ts @@ -106,9 +106,14 @@ test.describe("Lender Withdraw Flow", () => { }, lenderWalletState("1500.00")); await page.click('button:has-text("Review Withdrawal"), button:has-text("Confirm Withdrawal")'); - await page.getByRole("button", { name: /Confirm Withdrawal/i }).click().catch(() => {}); + await page + .getByRole("button", { name: /Confirm Withdrawal/i }) + .click() + .catch(() => {}); - await expect(page.locator("text=/Withdrawal (Successful|Complete)/i")).toBeVisible({ timeout: 10000 }); + await expect(page.locator("text=/Withdrawal (Successful|Complete)/i")).toBeVisible({ + timeout: 10000, + }); await page.reload(); await expect(page.locator("text=1,500")).toBeVisible(); @@ -126,9 +131,11 @@ test.describe("Lender Withdraw Flow", () => { await page.fill('input[type="number"]', "999999"); const confirm = page.getByRole("button", { name: /Confirm Withdrawal/i }); - await expect(confirm).toBeDisabled().catch(async () => { - await confirm.click(); - await expect(page.locator("text=/exceeds|insufficient|maximum/i")).toBeVisible(); - }); + await expect(confirm) + .toBeDisabled() + .catch(async () => { + await confirm.click(); + await expect(page.locator("text=/exceeds|insufficient|maximum/i")).toBeVisible(); + }); }); });