מפת דרכים לסטנדרט

מה נבדק בליבת WIZZO CMS בסקירה פנימית ב-01.10.2026, אילו נושאים עלו בחומרה הגבוהה ביותר, ואיזה סטנדרט הליבה מכוונת אליו

⏱ 9 דק' קריאה 1611 מילים ערוך דף זה ב-GitHub

הדף הזה מתאר את הדרך מהמצב הנוכחי של הליבה אל סטנדרט של מוצר שאפשר לבנות עליו בביטחון: סביבת פיתוח שמרימים בפקודה אחת, בדיקות ו-CI, גרסאות עם חתימה, ושכבות אבטחה שלא תלויות בזהירות של כל מפתח. הוא לא מבטיח תאריכים. הוא מסדר את העבודה לפי חשיבות, כדי שמפתח שנוגע בליבה יידע מה עדיין לא מובן מאליו בה.

הערה
זה צילום מצב מ-01.10.2026, על גרסת הליבה 5.0.114. המקור הוא סקירה פנימית של כל הקוד בריפו, שמצאה 458 ממצאים: 19 ברמה Critical, 89 High, 192 Medium, 136 Low ו-22 Info. הדף מכסה את שתי הרמות הגבוהות, מקובצות לפי נושא. פרטי הממצאים עצמם (מיקומים ואופן ניצול) פנימיים, ולכן אינם מופיעים בדף הזה בכוונה. מה שתוקן מאז מופיע בהיסטוריית הגרסאות, ולא נמחק מכאן אוטומטית.

איך לקרוא את הדף#

  • מצב היום אומר מה נכון עכשיו, בלי עיגול פינות. אם אתם בונים על הליבה, זה מה שחשוב לדעת.
  • לאן מכוונים אומר מה הסטנדרט המבוקש.
  • מה לעשות עד אז הוא ההנחיה המעשית למפתח, ושם מופיעים קישורים לדפי ההנחיות.
  • הסדר בין הנושאים הוא סדר עדיפויות, מהדחוף לפחות דחוף (ראו "סדר ביצוע").

נושא 1: סודות ומפתחות#

מצב היום. הסקירה מצאה שבהיסטוריית git של הריפו נשמרו פרטי גישה אמיתיים, שאינם צריכים להיות שם: סיסמת פריסה, אסימוני גישה לשירותים ומפתח של חשבון שירות. בנוסף, פונקציות ההצפנה של MISC (encode / decode) משתמשות במפתח ובווקטור אתחול ברירת מחדל שמוגדרים בקוד, ולא קיים בליבה מנגנון שמחליף אותם, ו-decode מפעיל unserialize על תוצאת הפענוח.

לאן מכוונים.

  • סיבוב של כל סוד שנחשף, וניקוי ההיסטוריה (כולל חידוש כל ה-clones).
  • מפתח הצפנה ייחודי לאתר, שמגיע מ-CONFIG_USER או מהסביבה, בלי ברירת מחדל שקטה, ומעבר ל-JSON במקום unserialize.
  • סריקת סודות אוטומטית (למשל gitleaks) כ-hook מקומי וכשלב ב-CI, וקבצי *.example במקום קבצים אמיתיים.

מה לעשות עד אז.

  • לא להכניס אף סוד לריפו (ראו שליחת שינויים).
  • להגדיר בכל אתר מפתחות ייחודיים (ראו הצפנה והקשחה).
  • להתייחס לטוקן או לעוגייה מוצפנים כאל חתומים בלבד על ידי מפתח האתר: כל עוד המפתח לא נקבע ייחודית לאתר, אין להסתמך עליהם להגנה על מידע רגיש.

נושא 2: שכבת ה-DB והזרקת SQL#

מצב היום. שכבת DB בנויה על שרשור מחרוזות, ואין בה API של prepared statements. DB::escape מסתמך על PDO::quote ומסיר את הגרשיים שהוא מוסיף. מספר מסלולים בליבה מדביקים קלט חיצוני ל-SQL, בין היתר בפרמטרים של מיון וסינון בטבלאות הניהול, בשדות גלריה, בנקודות הכניסה של האנליטיקס ובפרמטר השני של DB::get_val. חלק מהכתובות מגיעות מ-GET, חלק מכותרות HTTP. הבדיקה הכללית MISC::init_security מכסה רק חלק מהמקרים.

