تیم یک فروشگاه ایرانی سه بار SQL Injection را «رفع» کرد؛ هر بار در Endpoint دیگری بازگشت. XSS هم پس از تعویض Editor دوباره ظاهر شد. مشکل کمبود WAF یا اسکن نبود: هر Developer راه خودش را برای Query و HTML داشت، هیچ Safe default مشترکی وجود نداشت و Findingها به Regression test تبدیل نمیشدند.
حذف یک کلاس ضعف با Patch یک خط کد فرق دارد. سازمان باید مسیر امن را آسانتر از مسیر ناامن کند، Repositoryها و Ownerها را بشناسد، Requirement و Test نسخهدار داشته باشد و هر رخداد را به بهبود Library، Rule و آموزش برگرداند. این مقاله برنامه اجرایی حذف SQL Injection و XSS از چرخه توسعه را میسازد؛ جزئیات فنی Query، Context و DOM در مرجع دفاع SQL Injection و XSS باقی میماند.
Patch، Project و Program سه چیز متفاوتاند
| سطح | خروجی | ریسک باقیمانده |
|---|---|---|
| Patch | یک Query یا Sink مشخص اصلاح و Retest میشود | همان Pattern در جای دیگر بازمیگردد |
| Project | یک محصول Inventory و Backlog آن پاکسازی میشود | تیم/Repository بعدی کنترل یکسان ندارد |
| Program | Safe API، Requirement، Test، Owner، Gate و Feedback مشترک میشود | Residual risk اندازهگیری و Exception مدیریت میشود |
هدف Program «صفر Finding در Scanner» نیست. هدف این است که ساخت SQL/DOM ناامن در کد جدید دشوار شود، موجودی Legacy براساس Risk کاهش یابد، Regression پیش از انتشار متوقف و رخداد با Evidence مهار شود.
مرز این برنامه با DevSecOps عمومی
DevSecOps همه Serviceها، Supply chain، Secret، SCA، IaC، Container، Finding و Runtime را پوشش میدهد. این صفحه یک Vertical slice عمیق برای دو خانواده Injection است: از استاندارد Safe query/render تا Regression و حذف بدهی. مدل عملیاتی گستردهتر در راهنمای DevSecOps آمده است.
این محدودکردن Scope مزیت دارد: تیم میتواند یک کلاس ضعف را با Denominator روشن اندازه بگیرد، Library قابل استفاده بسازد و نتیجه را قبل از توسعه برنامه به ضعفهای دیگر اثبات کند.
Success contract را عددی اما غیرنمایشی بنویسید
- ۱۰۰٪ Service/Repositoryهای در Scope، Owner و Stack مشخص دارند.
- کد جدید فقط از Safe query/render path تأییدشده استفاده میکند.
- همه Findingهای تأییدشده، Fix owner، SLA، Root cause و Retest evidence دارند.
- هر Bug اصلاحشده، در صورت امکان Regression test یا Rule قابل تکرار میسازد.
- Exception بدون Risk owner، کنترل جبرانی و Expiry وجود ندارد.
- Coverage برای مسیرهای Critical و Legacy در حال رشد و Recurrence در حال کاهش است.
Guardrailها: Build time و False positive کنترل شود؛ تیم برای عبور از Gate اسکن را خاموش نکند؛ Payload/PII در Log نرود؛ تست Production را مختل نکند؛ و WAF جای Fix دائمی نشود.
Inventory؛ قبل از Tool، دامنه مسئله را ببینید
Inventory حداقل باید Service، Repository، Runtime، Framework، ORM/DB driver، Database، Template/Frontend framework، Rich-text editor، CMS/WordPress، Public/Admin exposure، داده حساس، Critical journey، Deployment pipeline و Owner را پیوند دهد.
service | repo | owner | risk-tier | language/framework | db/orm/driver
query-surfaces | render-surfaces | rich-html | public/admin | data-class
safe-library-version | ruleset | tests | last-scan | exceptions | releaseRepository بدون Production mapping تصویر غلط میدهد؛ یک Artifact ممکن است از Monorepo ساخته شود یا چند Service یک Library مشترک داشته باشند. Inventory باید Repo→Build→Artifact→Runtime را دنبال کند.
Risk tier و اولویت مهاجرت
همه Sinkها برابر نیستند. Priority را از Exposure، Data sensitivity، Action، Privilege، Reachability، User count، Persistence، Blast radius، Recoverability، Change rate و Evidence بسازید. Admin-only نیز «امن» نیست؛ Admin XSS میتواند اثر زیادی داشته باشد.
| Tier نمونه | نمونه | حداقل کنترل |
|---|---|---|
| T1 حیاتی | Login، Checkout، Support admin، Multi-tenant report | Safe library، Unit/Integration، SAST، Manual review، DAST مجاز، Retest |
| T2 مهم | Search، CMS editorial، Customer dashboard | Safe library، Regression، SAST و Review مبتنی بر تغییر |
| T3 محدود | صفحه داخلی کمداده با شبکه بسته | Baseline و Control متناسب با Exposure |
Tier نباید مجوز کدنویسی ناامن باشد؛ عمق Verification و SLA را تنظیم میکند. Requirementهای پایه Separation/Encoding برای همه Scope معتبر میمانند.
Baseline را با چهار شاهد بسازید
- Code inventory: Raw query، String interpolation، Dynamic identifier، Unsafe DOM sink و Raw HTML؛
- Control inventory: Safe wrapper، Encoder، Sanitizer، CSP/Trusted Types، DB roles؛
- Test inventory: Unit/Component/SAST/DAST/Manual و آخرین موفقیت؛
- Production evidence: Route/Template usage، CSP report، WAF virtual patch، Incident و change rate.
Scanner تنها بخشی از Source/Sinkها را میبیند. Baseline را با نمونهبرداری دستی، Search ساختاری و مشاهده Runtime تکمیل کنید. Unknownها را صفر فرض نکنید؛ بهعنوان Debt با Owner نگه دارید.
Secure requirement را به Use case متصل کنید
«ورودی باید Sanitize شود» مبهم و گاهی غلط است. Requirement قابل تست بنویسید:
- همه SQL Valueها از API پارامتری Driver عبور میکنند؛
- Sort/Column فقط از Mapping داخلی مشخص انتخاب میشود؛
- متن Ticket در HTML-text Context با Encoder Template Render میشود؛
- Rich HTML فقط از Sanitizer Policy شمارهدار عبور میکند؛
- Client code String را به Sinkهای ممنوع DOM نمیفرستد؛
- DB runtime role فاقد Schema/DDL و Tableهای خارج از Scope است؛
- هر تغییر Control، Test مثبت و منفی متناظر را اجرا میکند.
Baseline را به نسخه پایدار OWASP ASVS 5.0.0 نگاشت کنید و در شناسه Requirement، Version را نگه دارید. نسخه Bleeding-edge برای Explore خوب است، نه قرارداد متغیر Production.
Threat model را روی تغییرهای مشخص Trigger کنید
Threat model یک Diagram سالانه نیست. این تغییرها Review را فعال کنند: Database/ORM جدید، Raw query، Rich-text editor، Client framework، SSR/Hydration، Third-party widget، Admin surface، Data import، Tenant model، گزارش پویا، URL redirect یا Sanitizer/CSP policy.
جلسه کوتاه باید Actor، Asset، Trust boundary، Data flow، Source، Transform، Sink، Misuse و Control را ثبت کند. خروجی مستقیم به Requirement و Test case تبدیل شود.
Paved road برای Query امن
توسعهدهنده نباید در هر Feature دوباره Placeholder، IN، LIKE، Sort و Pagination را اختراع کند. یک Library/Pattern مشترک بسازید که:
- Value binding را Default و String interpolation را سخت کند؛
- Dynamic sort/filter را از Enum/Mapping بسازد؛
- IN list، Empty list، Type و Max count را درست مدیریت کند؛
- LIKE wildcard را طبق Driver جدا از SQL binding کنترل کند؛
- Tenant scope و authorization hook را فراموشنشدنی کند؛
- Structured error و telemetry بدون SQL/PII نشتکرده بدهد؛
- Test fixture و Example واقعی Stack داشته باشد.
Wrapper نباید یک API «SQL string آزاد + values» مبهم بسازد که Identifier ناامن را پنهان کند. Escape hatch باید نام صریح، Owner، Review اجباری و Telemetry داشته باشد.
Paved road برای Render امن
Componentها را براساس Context بسازید: Text، Quoted attribute، Safe URL، Rich HTML و DOM update. Text component باید Auto-escape؛ URL component باید Parse/Policy/Encode؛ Rich HTML باید Sanitizer Policy مشخص؛ و DOM helper باید Safe sink را Default کند.
Raw HTML، innerHTML، Dynamic code و trust bypass را از مسیر عادی خارج کنید. درخواست Escape hatch باید دلیل Business، Data source، Sanitizer/Encoder، Owner، Test و Expiry داشته باشد.
Safe default باید Developer Experience خوبی داشته باشد
اگر مسیر امن کند، پیچیده و بدون مستندات باشد، تیم راه میانبر میسازد. Paved road باید Autocomplete، مثال Stack-specific، خطای قابل فهم، Migration guide، Local test و پشتیبانی Owner داشته باشد.
Success را با Adoption و Time-to-fix بسنجید. تعداد دانلود Library کافی نیست؛ چند Query/Component واقعی از آن استفاده میکنند و چند Escape hatch جدید ایجاد شده است؟
استاندارد کدنویسی؛ ممنوعیت همراه با جایگزین
| Pattern ممنوع/محدود | جایگزین تأییدشده | Evidence |
|---|---|---|
| Concatenation/Interpolation SQL | Driver binding یا Query builder امن | Unit + structural rule |
| Identifier از Request | Enum/Mapping داخلی | Negative test |
| Raw HTML بدون Policy | Auto-escaped text یا Sanitizer شمارهدار | Component test |
| Unsafe DOM sink | textContent/value/createElement یا Trusted policy | Lint + browser test |
| Runtime DB admin role | Role حداقلی هر Service | Permission test |
| WAF-only closure | Virtual patch موقت + code fix + Retest | Expiry و removal |
استاندارد باید Version، Scope، Owner، Change log، Deprecated path و Deadline مهاجرت داشته باشد. PDF فراموششده Control نیست؛ Rule و Library باید آن را در کار روزانه حاضر کنند.
آموزش را به Stack و کار واقعی وصل کنید
یک دوره عمومی سالانه رفتار را عوض نمیکند. آموزش کوتاه بر پایه PRهای ناشناس، Query builder واقعی، Template engine تیم و Bugهای قبلی بسازید. Developer باید تفاوت Validation/Binding، Encoding/Sanitization و Input/Output context را در Stack خودش تمرین کند.
Security champion جای AppSec یا Owner محصول را نمیگیرد. ظرفیت، مسیر Escalation، Office hour و Recognition لازم دارد؛ وگرنه نقش افتخاری و گلوگاه میشود.
کنترل محلی قبل از Push
IDE/Linter/pre-commit باید Ruleهای سریع و کمNoise اجرا کنند: API ممنوع، Raw query، Unsafe sink، Missing safe wrapper و Policy bypass. Rule کند یا Context-dependent را به CI ببرید.
Developer باید بتواند Finding را Local بازتولید و Fix پیشنهادی درست ببیند. Ruleی که فقط «مشکل امنیتی» میگوید و Context/جایگزین ندارد، Adoption را کم میکند.
Pipeline؛ کنترلها را بر زمان و عمق پخش کنید
PR: unit/security regression + lint/structural SAST + changed-code review
merge: full SAST + component/integration + build evidence
staging: DAST safe profile + browser/template tests + DB permission tests
release: risk-based gate + exception/expiry + artifact/test evidence
production: CSP/WAF/app telemetry + incident feedback + scheduled deep reviewهمه Checkها را به یک Stage آخر هل ندهید. Feedback سریع برای Developer و Verification عمیق برای مسیرهای پرریسک لازم است. Build/deploy/rollback عمومی را راهنمای CI/CD امن پوشش میدهد.
SAST را با Denominator و Seed کالیبره کنید
یک Scanner ممکن است Language یا Framework را پشتیبانی کند اما Generated template، Custom wrapper یا ORM escape hatch را نبیند. Coverage denominator بسازید: Repo/Language/Framework/File type/Source/Sink. سپس Seeded caseهای امن آزمایشگاهی اضافه کنید تا Rule upgrade را بسنجید.
- Ruleset و Tool version Pin/Change log داشته باشد؛
- False positive/negative نمونهای اندازهگیری شود؛
- Finding fingerprint و Dedup پایدار باشد؛
- New code، Reachability، Exposure و Risk در Gate دخیل باشند؛
- Suppression دلیل، Owner، Expiry و Review داشته باشد؛
- Outage اسکنر سیاست Fail-open/closed و Post-scan مشخص داشته باشد.
Block کردن هر Severity بالا بدون Context، تیم را به Suppress و خاموشکردن کنترل سوق میدهد. Gate باید Risk-based و قابل توضیح باشد.
Security unit و regression test
Testهای کنترل باید مثبت و منفی باشند: Query با Valueهای مرزی ساختار ثابت نگه دارد؛ Mapping گزینه ناشناخته را رد کند؛ Text component Markup را متن نگه دارد؛ Rich-text Policy فقط عناصر مجاز را حفظ کند؛ URL component Scheme نامعتبر را نپذیرد؛ DB role عملیات خارج Scope را رد کند.
هر Bug واقعی باید در سطح مناسب Test شود. اگر Bug از Library مشترک بود، Regression فقط در یک Service کافی نیست؛ Library test، Consumer compatibility و rollout version لازماند.
DAST و تست دستی؛ با مجوز و هدف
DAST میتواند رفتار Runtime را ببیند اما Source/Root cause را همیشه نمیداند و مسیرهای Auth/State را از دست میدهد. Profile محیط، Account/role، Rate، Data، Cleanup و Stop condition را تعریف کنید. مسیر Critical و Business logic به Review دستی نیاز دارد.
تست نفوذ مستقل باید Finding را به Root cause و Remediation قابل تکرار برساند؛ Scope، Evidence و Retest آن در راهنمای تست نفوذ وباپلیکیشن آمده است.
Control verification با Vulnerability hunting فرق دارد
OWASP SAMM میان Requirements-driven testing و Security testing تفاوت میگذارد. اولی میپرسد «کنترل تعریفشده درست کار میکند؟»؛ دومی ضعفهای ناشناخته را با Automation و متخصص جستوجو میکند. هر دو لازماند.
برای نمونه، Unit test اثبات میکند Safe query wrapper Binding دارد؛ Manual test ممکن است یک Report قدیمی خارج Wrapper پیدا کند. صفحه رسمی OWASP SAMM Requirements-driven Testing بر Test مثبت/منفی و Regression بعد از Fix تأکید دارد.
Finding lifecycle؛ از Alert تا Evidence بستهشدن
detect → normalize/fingerprint → validate → scope/reachability
→ severity/business context → owner/SLA → root cause
→ fix/compensation → deploy → independent retest
→ regression/control improvement → close with evidenceDuplicateها را به Root cause مشترک گروهبندی کنید. اگر ده Finding از یک Helper ناامن میآیند، ده Ticket خطی کمتر از اصلاح Helper، Codemod، Test و مهاجرت Consumerها ارزش دارد.
Severity تنها اولویت نیست
Priority از Severity فنی، Exploitability، Reachability، Exposure، Data/Action، Privilege، Persistence، Tenant blast radius، Compensating control و Fix cost ساخته میشود. یک XSS ذخیرهشده Admin در مسیر پشتیبانی ممکن است از Finding عمومی اما unreachable مهمتر باشد.
Risk acceptance باید Business owner و Security owner را در تصمیم نگه دارد؛ Developer تنها نباید Risk مشتری را بپذیرد.
Exception و Suppression را منقضی کنید
Exception معتبر شامل Requirement، Scope دقیق، دلیل، Evidence، Residual risk، کنترل جبرانی، Owner، Approver، Deadline اصلاح، Expiry و Trigger بازبینی است. Suppression Rule نیز باید به Finding/Code location و Version محدود باشد.
Exception بدون Expiry به Policy جدید تبدیل میشود. Dashboard باید نزدیکشدن به انقضا و تغییر Exposure/Dependency را Alert کند.
Legacy migration بدون Big Bang
- Hotspotها را با Search/SAST/History/Runtime usage پیدا کنید.
- مسیرهای T1 و Code پرتغییر را جلو بیندازید.
- Safe wrapper/component را کنار مسیر قدیمی معرفی کنید.
- Regression characterization بسازید تا رفتار Business حفظ شود.
- Call siteها را Batch/Canary مهاجرت و Metric/خطا را مقایسه کنید.
- Escape hatch قدیمی را Deprecated و سپس Build-failing کنید.
- DB role/CSP/Trusted Types را پس از سازگاری مرحلهای Enforce کنید.
خطوط کد مهاجرتشده KPI کافی نیست؛ مسیرهای پرترافیک/حساس و کاهش Reachable surface مهمترند.
WordPress و CMS در Program
Theme/Plugin سفارشی، Snippet manager، Page builder HTML، REST endpoint، Shortcode، Block render و admin-ajax را در Inventory بگذارید. استاندارد باید $wpdb->prepare()، APIهای Core، Escape late، KSES، Capability و REST permission callback را پوشش دهد.
کد Third-party را نمیتوان با Training تیم اصلاح کرد؛ Supplier evidence، Patch SLA، Staging، Replacement و Exit لازم است. Update امن و Rollback را به Control program وصل کنید، نه اینکه «افزونه بهروز است» را ضمانت بگیرید.
WAF و Virtual patch را با Fix پیوند دهید
WAF در رخداد یا Patch delay میتواند Window را کم کند، اما Rule باید Asset/Route/Threat، Mode، Evidence، False-positive budget، Owner و Expiry داشته باشد. Ticket WAF و Ticket Code fix باید به هم Link شوند.
پس از Deploy و Retest، Rule موقت حذف یا به Baseline هدفمند تبدیل شود. انباشت Virtual patch، Signal بدهی و ظرفیت ناکافی است.
Incident feedback؛ Bug دوباره نباید همان Bug بماند
Post-incident فقط Timeline نیست. بپرسید چرا Safe path استفاده نشد، Review/Rule/Test کجا Gap داشت، Inventory/Owner چرا ناقص بود و کدام کنترل باید در Paved road تغییر کند. Actionها Owner/Deadline/Evidence داشته باشند.
اگر رخداد یک Raw query ناشناخته پیدا کرد، برنامه باید Rule جستوجو، Inventory و Training را برای کل Portfolio بهروز کند؛ نه فقط همان خط را Patch کند.
Secure by Design؛ بار را از مشتری بردارید
CISA و FBI در هشدار رسمی ۲۰۲۴ درباره حذف SQL Injection، از تولیدکنندگان خواستند کد را رسمی بازبینی و این کلاس ضعف شناختهشده را از محصولات جاری و آینده حذف کنند. پیام عملی برای مدیر محصول این است: امنیت را به WAF یا پیکربندی مشتری واگذار نکنید؛ Safe default و Root-cause remediation مسئولیت سازنده است.
منبع: هشدار Secure by Design برای حذف SQLi. این Guidance داوطلبانه را با الزام حقوقی محلی اشتباه نگیرید، اما اصل Ownership آن برای طراحی محصول مفید است.
NIST SSDF؛ Program را در SDLC جا دهید
NIST SSDF 1.1 مجموعه Practiceهای سطحبالا برای آمادهسازی سازمان، حفاظت نرمافزار، تولید نرمافزار امن و پاسخ به ضعفهاست. آن را Checklist ابزار نکنید؛ Taskها را به Outcome/Evidence این Program نگاشت کنید: Standard/Training، Safe library، Verification، Finding remediation و Root-cause prevention.
Snapshot ۱۲ اوت ۲۰۲۶: SP ۸۰۰-۲۱۸ Version ۱.۱ همچنان Final منتشرشده است. Draft یا Potential update را بهعنوان Final گزارش نکنید.
RACI؛ «امنیت مسئولیت همه است» کافی نیست
| نقش | Accountability نمونه |
|---|---|
| Product/Business owner | Risk tier، Priority، Acceptance و Exception business risk |
| Engineering owner | Safe library adoption، Fix، Test و Release quality |
| AppSec | Standard، Rule quality، Threat support، Verification و independent challenge |
| Platform/DevOps | Pipeline، Tool availability، Evidence، Secret و safe environment |
| QA | Requirement-driven/negative/regression coverage |
| SOC/Operations | Detection، Incident channel و feedback |
| Procurement/Supplier owner | Third-party evidence، SLA، disclosure و exit |
یک Finding دقیقاً یک Owner و Deadline میخواهد؛ مشورتکنندگان میتوانند چند نفر باشند. ظرفیت AppSec و Champion را در برنامهریزی Sprint وارد کنید.
تیم کوچک؛ Minimum viable program
برای تیم کوچک، از هشت ابزار شروع نکنید. یک Inventory ساده، Standard یکصفحهای با جایگزین، Safe wrapperهای Stack، Unit regression، Lint/SAST کمNoise، Review مسیرهای T1، Tracker Finding/Exception و Pen-test دورهای کافی است. یک Dashboard Sheet قابل اعتماد از Platform پیچیده بدون Owner بهتر است.
وقتی Coverage و Change رشد کرد، Automation و Ruleهای بیشتر اضافه کنید. Tool باید Problem مشخص را حل و Export/Exit قابل قبول داشته باشد.
ملاحظات ایران
ابزار SaaS، Registry، Advisory feed، Payment، Region، Terms، Export و دسترسی شبکه را تاریخدار بررسی کنید و برنامه را بر دورزدن محدودیت بنا نکنید. برای CI ناپایدار، Tool self-hosted یا Cache/Offline rule bundle میتواند گزینه باشد، اما هزینه Patch/Operation آن را حساب کنید.
Corpus تست باید فارسی/RTL، ی/ک، نیمفاصله، ارقام، URL، متن ترکیبی و Rich text واقعی داشته باشد. Partner/پیمانکار باید Evidence، مالکیت کد، Dependency list، Fix SLA و Retest را در قرارداد بپذیرد.
بودجه Program
هزینه فقط Scanner license نیست: Inventory، Library engineering، Training، Rule tuning، Test environment/data، Developer fix time، AppSec review، Pen-test، Retest، WAF bridge، Incident exercise و Legacy migration را وارد کنید.
Budget را با Risk tier و Change rate تخصیص دهید. Business case و Roadmap ریسکمحور در راهنمای بودجه امنیت سایت و مدیریت Cleanup پایدار در راهنمای بدهی فنی تکمیل میشوند.
Metric tree؛ از Activity تا Outcome
| لایه | سنجههای مفید | دام |
|---|---|---|
| Coverage | Service/Repo/route/template/stack تحت Inventory و Test | اسکنشده را ایمن فرضکردن |
| Adoption | درصد Query/Render path روی Safe library؛ Escape hatch جدید | تعداد Download |
| Flow | Age، MTTA/MTTR/Retest، SLA breach | بستن Ticket بدون Deploy |
| Quality | False positive/negative، seeded-case detection، regression pass | Finding خام |
| Risk | Reachable T1 debt، Exception age، virtual patch age | CVSS تنها |
| Outcome | Recurrence، Incident، affected users/data، time to contain | صفر Incident گزارششده |
| DX | زمان استفاده از Safe path، bypass reason، training task success | رضایت بدون رفتار |
Decision gate ماهانه
هر ماه Portfolio را با چهار تصمیم مرور کنید: Scale اگر Adoption/coverage بالا و Noise قابل کنترل است؛ Hold اگر Evidence ناکافی است؛ Repair اگر Rule/Library موجب Bypass یا Incident شده؛ Retire/Replace اگر Tool/Pattern هزینهای بیش از ارزش دارد.
نتیجه باید Backlog و Capacity دوره بعد را عوض کند. Dashboardی که هیچ تصمیمی نمیسازد، گزارش نمایشی است.
Runbook شکست Gate
- Finding را Validate و Fingerprint کنید؛ Duplicate و Generated/vendor code را جدا کنید.
- Reachability/Exposure/Data/Change را تعیین و Owner بسازید.
- اگر Release Critical است، Fix یا Exception زماندار با کنترل جبرانی بگیرید.
- اسکنر را بیصدا خاموش نکنید؛ Outage/False positive را به Rule owner Escalate کنید.
- پس از Deploy، Retest و Evidence را به Artifact/Release وصل کنید.
Runbook Recurrence
- Finding جدید را با Root causeهای قبلی Match کنید.
- بررسی کنید Library، Standard، Rule، Training یا Inventory کدام Gap را داشته است.
- Fix را از Call site به shared control ارتقا دهید.
- Codemod/Migration و Regression را برای Consumerها اجرا کنید.
- Recurrence rate و rollout را تا حذف Pattern پایش کنید.
Runbook Virtual patch منقضی
- Code fix، Deploy و Retest را تأیید کنید.
- Rule را ابتدا Count/Canary کم یا حذف و Traffic/Error را مقایسه کنید.
- اگر Fix ناقص است، Expiry را با Risk owner و Deadline جدید تمدید کنید؛ تمدید خودکار ممنوع.
- False positive و Performance cost Rule را ثبت کنید.
برنامه ۳۰/۶۰/۹۰روزه
۳۰ روز: Scope و Baseline
Inventory، Owner، Risk tier، Standard اولیه، ASVS profile و Hotspotهای T1 را بسازید. یک Finding قدیمی را از Root cause تا Retest دنبال کنید تا Gap فرایند آشکار شود.
۶۰ روز: Paved road و Gate آزمایشی
Safe query/render library، Regression cases، SAST/Lint کمNoise، Finding/Exception schema و CI evidence را برای دو تیم Pilot کنید. Gate ابتدا Advisory و سپس برای New critical issue محدود شود.
۹۰ روز: Scale و Feedback
Legacy T1 را Batch مهاجرت، DAST/Manual review و Pen-test را زمانبندی، WAF patchها را به Fix پیوند و Dashboard Coverage/Adoption/Risk/Outcome را راهاندازی کنید. Program review تصمیم Scale/Hold/Repair/Retire بدهد.
موضوعات مکملی که به مقاله مستقل نیاز دارند
- Safe query/render paved-road starter kit برای Stackهای رایج تیمهای ایرانی؛
- Injection/XSS structural SAST ruleset با Seeded regression و Noise benchmark؛
- ASVS ۵.۰.۰ profile/evidence/exception/retest registry؛
- Legacy raw-query/unsafe-sink migration planner و Codemod catalog؛
- Program dashboard برای Coverage، Adoption، Recurrence، Exception و Virtual patch age.
پرسشهای متداول برنامه حذف SQLi و XSS
چرا اسکن دورهای برای حذف SQL Injection و XSS کافی نیست؟
اسکن ممکن است بخشی از Source/Sinkها را پیدا کند، اما Safe default، Owner، Root cause، Fix، Regression و Prevention در کد جدید را نمیسازد. Program این چرخه را به هم وصل میکند.
آیا هر Finding با Severity بالا باید Build را متوقف کند؟
نه بهصورت کور. Gate باید Validity، Reachability، Exposure، Asset risk، New/baseline status و کنترل جبرانی را ببیند. Issue تأییدشده و قابلدسترسی در مسیر حیاتی معمولاً Block میشود؛ Noise باید Rule-fix شود.
Paved road چه تفاوتی با Coding guideline دارد؟
Guideline میگوید چه باید کرد؛ Paved road Library، Component، Example، Test و Tool آماده میدهد تا انجام درست آسانترین مسیر باشد و Escape hatch قابل مشاهده شود.
با Legacy بزرگ از کجا شروع کنیم؟
از Inventory و Risk tier؛ مسیرهای عمومی/حساس/پرتغییر را جلو بیندازید، Safe wrapper را معرفی و با Characterization test بهصورت Batch/Canary مهاجرت کنید. Big Bang لازم نیست.
چه زمانی میتوان WAF Rule موقت را حذف کرد؟
پس از Deploy Fix ریشهای، Retest همان مسیر و بررسی Patternهای مشابه. حذف را Canary کنید و Telemetry ببینید؛ Rule بدون Owner/Expiry نباید به کنترل دائمی ناشناخته تبدیل شود.
جمعبندی
حذف SQL Injection و XSS با Finding کمتر شروع نمیشود؛ با Safe path مشترک، Requirement قابل تست و Owner روشن آغاز میشود. Inventory، Risk tier، Safe query/render library، استاندارد همراه جایگزین، Test چندلایه، Gate ریسکمحور، Finding/Exception منقضی و Retest اجزای یک Program قابل دفاعاند.
صفحه ۱۳۳۸ پاسخ فنی «کد را چگونه امن کنیم» است؛ این صفحه پاسخ عملیاتی «چگونه مطمئن شویم همه تیمها امروز و Release بعد همین کار را میکنند». وقتی هر Bug به Regression و بهبود Paved road تبدیل شود، سازمان از Patch تکراری به حذف تدریجی کلاس ضعف میرسد.






