T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/predict.py:36
- Finding
- Unsafe Deserialization of Local Model Artifacts## Vulnerability Details **File Location**: `scripts/predict.py:36-41` **Vulnerability Type**: Unsafe pickle-compatible deserialization **Risk Level**: Medium ### Vulnerable Code ```python def load_model(): model = joblib.load(config.MODEL_PATH) with open(config.FEATURE_PATH) as f: feature_names = json.load(f) scaler = joblib.load(config.SCALER_PATH) return model, feature_names, scaler ``` The affected artifact paths are defined in `scripts/config.py:45-47`: ```python MODEL_PATH = os.path.join(MODEL_DIR, "xgb_stock_model.pkl") FEATURE_PATH = os.path.join(MODEL_DIR, "feature_names.json") SCALER_PATH = os.path.join(MODEL_DIR, "scaler.pkl") ``` ### Technical Analysis `joblib.load()` relies on Python's pickle-compatible deserialization mechanism. Pickle artifacts can contain object-reconstruction instructions that invoke arbitrary Python callables during loading. Therefore, loading an attacker-controlled `.pkl` file is equivalent to executing untrusted code. The model and scaler are normally generated locally by `scripts/train.py`, so this finding does not indicate intentionally embedded malicious behavior. However, `load_model()` performs no signature, checksum, ownership, permission, symlink, or provenance validation before deserializing the files. A replaced artifact in a shared, compromised, or attacker-writable project directory could consequently execute code when prediction starts. ### Attack Path 1. An attacker gains the ability to replace either `scripts/models/xgb_stock_model.pkl` or `scripts/models/scaler.pkl`, such as through a compromised project archive, shared writable workspace, poisoned artifact distribution, or another process with write access. 2. The attacker creates a malicious pickle-compatible artifact whose reconstruction routine executes an operating-system command or arbitrary Python code. 3. A user runs `python3 predict.py`, or runs `python3 main.py` with th ...[truncated 1181 chars]
- Remediation
- ## Remediation Suggestions 1. **Replace executable serialization formats** - Store the XGBoost model using a non-pickle model format, such as JSON or UBJSON. - Store scaler parameters and feature metadata in validated JSON or another non-executable data format. - Reconstruct the scaler from validated numeric fields rather than deserializing a Python object. 2. **Authenticate artifacts** - Generate a cryptographic digest or digital signature when training completes. - Verify the digest or signature before loading either artifact. - Store the trusted verification key or expected digest separately from the writable artifact directory. 3. **Restrict filesystem access** - Place model artifacts in a directory writable only by the owning user. - Reject symbolic links and files with unexpected ownership or group/world-writable permissions. - Open and validate artifacts using race-resistant filesystem operations where supported. 4. **Validate artifact provenance and schema** - Record model version, expected type, library versions, feature count, and training metadata. - Reject artifacts with unexpected metadata or incompatible versions. - Do not accept downloaded or user-supplied `.pkl` files unless they originate from an authenticated source. 5. **Document the trust boundary** - Clearly warn that `joblib` and pickle artifacts must never be loaded from untrusted sources. - Treat models bundled in third-party archives or copied from shared locations as executable content. 6. **Use containment as defense in depth** - Run prediction under a dedicated, least-privileged account or isolated container. - Limit filesystem access, environment secrets, and outbound network access available to the prediction process.
