ما الجديد
سجل إصدارًا بإصدار لتطوير Fendix. صدر الإصدار v3.7.0 في أكتوبر 2026: صار إجراء GitHub يُفشل المهمة حين يتعذّر عمل Semgrep، وصار تشغيل Semgrep الذي ينتهي بخطأ فادح يُسجَّل فاشلًا بدل أن يمرّ كأنه فحص نظيف. يذكر كل إدخال أدناه ما تغيّر في ذلك الإصدار.
A threshold you ask for is a threshold you get
October 2026
- `--fail-on` fails closed. It accepts a severity in any case —
high,High,HIGH— and refuses anything else,INFOincluded, with exit 2 before scanning. v3.4.1 ran an unrecognised value as no threshold at all, so--fail-on highwarned on a HIGH finding and exited 0: the gate you asked for was off. A pipeline that passed an invalid value now fails with exit 2; the valid thresholds areCRITICAL,HIGH,MEDIUMandLOW. - `fendix verify` no longer reads missing input as a fix. A source file or dependency manifest that is absent or unreadable, or a header finding re-checked against an error or login page, now returns
unknowninstead ofresolved. - govulncheck says why a Go module could not be loaded — the go command's own diagnosis instead of a misleading "no go.mod file" — and release binaries are built with Go 1.27.1, the toolchain the images ship.
- Official distribution. Images publish to
docker.io/fendixapp/fendix, the Homebrew tap isFendix-app/fendix, and release signatures carry theFendix-app/Fendixworkflow identity. - No fingerprint, report-schema or decision-policy changes.
Go 1.27 in the images
September 2026
- The engine images build with and ship Go 1.27, so govulncheck loads any module whose go.mod requires Go 1.27 or older; the earlier ceiling was 1.25.
- No scanner, fingerprint or exit-code changes. The Go module floor stays 1.25.
- Hosted scans: release policy 2.0.0 is live — every whitebox analyzer is required, coverage gaps are owned and refunded once, and the verdict wording is the same in the app, the PR check, email and Slack.
A scan can no longer look complete when it wasn't
September 2026
- Every analyzer now says whether it ran, and if not, why. Endpoint discovery, the spec parser, active probes, secrets, textscan, semgrep, govulncheck, pip, npm, the Python engine and each of its checks, and plugins are recorded once per scan in a fixed order with a closed, machine-readable reason: not applicable to this target, disabled by a flag you passed, a missing dependency in the environment, a target the analyzer does not support, or a failure with its cause. A scanner that was quietly absent from a report can no longer be mistaken for one that ran clean.
- The report states its own coverage. A new
metadata.coverageblock says whether everything the run was configured to execute actually ran, names the gaps, lists the limitations, and records anything that was retried. Consumers that used to check only for afailedentry should readcoverage.configured_completeinstead: a missing dependency is a skip, and it is a gap. - A URL scan that finds zero endpoints writes its report instead of vanishing. It still exits 2, so scripts see the same code, but the report now exists with discovery recorded as
failed/no_endpoints— Fendix Cloud used to store that case as a clean scan. - Two opt-in flags turn a coverage gap into a failing build.
--fail-on-coverage-gapexits 2 when something the run was configured to execute was unavailable or failed;--require-analyzers a,bexits 2 when a named analyzer was not delivered, and a required analyzer disabled by another flag is reported as the contradiction it is. Both are off by default; nothing about the default exit codes changed. - A transient network failure in a dependency scanner is retried once, in process. govulncheck, pip and npm get one re-invocation on a network error or timeout, and the entry says
attempts: 2. Nothing else is retried and the engine never re-runs itself. - Coverage is visible in every format. SARIF lists every analyzer that did not run as a tool notification and carries the coverage block; HTML and PDF reports show a coverage table under the verdict; the scan-end summary on the terminal is now that same table.
- The Docker image ships a Go toolchain, so govulncheck runs inside it. Every earlier image recorded govulncheck as failed on any Go repository because the
gocommand it depends on was not there. Module resolution uses Go's default proxy; setGOPRIVATEfor private modules. - Two report semantics were corrected.
pipwith no manifest isskipped/not_applicable, notok; an npmpackage.jsonwithout a lockfile isskipped/unsupported_target. Neither is a coverage gap; both stop confusing "nothing to scan" with "scanned clean".
An upgrade stops splitting your findings in two
September 2026
- A finding you were already tracking is recognised after the identity change, instead of arriving as one closed issue and one new one. When finding identity moved in v3.0, anything tracking Fendix findings had no way to tell that the finding it knew and the finding it now saw were the same one — so one vulnerability could become two records, with two ids and two histories. Reports now carry the retired identity alongside the current one, purely so a consumer can join the two. It is a migration bridge and nothing scores or filters on it; the current identity is unchanged, so saved baselines and
.fendix-ignorefingerprint rules keep matching exactly as before. - The list of checks a scan ran no longer includes checks it skipped. A report could name a scanner under
checks_runwhile, in the same document, recording that the scanner never ran — because the list was built from what the scan was configured to do rather than from what it did. It is now built from what actually completed. You may see fewer entries than before on scans where a scanner was unavailable; that is the list becoming accurate, not coverage shrinking. What a scan actually covered, and every release decision made from it, are unchanged.
Every blocking decision explains itself
August 2026
- A blocked build now tells you why, in the report itself. A BLOCK used to arrive in your SARIF as little more than the word BLOCK once it had been through Fendix's own storage and re-rendering — the reasoning existed, but not everywhere you could read it. Every finding now carries the decision, the policy it was made under, and the specific evidence that justified it, and the JSON and SARIF reports say exactly the same thing. You can answer "why did this fail my pipeline?" without opening Fendix.
- You can see which evidence class allowed a block. A dependency blocked on a deterministic match in production code, a vulnerability blocked because user input provably reaches the dangerous call, and a finding blocked because two independent signals agreed are three different claims — and they now read as three different claims rather than one undifferentiated verdict.
- A finding held back says why it was held back. "Held at WARN because nothing corroborates it", "the vulnerable component is never imported", "this credential is test fixture data" — each is now a stable machine-readable reason, not a sentence you would have had to parse.
- Confidence scores are explainable line by line. Each score comes with the rules that produced it and what each contributed, so a 45 and a 75 are no longer just numbers.
- A relaxed gate can no longer be mistaken for a normal one. If a build was blocked only because confidence enforcement was switched off, the report says so. Findings that do not block are no longer mislabelled as though they did.
Findings claim only what they proved
August 2026
- A wildcard CORS policy with credentials is reported as a misconfiguration, not an exploit. Browsers reject that combination outright, so it can never produce the authenticated cross-origin read the CRITICAL rating was claiming. It is now MEDIUM and no longer fails a build. Origin reflection with credentials — the shape that genuinely is account-takeover grade — is unchanged.
- Missing rate limiting is ranked by what abusing the endpoint is worth. One flat severity across a large API asserted that an unlimited login and an unlimited list read deserved equal urgency. Login, identity and expensive unauthenticated operations stay prominent; ordinary reads drop to informational.
- Browser security headers are judged against the response they are on. A JSON API response is not a browser document, so a missing Content-Security-Policy on one is no longer graded as though it were.
- A dynamic file path is no longer reported as a proven path traversal. Building a path from a variable is worth flagging; it is not the same claim as demonstrating traversal, and the wording now reflects that.
- Obvious test credentials stop being treated as leaks. When both the location and the value agree that a string is fixture data, it is reported as informational. A real provider-issued secret is never de-escalated, wherever it sits.
- An unresolved import is no longer read as proof a dependency is unused. Not being able to tell is different from knowing it is safe, and only positive evidence of non-use now lowers a dependency finding.
Semgrep findings hold still
August 2026
- Every Semgrep finding was getting a brand-new identity on each scan. Its identity carried an internal temporary path that changed every single run, so a baseline or a suppression never matched it again — even when nothing in your code had changed at all. Semgrep findings now keep the same identity from one scan to the next, like every other finding.
- Every unprotected route is its own finding again. Five Flask routes missing an auth decorator were collapsing into one finding, so suppressing the one you had reviewed silently suppressed the four you had not. Separately, these findings were showing "requires login" as their evidence — a placeholder Semgrep returns when it is not signed in — instead of the line of code that actually matched. You now see the code.
Older reports keep their own identity scheme
August 2026
- Re-exporting a report saved before v3.0.0 labelled it with the new identity scheme while it still carried the old values. A tool reading that export could match those identities against the wrong things. A report now always declares which scheme its own identities were produced under, so old and new exports can never be confused for one another.
صدر الإصدار v3.7.0 في أكتوبر 2026 — صار إجراء GitHub يشترط عمل Semgrep في فحص الشيفرة ويُفشل المهمة حين يتعذّر تشغيله، ولا يثبّت إلا الحزم الجاهزة (wheels)، ولا يرفع SARIF إلا لفحص اكتمل، وصار تشغيل Semgrep المنتهي بخطأ فادح يُسجَّل فاشلًا؛ ولا تغييرات في مخطط التقرير أو SARIF أو البصمات أو سياسة القرار، ويبقى لكل رمز خروج معناه. صدر الإصدار v3.6.5 في أكتوبر 2026 — أصلحت تحديثات Semgrep 1.182.1 وMCP 1.29.0 وgolang.org/x/mod 0.40.0 آخر الثغرات عالية الخطورة القابلة للإصلاح في الصورة الرسمية، ولم يعد Semgrep يتصل بخادم semgrep.dev، وصارت مشغّلات CI ذاتية الاستضافة على Linux تحتاج إلى glibc 2.34 أو أحدث لتشغيل Semgrep؛ ولا تغييرات في الفاحصات أو البصمات أو مخطط التقرير أو سياسة القرار أو رموز الخروج. صدر الإصدار v3.6.4 في أكتوبر 2026 — أُعيد بناؤه باستخدام Go 1.27.3 وبحزمة certifi 2026.10.23، فلم تعد اتصالات TLS تثق بسلطات التصديق الوسيطة الثماني التابعة لـ emSign التي اختُرقت مفاتيحها الخاصة، ولم يعد بإمكان هدف فحص خبيث عبر HTTP/2 أن يستنزف معالج الفاحص؛ ولا تغييرات في الفاحصات أو البصمات أو مخطط التقرير أو سياسة القرار أو رموز الخروج. صدر الإصدار v3.6.3 في أكتوبر 2026 — صارت أربع قواعد Semgrep مضمّنة لم تكن تطابق شيئًا تُبلغ عن نتائجها، بالحالة WARN افتراضيًا مع --fail-on المقيّدة بمستوى الثقة؛ وتنص إرشادات المصادقة في Flask على وضع المُزخرِف أسفل @app.route(...)؛ وصار لإحدى عشرة قاعدة نص ثابت في الفهرس؛ ولا تغيير في هوية النتائج. صدر الإصدار v3.6.2 في أكتوبر 2026 — صارت الفحوصات القائمة على الفروق مع مسار --code نسبي تفحص الملفات المتغيّرة من جديد، ويتحول نطاق الفروق الذي لا يمكن تمثيله بأمان إلى فحص كامل. صدر الإصدار v3.6.1 في أكتوبر 2026 — صار ملف SARIF لفحص بلا نتائج صالحًا، وصار إجراء GitHub يتحقق من توقيع الإصدار قبل تشغيل الملف التنفيذي. صدر الإصدار v3.6.0 في أكتوبر 2026 — صارت خطوط الأساس وقواعد .fendix-ignore وملفات SARIF تعمل على كل وقوع أمني على حدة، فلم يعد بإمكان بيانات اختبار مُدرجة في خط الأساس أو مستبعدة أن تخفي بيانات اعتماد إنتاجية جديدة مجمّعة معها؛ مع صيغة خط الأساس 2، ونتيجة SARIF لكل وقوع، وتتبّع fendix jira وfendix verify لكل وقوع. صدر الإصدار v3.5.1 في أكتوبر 2026 — صار fendix init يكتب ملفات CI تثبّت إصدارًا محددًا من Fendix بعد التحقق من توقيعه، وصار brew upgrade يصل إلى التثبيتات التي سجّلها Homebrew القديم بالإصدار 64، وصار بإمكان المثبّت اشتراط التوقيع أو بصمة SHA-256 محددة؛ ولا تغييرات في الفاحصات أو البصمات أو مخطط التقرير أو سياسة القرار أو رموز الخروج. صدر الإصدار v3.5.0 في أكتوبر 2026 — صارت --fail-on ترفض العتبة غير الصالحة بدل أن تُجري المسح بلا عتبة بصمت، ولم يعد fendix verify يعدّ المدخلات المفقودة دليلًا على الإصلاح، وتُنشر الصور على Docker Hub؛ ولا تغييرات في البصمات أو مخطط التقرير أو سياسة القرار. صدر الإصدار v3.4.1 في سبتمبر 2026 — تُبنى صور المحرك الآن بلغة Go 1.27 وتشحن بها، فيرتفع سقف الوحدات المدعومة في govulncheck من 1.25؛ ولا تغييرات في الفاحصات أو البصمات أو رموز الخروج، ويبقى الحد الأدنى لإصدار وحدات Go عند 1.25. صدر الإصدار v3.4.0 في سبتمبر 2026 — لم يعد بالإمكان أن يبدو المسح مكتملًا وهو ليس كذلك: يسجّل كل محلل ما إذا كان قد عمل ولماذا لم يعمل، ويحمل التقرير كتلة تغطية تسمّي الفجوات، ويكتب مسح URL الذي لا يجد نقاط نهاية تقريره بدل أن يختفي، وتحوّل رايتان اختياريتان فجوة التغطية إلى بناء مُخفق. صدر الإصدار v3.3.0 في سبتمبر 2026 — ولم تعد الترقية تقسم النتيجة التي تتابعها إلى مغلقة وجديدة، وصارت قائمة الفحوص تُبنى مما اكتمل لا مما جرى إعداده. وفي v3.2.0 — وفيه صار كل قرار حظر يشرح نفسه. تحمل نتيجة BLOCK الآن السياسة التي اتُّخذت بموجبها وصنف الدليل الذي برّرها، عبر تخزين Fendix نفسه وحتى ملف SARIF الذي تصدّره، فيصير خط الإنتاج المخفق قابلًا للتفسير من التقرير وحده. وتذكر النتائج المحجوزة سبب حجزها، وتأتي درجات الثقة مصحوبة بالقواعد التي أنتجتها، ويُوسم صراحةً أي بناء حُظر لمجرد أن فرض الثقة كان مُعطَّلًا. وأوقف الإصدار v3.1.0 ادعاء النتائج بأكثر مما أثبتته — من CORS بحرف بدل مع بيانات الاعتماد، إلى ترتيب أولويات تحديد المعدّل، وتقييم الترويسات بحسب نوع الاستجابة، وصياغة اجتياز المسارات، وبيانات الاعتماد الاختبارية، وقابلية تطبيق الاعتماديات. ومنح الإصدار v3.0 النتائج هوية مستقرة مبنية على القاعدة التي أطلقت النتيجة، وفي أي ملف، وداخل أي دالة، وحول أي عملية. أعد حفظ خطوط الأساس مرة واحدة بعد الترقية من إصدار أقدم من v3.0، وأعد كتابة أي قاعدة .fendix-ignore تثبّت قيمة fingerprint: — أما القواعد التي تستخدم محددات المعرّف أو نقطة النهاية أو الفئة المدعومة فلا تتأثر بتغيير البصمة، مع أن معرّفات SEC-NNN موضعية ولا تناسب إلا المعالجة المؤقتة.