# Security Policy | سیاست امنیتی

IR-Toolbox یک ابزار رمزنگاری سمت‌کلاینت است؛ امنیت آن برای ما جدی‌ترین اولویت است. 🔐

## Supported versions | نسخه‌های پشتیبانی‌شده

| Version | Supported |
|---------|-----------|
| v1.3.8 (latest) | ✅ — سخت‌سازی‌شده (CSP، بدون `eval`، PBKDF2 ۶۰۰k، CSV injection) |
| v1.3.x | ⚠️ کار می‌کند، اما فاقد سخت‌گیری‌های نسخه‌های جدیدتر است |
| < 1.3 | ❌ — لطفاً به آخرین نسخه به‌روزرسانی کنید |

## Reporting a vulnerability | گزارش آسیب‌پذیری

لطفاً آسیب‌پذیری‌ها را **علنی گزارش نکنید** (Issue عمومی باز نکنید). به‌جای آن:

1. از طریق GitHub به نگه‌دارنده پیام خصوصی بدهید (پروفایل [Kourosh242](https://github.com/Kourosh242)) یا از قالب **Private Vulnerability Reporting** در تب Security مخزن استفاده کنید.
2. حداکثر تا ۷۲ ساعت پاسخ اولیه دریافت می‌کنید.
3. لطفاً این موارد را ذکر کنید: نوع مشکل، مراحل بازتولید، مرورگر/سیستم‌عامل آزمایش‌شده، و در صورت امکان Proof-of-Concept.

## Scope | حوزه

- منطق رمزنگاری (گاوصندوق IR، مدیر رمز عبور): Web Crypto / AES-256-GCM / PBKDF2
- هر مسیر اجرای کد ناامن (`eval`، `new Function`، `innerHTML` با ورودی کاربر، اسکیم‌های `javascript:`)
- حملات محلی: تزریق فرمول در خروجی CSV، ReDoS در آزمایش Regex، دست‌کاری دادهٔ پشتیبان/`localStorage`
- سیاست `Content-Security-Policy` صفحه‌ها
- سرویس‌ورکر و کش آفلاین
- هر مسیر نشت داده به بیرون دستگاه (هیچ‌کدام نباید وجود داشته باشد)

## Hardening (v1.3.8) | سخت‌گیری‌های نسخهٔ ۱.۳.۸

| حوزه | وضعیت |
|---|---|
| مشتق کلید | PBKDF2-HMAC-SHA-256 با **۶۰۰٬۰۰۰ تکرار** (توصیهٔ OWASP). شمارش تکرار به‌صورت `kdfId` داخل فایل `.ir256` و دادهٔ پشتیبان ذخیره می‌شود؛ `kdfId=1` → ۲۵۰٬۰۰۰ (قدیمی) و `kdfId=2` → ۶۰۰٬۰۰۰. بالا رفتن هزینهٔ KDF داده‌های قبلی را قفل نمی‌کند. |
| اجرای کد | **صفر `eval` و صفر `new Function`** در کل مخزن. ماشین‌حساب علمی یک پارسر `recursive-descent` با فهرست سفید توابع است. |
| Content-Security-Policy | روی `index.html` و همهٔ صفحه‌های استاتیک (درباره، هاب ابزارها، ۹ دسته، ۵۲ ابزار، ۴۰۴). فقط `'self'` + `data:`/`blob:` برای پیش‌نمایش ابزارها و `blob:` برای Web Worker. مقدار آن در `seo/site.mjs` تعریف می‌شود، توسط `scripts/build-seo.mjs` نوشته می‌شود و توسط `scripts/validate-seo.mjs` بررسی می‌شود. |
| ReDoS | آزمایش Regex در **Web Worker** اجرا می‌شود و پس از **۸۰۰ms** به‌همراه خود Worker `terminate` می‌شود؛ ترد اصلی هرگز فریز نمی‌شود. |
| CSV Injection (CWE-1236) | سلول شروع‌شده با `=` `+` `-` `@` در خروجی CSV با آپاستروف محافظ پیشوند می‌شود؛ از v1.3.8 کاراکترهای `Tab` و `CR` هم پوشش داده می‌شوند (توصیهٔ OWASP). |
| اسکیم‌های خطرناک | QR‌خوان و هر مسیر «باز کردن لینک» فقط `http`/`https` (و `tel:`/`mailto:` برای انواع شناخته‌شده) را می‌پذیرد؛ `javascript:`/`data:`/`vbscript:` اجرا یا باز نمی‌شود و فقط کپی متن ممکن است. |
| تصادف | همهٔ تولیدهای تصادفی (رمز، توکن، عدد، shuffle) با `crypto.getRandomValues` و **rejection sampling** — بدون بایاس modulo. |
| کلیپ‌بورد | پاک‌سازی کلیپ‌بوردِ کپی موقت، فقط وقتی انجام می‌شود که هنوز متن خود اپ آن‌جاست؛ کپی بعدیِ کاربر پاک نمی‌شود. |

### راستی‌آزمایی

```bash
npm test                    # منطق خالص: جلالی، هش‌ها، پارسر ریاضی، کانتینر .ir256، ایمنی لینک
npm run validate:seo        # سازگاری نسخه، CSP یکسان روی همهٔ صفحه‌ها، لینک‌ها، JSON-LD
```

## Security model | مدل امنیتی

- همه پردازش‌ها **سمت کلاینت** انجام می‌شود و هیچ داده‌ای به سرور ارسال نمی‌شود.
- کلیدهای رمزنگاری از رمز اصلی کاربر با PBKDF2 مشتق می‌شوند و هرگز ذخیره نمی‌شوند.
- فایل `.ir256` شامل داده رمزنگاری‌شده با AES-256-GCM است (به‌همراه فشرده‌سازی gzip قبل از رمزنگاری از v1.3.6).
- کانتینر `.ir256` **نسخه‌دار و خودتوصیف** است: magic (`IRT1`، و `IVA1` برای فایل‌های قدیمی)، شمارهٔ نسخهٔ قالب (۱ یا ۲)، `kdfId` (شمارش تکرار PBKDF2) و `algId`. هر دو نسخهٔ قالب و هر دو `kdfId` هنگام بازگشایی پشتیبانی می‌شوند.
- کلیدها با PBKDF2-HMAC-SHA-256 و salt تصادفی ۱۶ بایتی و IV تصادفی ۱۲ بایتی **برای هر فایل** مشتق می‌شوند؛ احراز اصالت با تگ GCM انجام می‌شود، پس رمز اشتباه یا فایل دست‌کاری‌شده با خطا رد می‌شود.
- در محیط ناامن (`file://` یا HTTP بدون TLS) ابزارهای رمزی به‌جای اجرای بی‌صدا هشدار واضح نمایش می‌دهند.

با تشکر از محققان امنیتی که مسئولیت‌پذیرانه گزارش می‌دهند. 🙏