לאן מכוונים.

  • API עם פרמטרים קשורים ל-DB::query ול-DB::update, ומעבר הדרגתי של כל השימושים הגולמיים.
  • רשימות לבנות לשדות שמגיעים מקלט (עמודות מיון, כיוון, שמות שדות).
  • איסור על מחרוזת גולמית ב-builder כברירת מחדל, וסימון מפורש (raw) כשצריך.
  • קריאה שנכשלה היא חריג מתועד ולא "statement ריק".

מה לעשות עד אז. לפעול לפי כללי DB ב-תקן הקוד, להמיר כל מזהה ל-(int), להעביר כל מחרוזת דרך DB::escape ולעטוף אותה בגרשיים, ולבדוק רשימה לבנה על שמות עמודות. פרטים בשכבת ה-DB וב-CSRF, XSS ו-SQLi.

נושא 3: אימות, הרשאות, CSRF ו-XSS#

מצב היום.

  • חלק מקונטרולרי המערכת תחת controllers/ נגישים בלי אימות, ופעולות cron בהם נשענות על טוקן בלבד (ראו קונטרולרי מערכת).
  • הגנת CSRF נאכפת רק במסך הכניסה ובמנהל הקבצים, ולא בשמירת טפסים ובפעולות טבלה.
  • מספר מסכי ניהול מחזירים פרמטרים מה-URL ל-HTML בלי קידוד.
  • מנגנון משתמשים ישן (COOKIES) שומר זהות בעוגייה, בלי HttpOnly, ו-SameSite=None מוגדר באופן גלובלי (ראו עוגיות וסשן).
  • מודל ההרשאות מתיר עמוד שאין לו רשומת הרשאה, ושמירת קבוצות לא מאמתת את תוכן ה-JSON.
  • ה-CAPTCHA הפנימי ניתן לחישוב בצד הלקוח, ו-md5 הוא ברירת המחדל של שדה סיסמה בטפסים.

לאן מכוונים.

  • דגל "הרשאה חובה" כברירת מחדל לכל קונטרולר וכל פעולת פאנל, וחריגים רק במפורש.
  • אסימון CSRF לכל פעולה שמשנה מצב, שנאכף בשכבה אחת (panel_table, AJAXForm).
  • קידוד פלט אחיד בשכבת התבניות.
  • עוגיות Secure, HttpOnly ו-SameSite נכון, וסיסמאות עם password_hash.
  • ולידציה בצד שרת לכל שדה, ולא רק בדפדפן.

מה לעשות עד אז. כל קונטרולר חדש בודק הרשאה בעצמו, וכל פלט מקודד (ראו תקן קוד ומודל האבטחה).

נושא 4: גשר ה-AI וה-MCP#

מצב היום. שכבת ה-AI והסוכנים (ראו סקירת MCP) כוללת כלים חזקים: קריאה וכתיבה ל-DB, ניהול קבצים ויבוא מדיה. הסקירה מצאה כמה פערים בגבולות ההרשאה שלה: מפתחות API של שירותים שמגיעים לדפדפן של כל מנהל, מסכים שמדלגים על בדיקת הרשאות, כלים בלי בדיקת הרשאה לפי פאנל, קריאות חיצוניות בלי הגנת SSRF, אימות TLS שמבוטל בקריאות מסוימות, ואסימונים שמופיעים בכתובות ובלוגים.

לאן מכוונים.

  • הרשאה לכל כלי (allowed_tools) וטוקנים עם תפוגה, מוגבלים לתחום.
  • אסימוני לקוח קצרי חיים במקום מפתחות שירות בדפדפן.
  • הגנת SSRF אחת (רשימת לבנה של יעדים, חסימת כתובות פנימיות) לכל יבוא מכתובת.
  • אימות TLS פעיל תמיד.
  • פעולות הרסניות עוברות תור אישורים.

