להשתחרר מערכים מקודדים

להשתחרר מערכים מקודדים: אסטרטגיות חכמות יותר לתוכנה מודרנית

ערכים מקודדים בקפידה נראים כמו קיצורי דרך. מפתח זקוק לכתובת URL של מסד נתונים, מקליד אותה ישירות לתוך מחרוזת חיבור וממשיך הלאה. שלושה חודשים לאחר מכן, כתובת ה-URL משתנה, השינוי מתבצע בקובץ אחד אך מושמט בארבעה אחרים, והייצור מופסק בשעה 2 לפנות בוקר. מפתח זקוק למפתח API, מקליד אותו בקובץ המקור, מבצע commit ו-push. שישה חודשים לאחר מכן, המאגר משוכפל, המפתח מופיע ב-public fork, והחשבון נפרץ לפני שמישהו שם לב. אלה אינם מקרי קצה. הם המסלול הסטנדרטי של ערכים מקודדים בקפידה במערכות תוכנה: קיצורי דרך שנראים לא מזיקים שמצטברים לחוב תחזוקה, אירועי אבטחה וכשלים בפריסה.

מצא ובטל ערכים מקודדים בקפידה

בטל והיפטר מערכי קידוד קשיח

למד עוד

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

מהו ערך קשיח?

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

דוגמאות נפוצות:

  • מחרוזת חיבור למסד נתונים המוקלדת ישירות לתוך מחלקת תצורה
  • מפתח API או אסימון גישה בקובץ מקור
  • כתובת URL של שירות המפנה לסביבה ספציפית
  • סף מספרי (if (amount > 5000)) ללא הסבר או מקור חיצוני
  • נתיב קובץ בהנחה של פריסת שרת ספציפית
  • מחרוזת תפקיד משתמש ("admin") מפוזרים על פני בדיקות אישור

ערכים מקודדים קשיחים מופיעים בכל שפה ובכל בסיס קוד. יישומי מיינפריים מדור קודם מקודדים שמות של מערכי נתונים, קודי אזור וספי עסקיים ספציפיים לסביבה ישירות בתוכניות COBOL. מיקרו-שירותים מודרניים צוברים ערכי פסק זמן מקודדים קשיחים, ספירת ניסיונות חוזרים וכתובות URL לגילוי שירותים במחלקות יישומים. הצורה משתנה עם השפה; הבעיה זהה.

ערכים קשיחים לעומת קבועים: מה ההבדל?

ערכים קשיחים מתבלבלים לעיתים קרובות עם קבועים, אך ההבדל חשוב. קבוע מייצג עובדה יציבה, מכוונת, ברמת התחום, שהיא נכונה מעצם הגדרתה וסביר להניח שלא תשתנה: Math.PI, HTTP_STATUS_OK = 200, MAX_RETRY_ATTEMPTS = 3 (אם שלושה באמת נכונים לכל ההקשרים). קבועים מתאימים בקוד. הם מוסיפים בהירות, מונעים שגיאות כתיב ומבהירים את הכוונה.

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

מהו קידוד רך?

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

ההבדל בין קידוד קשיח לקידוד רך הוא ההבדל בין מערכת הדורשת שינוי קוד ופריסה לעדכון שיעור מס, לבין מערכת המאפשרת לחבר צוות תפעול לעדכן אותו בקובץ תצורה ולהפעיל מחדש שירות. בקנה מידה גדול, הבדל זה מייצג אלפי שעות מהנדס וסיכון תפעולי משמעותי.

למה קידוד קשיח הוא נוהג רע

זה הורס את יכולת התחזוקה

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

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

זה חוסם בדיקות ו-CI/CD

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

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

זה יוצר פגיעויות אבטחה חמורות

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

OWASP מזהה במפורש סיסמאות מקודדות כפגיעת אבטחה קריטית (CWE-259, CWE-798). הנחיות NIST דורשות שלא לאחסן אישורים בקוד המקור. למרות זאת, דליפות אישורים דרך ערכים מקודדים נותרות בין הגורמים השכיחים ביותר לאירועי אבטחה בענן.

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

אישורים מקודדים ומפתחות API: הקטגוריה בעלת הסיכון הגבוה ביותר

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

איך נראים אישורים מקודדים בקשיחות

פִּיתוֹן

# Python -- hardcoded database credentials (never do this)
connection = psycopg2.connect(
    host="prod-db.internal.example.com",
    database="accounts",
    user="app_service",
    password="s3cr3tP@ssword!"   # hardcoded secret in source code
)

