# Command Injection और Path Traversal — LLM Application Security

Source: https://www.geekswithgeeks.com/hi/llm-security/o-shell

> मॉडल आउटपुट कभी shell से न दें, और file पहुँच सीमित करें।

## Shell = हमलावर के पाठ का व्याख्याकार

यदि tool मॉडल आउटपुट जोड़कर shell command बनाता है (`"cat " + filename` shell से चलाया), तो `;`, `&&`, `|` और backticks जैसे अक्षर हमलावर को अतिरिक्त commands जोड़ने देते हैं। बचाव: **shell उपयोग न करें**; programs को **argument list** से बुलाएँ ताकि हर मान एक ही argument रहे; कौन-सी commands और मान स्वीकार्य हैं उनकी **allow-list** रखें; credentials रहित **sandbox** में चलाएँ। Files के लिए **असली path निकालें** (`..` और symlinks अनुसरित करके) और जाँचें कि वह **अनुमत base folder** के भीतर रहता है; absolute paths अस्वीकार करें। उदाहरण `shell=True` call में injected `echo` चलता दिखाते हैं, सुरक्षित allow-list जाँच, और path guard जो `../` और absolute paths रोकता है जबकि हानिरहित `sub/../notes.txt` की अनुमति देता है।

## shell=True बनाम argument list, चलाकर

मैंने यह सादे Python 3 (सिर्फ़ standard library) से चलाया। यहाँ सारे हमले स्थानीय डेटा पर हानिरहित प्रदर्शन हैं, कोई असली system उपयोग नहीं हुआ। `shell=True` के साथ, semicolon के बाद का पाठ दूसरी command के रूप में चलता है और INJECTED छापता है। सुरक्षित रूप माँगे नाम को allow-list से जाँचता है और argument list के साथ `echo` चलाता है, इसलिए पूरी string अस्वीकृत होती है (या अनुमत नाम के लिए एक सादा argument माना जाता है)। यहाँ command हानिरहित `echo` है।

```python
import subprocess

model_output = "report.txt; echo INJECTED"
unsafe = subprocess.run("echo reading " + model_output, shell=True, capture_output=True, text=True)
print("UNSAFE (shell=True):", unsafe.stdout.strip().replace("\n", " | "))

ALLOWED = {"report.txt", "summary.txt"}
def safe_read(name):
    if name not in ALLOWED: return f"refused: {name!r} is not an allowed file"
    return subprocess.run(["echo", "reading", name], capture_output=True, text=True).stdout.strip()   # no shell, argument list
print("SAFE   :", safe_read(model_output))
print("SAFE ok:", safe_read("report.txt"))

```

Output:

```
UNSAFE (shell=True): reading report.txt | INJECTED
SAFE   : refused: 'report.txt; echo INJECTED' is not an allowed file
SAFE ok: reading report.txt
```

## File paths सीमित करना, चलाकर

मैंने यह सादे Python 3 (सिर्फ़ standard library) से चलाया। यहाँ सारे हमले स्थानीय डेटा पर हानिरहित प्रदर्शन हैं, कोई असली system उपयोग नहीं हुआ। Guard हर path resolve करके जाँचता है कि वह अनुमत folder के भीतर रहता है। `notes.txt` और `sub/../notes.txt` उसी अनुमत file पर resolve होते हैं, जबकि `../secret.txt` और `/etc/passwd` रुकते हैं।

```python
import os, tempfile

def safe_open(base, user_path):
    full = os.path.realpath(os.path.join(base, user_path))
    if os.path.commonpath([os.path.realpath(base), full]) != os.path.realpath(base):
        return "blocked: path escapes the allowed folder"
    return "ok: " + os.path.relpath(full, os.path.realpath(base))

with tempfile.TemporaryDirectory() as base:
    open(os.path.join(base, "notes.txt"), "w").write("hello")
    for p in ("notes.txt", "../secret.txt", "sub/../notes.txt", "/etc/passwd"):
        print(f"{p:20} -> {safe_open(base, p)}")

```

Output:

```
notes.txt            -> ok: notes.txt
../secret.txt        -> blocked: path escapes the allowed folder
sub/../notes.txt     -> ok: notes.txt
/etc/passwd          -> blocked: path escapes the allowed folder
```

## Subprocesses की जगह library calls पसंद करें

यदि Python function काम कर सके, तो उसे बुलाना shells और argument parsing से पूरी तरह बचाता है।

**Quiz:** Argument list से program बुलाना shell=True से सुरक्षित क्यों है?

- [ ] यह GPUs पर तेज़ चलता है
- [x] हर मान एक ही argument रहता है और shell syntax के रूप में कभी व्याख्यायित नहीं होता
- [ ] यह आउटपुट छिपाता है
- [ ] Shells अवैध हैं

*Answer:* हर मान एक ही argument रहता है और shell syntax के रूप में कभी व्याख्यायित नहीं होता. Shell के बिना ; और && जैसे अक्षरों का कोई विशेष अर्थ नहीं।