מה לעשות עד אז. לתת גישת MCP וסוכן רק למי שמורשה לשנות את האתר, ולא לחשוף אותה לצד שלישי (ראו כלי MCP והקשחה).

נושא 5: שרשרת האספקה של העדכונים#

מצב היום. אתרי הלקוח מושכים ליבה, סכימה, פאנלים ו-JS משרת ה-master (ראו עדכוני גרסה). אימות ה-ZIP הוא sha256 שמגיע מאותו שרת, בלי חתימה קריפטוגרפית, וזהות ה-master מקובעת בקוד. חלק מנקודות הקצה של ה-master אינן מאומתות. כל מיזוג ל-main הופך מיד לגרסה latest, בלי שלב staging. ה-master עצמו מתעדכן בהעלאת קבצים ישירה, בלי החלפה אטומית וללא rollback, והתהליך משתמש בהעברה לא מוצפנת. update_js אינו אטומי.

לאן מכוונים.

  • גרסאות שמבוססות על tag ב-git, וארטיפקט שנבנה ב-CI עם sha256 וחתימה, שהאתר מאמת מול מפתח ציבורי מוטמע.
  • ה-master רק מצביע על ארטיפקט, ולא אורז מהדיסק החי. הוא מתעדכן באותו מנגנון כמו הצי.
  • ערוץ stable כברירת מחדל ללקוחות, ו-latest רק לאתרי Wizzo, עם קידום אחרי תקופת ניסיון.
  • אימות לנקודות קצה, והוצאת כתובות ה-master לקונפיגורציה.
  • העברה מוצפנת (SSH או SFTP) והחלפה אטומית גם ל-update_js.

מה לעשות עד אז. לפרוס לשרת ה-master רק בצוות Wizzo, ורק עם publish:api ידני (לא watch:api) ולאחר בדיקות (ראו זרימת עבודה, בדיקות). באתרי לקוח, לעדכן בזמן שמישהו יכול לבדוק את האתר אחר כך.

נושא 6: ריפו שאי אפשר להריץ לבד#

מצב היום. אי אפשר להרים את הליבה מהריפו בלבד: אין סכימת DB, אין קובץ CONFIG_USER לדוגמה, אין docker, אין composer.lock (ו-vendor/ נדרש בזמן ריצה). הסכימה "חיה" על שרת ה-master. חלק מהטבלאות נוצרות בזמן ריצה, ובין הקוד לסכימה יש פערים. הקידומת CRM_ קשיחה בכ-80 מקומות, למרות CONFIG::$db_prefix. בריפו יושבים גם חומרים שלא קשורים לליבה (וידאו, צילומי מסך, קוד מת, חבילות ישנות).

לאן מכוונים.

  • examples/site עם CONFIG_USER מוכן, schema/ עם סכימה ו-seed, ו-docker-compose שמרים אתר עובד בפקודה אחת.
  • composer.lock ו-vendor/ שנבנה ב-CI ונכלל בארטיפקט.
  • ניקוי הריפו מקבצים כבדים וקוד מת, וקבצי .editorconfig ו-.gitattributes.
  • קידומת טבלאות אחת, שנגזרת מהקונפיגורציה.

מה לעשות עד אז. המדריך לבניית אתר מקומי ידני נמצא בזרימת עבודה, והמבנה הקיים במבנה הריפו.

נושא 7: בדיקות ו-CI#

מצב היום. אפס בדיקות אוטומטיות, ואין CI. אין בריפו קובצי LICENSE, CONTRIBUTING או CODEOWNERS (הנוהג הנוכחי מתועד בשליחת שינויים).

לאן מכוונים.

  • php -l, phpcs ו-phpstan (ברמה נמוכה שעולה בהדרגה) על כל Pull Request.
  • phpunit ליחידות, ובדיקות אינטגרציה מול מסד שנבנה מהסכימה, כולל core_ping.
  • סריקת סודות ובדיקת גודל קבצים.
  • הגנת branch על main: CI ירוק וסקירה אנושית.
  • קבצי LICENSE, CONTRIBUTING, SECURITY ו-CODEOWNERS.

מה לעשות עד אז. הרשימה הידנית בבדיקות.

