ما الجديد
سجل إصدارًا بإصدار لتطوير Fendix. صدر الإصدار v3.7.0 في أكتوبر 2026: صار إجراء GitHub يُفشل المهمة حين يتعذّر عمل Semgrep، وصار تشغيل Semgrep الذي ينتهي بخطأ فادح يُسجَّل فاشلًا بدل أن يمرّ كأنه فحص نظيف. يذكر كل إدخال أدناه ما تغيّر في ذلك الإصدار.
A finding keeps its identity when your code moves
August 2026
- Adding a comment above a vulnerability used to turn it into a different vulnerability. A finding was identified partly by the line it sat on, so any edit above it gave it a new identity: your baseline stopped recognising it, your
.fendix-ignorerule stopped suppressing it, and something you had already triaged came back as new work. Findings are now identified by what they are — which rule fired, in which file, in which function, about which operation — and not by where they happen to sit today. Scanned before and after an edit that moved every line of the file, every finding was still recognised; the old scheme lost roughly a quarter of them and reported the same issues over again as brand-new. - Findings no longer claim more than they proved. A path-traversal finding said "user input flows to filesystem path" even when Fendix had only seen the filesystem call and could not trace any user input reaching it. A fully proven SSRF, meanwhile, still described itself as "potential". The wording now follows the evidence: "Potential" when only the dangerous operation was observed, and a plain statement when the path from user input was actually traced. The finding does not change identity when its wording strengthens — it is the same issue, better understood.
- GitHub now shows what Fendix actually believes about a finding. A placeholder API key in a test fixture — scored low-confidence, held as a warning, never going to fail your build — was still handed to GitHub ranked as High with nothing to say otherwise. An alert now carries the rule's inherent severity, Fendix's confidence in that specific instance, and the two combined, each stated separately. Where they disagree, the alert says so in the first line you read.
- Rate limiting is tested with the method it reports. Fendix reported "no rate limiting observed" against
POST /loginhaving only ever sent a GET — a claim about a test that never happened. It now probes the operation's own method where that is safe: a passive scan will not fire twenty writes at your production API, and a DELETE is never burst-probed at any setting. Where an operation cannot be probed safely it is reported as not tested, rather than quietly counted as passing. - A rate-limit sweep reads as one finding instead of eight hundred locations. A sweep across a large API produced a single result carrying a separate location for every operation it touched, which no tool renders legibly. You now get a readable sample with the true total beside it, and the complete list is still attached.
- Separate scan types stop clearing each other's GitHub alerts. A code scan and a live scan of the same repository were filed under one category, so whichever ran last marked everything the other had found as fixed. Each scan type now keeps its own set of alerts.
- Before you upgrade, re-save your baselines. Because findings are identified differently now, a baseline written by an older version matches nothing — the first scan after upgrading would report every finding as new. Run
--save-baselineonce to regenerate it, and rewrite any.fendix-ignorerule that pins afingerprint:value. Rules using the supportedid,endpoint, orcategoryselectors are unaffected by the fingerprint change, although positionalSEC-NNNids are suitable only for short-lived triage. GitHub code-scanning alerts also re-file themselves once, under their new rule names.
A running scan shows you where it is
August 2026
- The progress bar moves while a scan is actually scanning. Fendix reports its progress at checkpoints, and there was no checkpoint during the longest part of a scan — probing your endpoints, which takes even longer with active probing on. The bar reached that point and sat there, so a scan that was working looked stuck. It now advances through that phase as the endpoints are covered.
Bring findings from your other scanners
August 2026
- Import SARIF from CodeQL, Semgrep, Trivy or anything else.
fendix import report.sarifruns another scanner's findings through the same pipeline your own scans use — deterministic confidence scoring, dedup,.fendix-ignoreand baseline filtering, and the confidence-gated fail-on decision. Attach one to a scan withfendix scan --import report.sarif, or upload it in the dashboard. Imported findings are labelled as such and never claim to be verified by Fendix's own engines. - When two engines independently agree, the finding says so. A finding now shows which other tool confirmed it. Confirmation is deliberately hard to earn: a genuinely different tool has to report the same weakness (exact CWE) at the same location, within five lines. Matching titles, matching categories, the same tool run twice, or two findings that merely sit in the same file never count — a false "both engines confirm" is worse than a missed one.
Reports that name the engine that produced them
August 2026
- A scan run from the Docker image now records its real engine version. Every image ever published answered
fendix version docker, so a scan run that way filed its engine as "docker" — in the scan record, and in thedriver.versionfield of the SARIF handed to GitHub code scanning. A report has to be able to say which build produced it. The image now carries its release tag, exactly as the downloadable binaries always have. Detection and scan behaviour are unchanged from v2.0.0.
Trust & precision — findings that only claim what they can prove
August 2026
- Your build no longer fails on a guess. A finding could previously fail your build on severity alone, even when the scan itself had recorded that it could not confirm the issue — the report literally said "unconfirmed by live scan" next to a failed build. Blocking now also requires the confidence to support the claim: high confidence blocks, medium blocks when something corroborates it, low warns instead. Real hardcoded credentials in production code still fail the build, exactly as before. If you want the old behaviour back,
--enforce-confidence=falserestores it precisely. - One finding per vulnerability, not one per advisory database. A vulnerable dependency is usually catalogued several times over — the same flaw filed once as a GHSA and again as a PYSEC record. You were seeing each copy. A recent
cryptographypin produced six findings for three actual vulnerabilities; it now produces three, each naming its CVE and listing the other identifiers it covers. - Upgrade advice you can actually run. "Upgrade to a patched version (no fix listed)" appeared even when a fix existed, and in some cases the suggested version was a git commit hash rather than a release. Fix versions are now read correctly and ranked against the version you actually have, so a project on Django 5.2.16 is told to go to 5.2.17 — not pushed onto the next major release.
- Test fixtures stop shouting. A
FAKE_API_KEYin your test folder was failing builds like a live credential. Placeholder-shaped values are now recognised deterministically and step aside, while a genuine secret in test code still gets your attention if anything corroborates it. Nothing is hidden — the finding and its evidence remain, exactly as they always have. - Secrets never leave the scanner. A detected credential used to have the first characters of its value copied into the finding's evidence, which then travelled into every report and export. The value is now replaced with a length and a hash the moment it is detected, so the secret itself never reaches a report at all.
- Reports that name real places. Dynamic findings were being labelled with a source file called "None", and a finding on a URL could end up filed under a file called "https". Findings from a live scan are now anchored to the endpoint they came from, and file-based findings to their real path and line.
- Better GitHub code-scanning integration. Results now carry a stable identity, so an alert stays the same alert between runs instead of reappearing as new; a severity score, so GitHub ranks them correctly; and a readable description, with the offending line of code shown as a code snippet rather than pasted in as the title.
- Fewer false alarms on Dockerfiles. A multi-stage Dockerfile referring to its own earlier stage —
FROM base AS production— was reported as an unpinned image. Build stages are now understood. Separately, base images pinned only to a tag rather than a digest are now noted for information.
Sharper signal — one finding per problem, and severity that reflects proof
August 2026
- One problem, one finding. Several analyzers cover the same ground, and when two of them recognised the same issue you used to see it reported two or three times under different names — a single hardcoded
SECRET_KEYproduced three separate findings at two different severities. Duplicates from different analyzers at the same line are now merged into the one from the most trustworthy engine, so the count in your triage queue is the number of problems you actually have. - Test code steps aside. Findings in tests, fixtures and conftest files now report as INFO by default, so production code leads your triage instead of competing with deliberately-vulnerable test data. Nothing is hidden — the finding and its evidence are still there — and a finding at or above your
--fail-onthreshold still blocks the build. Turn it off with--deescalate-tests=falseif you want to gate on test code too. - Severity now reflects proof. The analyzer flags dangerous shapes as well as proven exploit paths, and both used to arrive at the same CRITICAL. A finding where we could not trace user input to the sink now carries a lower severity than one where we can show the whole path — so CRITICAL means we proved it, not that the code looked risky.
- Context-aware confidence. A missing security header on a CDN-served asset, or a permissive CORS policy seen only behind a login wall, is a weaker signal than the same thing on a live API route. Those are now scored lower and tell you why in the finding's reasons, rather than sitting at full confidence alongside real issues.
- Quiet failures made loud. A profile with its credential at the wrong nesting level used to scan completely unauthenticated with no warning — it now fails with the exact correction. Session cookies missing HttpOnly on a 401 login response are reported instead of discarded, multi-line JWTs are detected, and the code analyzer no longer stops early when an optional dependency is missing.
Real-world precision — less noise, proven on real code, and a redesigned workspace
July 2026
- Quieter, more trustworthy findings. We built a benchmark that scores Fendix against real repositories — not just synthetic test cases — and used it to close the biggest sources of false positives: constant SQL misread as injection, safe guards, test-fixture code, sanitized output, and more. On a real Django app the noise dropped from roughly 90 findings to 5 while the one genuine vulnerability stayed flagged, and the synthetic accuracy score held at a perfect 1.000 throughout.
- Dramatically faster scans. A performance fix in the code analyzer took a full scan of a large real project from around 50 minutes to 9 seconds — the same finding quality, a fraction of the wait.
- Scanner coverage and decisions, visible in the app. Scan detail now shows which scanners ran, were skipped, or failed, the BLOCK / WARN / INFO decision summary at a glance, how many endpoints were discovered versus scanned, and the source tier of each finding — so you can see not just what was found, but how much ground the scan actually covered.
- A redesigned scan workspace. The new-scan flow is now a clean step-by-step layout, the issues page is a proper triage table with bulk actions and saved filters, and the whole dashboard moves onto a consistent design-token system — a calmer, more professional workspace end to end.
- Verify anything. The verify action now re-checks correlated and active-probe findings too, so you can confirm a fix resolved an issue no matter how it was detected.
Production release — decisions, confidence, Java coverage, and accuracy you can reproduce
July 2026
- Decision reports. Every finding now carries a decision — BLOCK, WARN, or INFO — plus a deterministic, explainable confidence score, surfaced in the JSON, SARIF, HTML, CLI, and PR-comment output. Your build fails only on what genuinely blocks it, so the PR check answers "can I merge?" at a glance instead of handing you a wall of findings.
- Java SAST coverage. Java joins the scanned languages with eleven line-local rules — command injection, SQL injection, weak crypto, insecure deserialization, XXE, insecure cookies, weak randomness, LDAP injection, SSRF, reflected XSS, and path traversal.
- Accuracy you can reproduce. Every published number is backed by a re-runnable benchmark and gated in CI: the synthetic corpus scores F1 1.000, the interprocedural taint engine 1.000, and the DVWA / OWASP Juice Shop DAST baselines verify clean. No marketing figure ships without a command that reproduces it — see BENCHMARKS.md.
- Faster, calmer developer experience. Incremental scans now cost only the changed files, error messages teach the fix, and the PR comment leads with the merge verdict.
- Signed, reproducible release. v1.0.0 ships cosign keyless-signed binaries,
.deb/.rpmpackages, multi-arch Docker images, CycloneDX + SPDX SBOMs, and SLSA build provenance — every artifact verifiable, no telemetry.
صدر الإصدار 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 موضعية ولا تناسب إلا المعالجة المؤقتة.