# Python -- correct approach: load from environment
import os
connection = psycopg2.connect(
    host=os.environ["DB_HOST"],
    database=os.environ["DB_NAME"],
    user=os.environ["DB_USER"],
    password=os.environ["DB_PASSWORD"]
)

תאווה

// Java -- hardcoded API key (never do this)
private static final String API_KEY = "sk-prod-a1b2c3d4e5f6g7h8i9j0";

// Java -- correct approach: load from environment
private static final String API_KEY = System.getenv("OPENAI_API_KEY");

כיצד לתקן אישורים מקודדים בקשיחות

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

שירותי ניהול סודות , AWS Secrets Manager, HashiCorp Vault, Azure Key Vault ו-Google Secret Manager, הם גישת ייצור לסיבוב, ביקורת והפצה של סודות בין שירותים. האפליקציה מאחזרת את הסוד בעת ההפעלה (או לפי דרישה) מהכספת במקום ממשתנה סביבה, ומספקת סיבוב ללא פריסה מחדש ויומן ביקורת מלא של כל גישה.

.env קבצים (באמצעות ספריות כמו python-dotenv or dotenv ב-Node.js) מתאימים לפיתוח מקומי. הם מספקים את אותו ממשק כמו משתני סביבה אך נטענים מקובץ מקומי. הכלל הקריטי: .env הקבצים חייבים להיות ב .gitignore ואסור להתחייב לעולם.

גילוי סודות שכבר בוצעואם סוד הוקידוד והופעל, יש להתייחס אליו כנפגע ולסובב אותו באופן מיידי. מחיקת הערך מהענף הנוכחי אינה מסירה אותו מהיסטוריית ה-git. כלים כמו git-filter-branch או שמנקה המאגרים של BFG יכול לנקות את ההיסטוריה, אבל ההנחה הבטוחה ביותר לאחר commit היא שהסוד נחשף.

כיצד למנוע מפתחות API מקודדים בקשיחות

עבור מפתחות API של צד שלישי, החלופות לקידוד קשיח תלויות בהקשר:

  • יישומים בצד השרתמשתני סביבה או שירותי ניהול סודיות
  • צינורות CI / CDמשתני סודות צינור (סודות פעולות GitHub, משתני CI של GitLab)
  • אפליקציות ניידותמפתחות API לעולם לא צריכים להיות בקוד בצד הלקוח; יש להשתמש בפרוקסי backend שקורא ל-API כאשר המפתח מאוחסן בצד השרת.
  • סוכני בינה מלאכותית ואינטגרציות לתואר שניטען מפתחות API מהסביבה בעת אתחול הסוכן, לעולם אל תעביר אותם כמחרוזות מקודדות קשיחות בהנחיות או בקריאות לפונקציה

קידוד מאובטח של RPG ב-IBM i פועל לפי אותו עיקרון: אזורי נתונים חיצוניים, תורי נתונים או ערכי מערכת צריכים להכיל פרמטרי חיבור ספציפיים לסביבה במקום לקודד אותם במקור התוכנית.

כיצד למנוע ערכים מקודדים בקשיחות: השלמת תבניות עם קוד

משתני סביבה

משתני סביבה הם הפתרון האוניברסלי ביותר. כל מערכת הפעלה, פלטפורמת ענן, מערכת קונטיינריזציה ומערכת פריסה מרכזית תומכת בהם.

פִּיתוֹן

# Python: load all configuration from environment
import os
from dotenv import load_dotenv

load_dotenv()  # loads .env file in development; ignored in production

DATABASE_URL = os.environ["DATABASE_URL"]
API_BASE_URL = os.environ.get("API_BASE_URL", "https://api.example.com")
MAX_RETRIES  = int(os.environ.get("MAX_RETRIES", "3"))
DEBUG_MODE   = os.environ.get("DEBUG", "false").lower() == "true"

JavaScript

// Node.js: access environment variables
require('dotenv').config();  // load .env in development

const config = {
  dbUrl:      process.env.DATABASE_URL,
  apiKey:     process.env.API_KEY,
  port:       parseInt(process.env.PORT, 10) || 3000,
  debug:      process.env.NODE_ENV !== 'production',
};

תאווה

// Java: environment variables via System.getenv()
public class AppConfig {
    public static final String DB_URL  = System.getenv("DATABASE_URL");
    public static final String API_KEY = System.getenv("THIRD_PARTY_API_KEY");
    public static final int    TIMEOUT = Integer.parseInt(
        Optional.ofNullable(System.getenv("REQUEST_TIMEOUT_MS")).orElse("5000")
    );
}

קבצי תצורה

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

יאמל