נושא 8: תלויות ונכסים ישנים#

מצב היום. חלק מהספריות המצורפות הן בסוף חייהן ובעלות חולשות מוכרות: CKEditor בגרסה 4.5.6 מ-2015, AWS SDK בגרסה 2 עם Guzzle 3, PHPExcel ו-TCPDF ישנות. סקריפטי דוגמה ובדיקה של ספריות צד שלישי נגישים תחת תיקיית ההפעלה, סקריפטים מ-CDN נטענים בלי SRI, וכל נכס סטטי של הליבה מוגש דרך PHP עם אתחול מלא וללא כותרות מטמון.

לאן מכוונים.

  • החלפה או שדרוג לגרסאות נתמכות, ו-composer audit ב-CI.
  • הסרת קבצי demo ו-test מהחבילה שנפרסת.
  • הגשת נכסים סטטיים ישירות מהשרת, עם cache.
  • נעילת גרסאות ו-SRI לכל משאב חיצוני.

מה לעשות עד אז. לא להסתמך על העורך או על ספריות הייצוא לקלט לא מהימן, ולא להוסיף תלות חדשה בלי להוסיף אותה ל-Composer (ראו Composer).

נושא 9: גרסאות ותהליך#

מצב היום. הגרסה היא 5.0.N שעולה ב-version.txt ידנית בכל שינוי, בלי tag ובלי CHANGELOG אוטומטי. מספרים כפולים כבר נוצרו, והעדכון מסתמך על מספר שרק עולה (ראו ניהול גרסאות). קובץ ה-ZIP של הליבה נבנה מהדיסק החי של ה-master.

לאן מכוונים.

  • SemVer אמיתי, החל מ-5.1.0, עם tag חתום כמקור האמת. version.txt נכתב על ידי תהליך השחרור.
  • CHANGELOG שנוצר מהודעות commit מובנות, שמוגש מקובץ ולא נמשך ממערכת חיצונית בזמן ריצה.
  • הודעות commit במבנה אחיד.

סדר ביצוע#

הסדר המומלץ, מהדחוף לפחות דחוף. כל שלב נשען על הקודם.

שלבתוכןנושאים
1סיבוב סודות, ניקוי היסטוריה וסריקת סודות1
2ניקוי הריפו, .editorconfig, .gitattributes, composer.lock6, 8
3CI בסיסי: php -l, phpcs, phpstan רמה נמוכה, סריקת סודות, הגנת branch7
4examples/site, schema/, docker-compose, בדיקות עשן ראשונות6, 7
5סגירת פרצות ההזרקה, ההרשאה וה-CSRF בנקודות הכניסה הציבוריות2, 3
6חתימת גרסאות, ארטיפקט שחרור, stable כברירת מחדל, ה-master מתעדכן מארטיפקט5, 9
7הקשחת גשר ה-AI וה-MCP, API עם prepared statements4, 2
8החלפת ספריות ישנות, SemVer מ-5.1.08, 9
מידע

הסדר משקף שיקול של סיכון מול מאמץ: שלבים 1 עד 4 זולים יחסית ופותחים את האפשרות לבדוק כל שינוי שאחריהם. חלק משלבים 5 עד 7 יכולים להתקדם במקביל, ושינויים קטנים בהם נכנסים כבר עכשיו כחלק מעבודה רגילה על הקוד.

איך זה משפיע עליכם#

  • מפתח שבונה אתר על הליבה: אין שינוי מיידי ב-API. שינויים שישברו תאימות (חוזה CONFIG_USER, חתימות של DB) יסומנו בגרסה ראשית או שניה ויתועדו בהיסטוריית הגרסאות.
  • מי שתורם לליבה: כללי העבודה כיום בשליחת שינויים ובתקן קוד. קוד חדש נכתב לפי התקן, גם כשהקוד שמסביב לא.
  • מי שמתחזק אתרי לקוחות: הקשחה מפרטת מה אפשר לעשות כבר היום ברמת האתר והשרת.

ראו גם#

מצאתם טעות או חוסר? תקנו את הדף או פתחו Issue בריפו. התיעוד נכתב מתוך הקוד של ליבה 5.0.115.