# config/production.yaml
database:
  host: prod-db.internal
  port: 5432
  pool_size: 20

api:
  base_url: https://api.partner.com/v2
  timeout_ms: 3000
  max_retries: 3

features:
  new_checkout: true
  beta_dashboard: false

פִּיתוֹן

# Load at startup; never hardcode the values it contains
import yaml

with open(f"config/{os.environ['APP_ENV']}.yaml") as f:
    config = yaml.safe_load(f)

timeout = config["api"]["timeout_ms"]

הזרקת תלות

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

תאווה

// Spring Boot: inject configuration via @Value
@Service
public class PaymentService {
    @Value("${payment.api.url}")
    private String apiUrl;

    @Value("${payment.api.timeout-ms}")
    private int timeoutMs;

    // No hardcoded URL or timeout anywhere in this class
    public PaymentResult process(Payment payment) {
        // uses apiUrl and timeoutMs injected from application.properties
    }
}

פִּיתוֹן

# Python: simple constructor injection
class EmailService:
    def __init__(self, smtp_host: str, smtp_port: int, api_key: str):
        self.smtp_host = smtp_host
        self.smtp_port = smtp_port
        self.api_key   = api_key

# Wire at application startup, reading from environment
email_service = EmailService(
    smtp_host=os.environ["SMTP_HOST"],
    smtp_port=int(os.environ["SMTP_PORT"]),
    api_key=os.environ["EMAIL_API_KEY"],
)

קבועים מרכזיים ואנומים

ערכים קבועים באמת על ידי עיצוב, קודי סטטוס HTTP, מצבים ספציפיים לתחום, מזהי פרוטוקול, שייכים למודול קבועים יחיד בעל שם ולא מפוזרים כמחרוזות ליטרליות.

פִּיתוֹן

# Python: centralised constants
from enum import Enum

class OrderStatus(Enum):
    PENDING   = "pending"
    CONFIRMED = "confirmed"
    SHIPPED   = "shipped"
    DELIVERED = "delivered"
    CANCELLED = "cancelled"

# Usage: no magic strings scattered across modules
if order.status == OrderStatus.CONFIRMED:
    notify_warehouse(order)

תאווה

// Java: enum with business meaning
public enum UserRole {
    ADMIN("admin"),
    EDITOR("editor"),
    VIEWER("viewer");

    private final String value;
    UserRole(String value) { this.value = value; }
    public String getValue() { return value; }
}

// Replaces scattered "admin", "editor", "viewer" strings
if (user.getRole() == UserRole.ADMIN) {
    grantFullAccess(user);
}

קידוד קשיח בשפות ספציפיות

מהו קידוד קשיח בפייתון?

בפייתון, קידוד קשיח מופיע לרוב כמחרוזות ליטרליות עבור כתובות URL ואישורים, קבועים מספריים בלוגיקה עסקית ונתיבי קבצים בהנחה של מבנה ספריות ספציפי. os.environ ו python-dotenv הם המנגנונים הסטנדרטיים לתצורה מבוססת סביבה. configparser המודול מטפל בקבצי תצורה בפורמט INI. pydantic-settings מספק תצורה מאומתת-סוג ממשתני סביבה עם ערכי ברירת מחדל, וזו הגישה המומלצת עבור שירותי Python לייצור.

זיהוי ערכים קשיחים בפייתון: כלי ניתוח סטטיים, כולל Bandit (לקידוד קשיח הקשור לאבטחה כמו סיסמאות ומפתחות), Pylint ו-Semgrep, יכולים לזהות באופן אוטומטי אישורים קשיחים ומספרי קסם.

מהו קידוד קשיח (hardcoding) בג'אווה?

ב-Java, ערכים מקודדים מופיעים לעתים קרובות כ- private static final String שדות, @Value הערות עם ברירות מחדל מוטבעות שיש להחיצון, וליטרלים בלוגיקה עסקית. Spring Boot's application.properties ו application.yml קבצים הם מנגנון ההחצנה הסטנדרטי. @ConfigurationPropertiesמחלקות -annotated מספקות אובייקטי תצורה מאומתים ובטוחים לסוגים מקובצי YAML או קבצי מאפיינים.

זיהוי ערכים קשיחים ב-Java: SpotBugs עם התוסף Find Security Bugs מזהה אישורים קשיחים. SonarQube מסמן מספרי קסם, כתובות URL קשיחות וסיסמאות קשיחות. SMART TS XLניתוח הארגון של מכסה בסיסי קוד של Java לצד COBOL ושפות מדור קודם אחרות.

קידוד קשיח בקוד מדור קודם ובקוד מיינפריים

לתוכניות COBOL, RPG ו-PL/I במחשבים מרכזיים ובמערכות בינוניות של IBM יש דפוסי קידוד קשיח ספציפיים: שמות מערכי נתונים המוטמעים במשפטי DD, מזהי סביבה בלוגיקת התוכנית וספי עסקים המהונדסים ישירות לתוך תוכניות. הפיכת ערכים אלה לחוצנים דורשת כלים מודעים למיינפריים: פרמטרי מערכת (SYSPARM), אזורי נתונים חיצוניים, טבלאות תצורה ב-DB2 ו-JCL פרמטריזטורי. כלי ניתוח סטטיים שמבינים שפות מיינפריים נדרשים כדי לזהות דפוסים אלה בקנה מידה גדול.

שיפוץ בעולם האמיתי: מקידוד קשיח לניתן להגדרה

גישת הרפקטורינג התלת-פאזי

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

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

שלב 3: אכיפה. הוספת בדיקות ניתוח סטטיות לצינור CI שנכשלות באישורים חדשים המקודדים בקשיחות. הוספת כללי linting המסמנים מספרי קסם. הוספת פריטי רשימת בדיקה לסקירת קוד. המטרה היא להקשות על הוספת ערך המקודד בקשיחות מאשר שימוש בתבנית הנכונה.

זיהוי ערכים קשיחים בפרויקטים מדור קודם

בפרויקטים מדור קודם שבהם ערכים מקודדים באופן קשיח הצטברו לאורך שנים:

  • השתמש grep או חיפוש במאגר אחר דפוסים נפוצים: מחרוזות חיבור, password, apikey, דפוסי כתובות IP ושמות שירותים ידועים
  • הפעלת כלי ניתוח סטטי (Bandit, SonarQube, Semgrep, SMART TS XL) כדי לקבל רשימה מלאה ללא סקירה ידנית של קובץ אחר קובץ
  • בדוק את היסטוריית ה-git עבור סודות שבוצעו ונמחקו בעבר, הם עדיין נגישים בהיסטוריית המאגר.
  • חפש ערכים המופיעים באופן זהה בקבצים מרובים, אלו מועמדים לריכוזיות

מניעת הצגת ערכים מקודדים בקשיח

  • ווים מראשהפעל סריקת אישורים (למשל, detect-secrets, git-secrets, truffleHog) על כל קומיט לפני שהוא מגיע למאגר
  • שערי צינור CI: בניית קבצים כושלת המכילה ממצאי ניתוח סטטי שהוצגו לאחרונה עבור אישורים או מספרי קסם
  • רשימות בדיקה לסקירת קודפריטים מפורשים להחצנת תצורה בתהליך הסקירה של הצוות
  • קליטת מפתחים: הפוך את התבניות הנכונות לברירות המחדל, ספק תבנית פרויקט שכבר משתמשת במשתני סביבה ו-a .env.example פילה

איך SMART TS XL מבטל ערכים קשיחים בקנה מידה גדול

חיפוש ידני ו-grep מספיקים למציאת מקרים ברורים בבסיסי קוד קטנים. במערכות ארגוניות המשתרעות על פני מיליוני שורות ב-COBOL, Java, Python, .NET, RPG ו-SQL, זיהוי מקיף של ערכים בקידוד קשיח דורש ניתוח מבני אוטומטי. SMART TS XL מבצע ניתוח סטטי בכל השפות הללו בו זמנית, ובונה מודל הצלבה מאוחד שמזהה:

  • ערכי מחרוזת מילוליים בפרמטרי חיבור וקריאות אימות, המסומנים כחשיפת אישורים פוטנציאלית
  • מספרי קסם בלוגיקה עסקית בהשוואה לקו בסיס הניתן להגדרה, תוך זיהוי ערכים שאינם עקביים בין מודולים או המופיעים עם ערכים שונים במקומות שונים
  • ערכים ליטרליים כפולים המופיעים בקבצים מרובים אך משרתים את אותה מטרה לוגית, מה שמצביע על הזדמנויות לריכוזיות
  • ערכים בתוכניות COBOL המקודדים מזהים ספציפיים לסביבה המנוהלים בדרך כלל באמצעות פרמטרי JCL
  • נתיבי זרימת נתונים מערכים מקודדים קשיחים דרך המערכת, המציגים אילו פעולות במורד הזרם תלויות בהם לפני קבלת החלטה על עיבוד מחדש

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

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

קידוד קשיח הוא בעיית משמעת, לא בעיית ידע

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

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

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