T09 · Insecure Skill Coding Practices
- Location
scriptBackend.py:141- Finding
Shell Command Injection Through Unsanitized Project Parameters
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This looks like a Django project scaffolding helper, but it runs shell commands built from user-entered names and paths, which can execute unintended local commands.
Review this before installing or running. Only use it in a disposable directory with trusted inputs, and preferably fix it first by replacing shell-string os.system calls with subprocess argument lists, validating Django identifiers, using pathlib for paths, and adding overwrite confirmations. I did not find evidence of exfiltration or persistence, so this is Review rather than malicious.
scriptBackend.py:141Shell Command Injection Through Unsanitized Project Parameters
scriptBackend.py:124Shell and Generated Python Code Injection Through Model Names
scriptBackend.py:72Unpinned Runtime Installation of Third-Party Dependencies
This is a confirmed tainted-flow command injection: appName originates from input() and reaches os.system inside a shell command that writes urls.py. Because the script is an interactive project scaffolder, users are expected to supply these values, which makes exploitability practical rather than theoretical.
break
with open('settings.py', 'w') as f:
f.writelines(lines)
os.system(f'''echo "from django.contrib import admin
from django.urls import path, include
urlpatterns = [
This is another confirmed user-input-to-shell sink where appName flows into os.system. The skill context increases danger because the script is intended to be run locally by developers, giving successful injection direct code execution on their workstation or CI environment.
''')
os.chdir(f'../{projectName}')
os.system(f'''echo "from django.contrib import admin
from django.urls import path, include
urlpatterns = [
This is a direct tainted-flow vulnerability from path input into os.system. In the context of a developer utility, the script is likely run with the user's normal filesystem permissions, so a successful injection can execute arbitrary local commands and modify source code or secrets.
answer = input(f'{color.YELLOW}Would you like to create a venv in the desired directory: {color.END}')
if answer.lower() == 'yes' or answer.lower() == 'y':
os.system(f'python3 -m venv {path}.venv')
loading('Creating Virtual Envirement', 1)
projectName = input(f'{color.YELLOW}Choose a name for your project: {color.END}')
projectName from input() is passed into a shell command that invokes django-admin startproject. Any shell metacharacter in projectName can break command boundaries and execute arbitrary commands, leading to full compromise of the executing user's environment.
os.chdir(path)
os.system('source .venv/bin/activate')
run_command('pip install django')
os.system(f'django-admin startproject {projectName}')
os.chdir(f'{path}{projectName}')
appName = input(f'{color.YELLOW}Choose a name for your app: {color.END}')
appName is directly tainted from user input and reaches a shell execution sink unchanged. This is straightforward command injection and can be exploited with minimal attacker control over the interactive input.
appName = input(f'{color.YELLOW}Choose a name for your app: {color.END}')
os.system(f'django-admin startapp {appName}')
create = input(f'{color.YELLOW}would you like to create a requirements file: {color.END}')
if create.lower() == 'yes' or create.lower() == 'y':
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
END = '\033[0m'
CYAN_BG = '\33[1;37;40m'
os.system('clear')
print(f'''{color.PURPLE}{color.BOLD}
\t _ __ __
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
def DjangoNoRest():
os.chdir(appName)
os.system('touch urls.py')
os.system(f'''echo "from django.urls import path
from .views import *
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
def DjangoNoRest():
os.chdir(appName)
os.system('touch urls.py')
os.system(f'''echo "from django.urls import path
from .views import *
The helper functions use shell redirection and file writes to recreate urls.py, views.py, and serializers.py, which can destroy existing content. There is no confirmation prompt or explicit warning that these operations are destructive to pre-existing files.
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
def DjangoNoRest():
os.chdir(appName)
os.system('touch urls.py')
os.system(f'''echo "from django.urls import path
from .views import *
urlpatterns = [
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
urlpatterns = [
path('AppRoute/', YOUR_VIEW),
]" > urls.py''')
os.system(f'''echo "from django.shortcuts import render
# Create your views here.
def YOUR_VIEW(request):
This shell command interpolates appName, which comes from user input, into a command string passed to os.system. An attacker can supply shell metacharacters in the app name to execute arbitrary commands on the host while the script is generating Django files.
break
with open('settings.py', 'w') as f:
f.writelines(lines)
os.system(f'''echo "from django.contrib import admin
from django.urls import path, include
urlpatterns = [
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
with open(f'../{projectName}/settings.py', 'w') as f:
f.writelines(lines)
os.system('touch urls.py')
os.system('touch serializers.py')
os.system(f'''echo "from rest_framework_nested import routers
from .views import *
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
f.writelines(lines)
os.system('touch urls.py')
os.system('touch serializers.py')
os.system(f'''echo "from rest_framework_nested import routers
from .views import *
router = routers.DefaultRouter()
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
urlpatterns = router.urls" > urls.py''')
os.system(f'''echo "from rest_framework.viewsets import ModelViewSet
from .models import *
from .serializers import *
This command again embeds user-supplied appName inside a shell command string. Because os.system invokes a shell, crafted input can break out of the intended echo statement and run arbitrary commands on the machine.
''')
os.chdir(f'../{projectName}')
os.system(f'''echo "from django.contrib import admin
from django.urls import path, include
urlpatterns = [
module values come from user input and are inserted into a shell echo command that appends Python code to models.py. An attacker can inject shell syntax to execute arbitrary commands, and can also inject malicious Python source into the generated application.
splitted = modulsName.split(', ')
os.chdir(appName)
for module in splitted:
os.system(f'''echo "class {module}(models.Model):
name = models.CharField(max_length=255, unique=True)
def __str__(self):
The path variable is user-controlled and embedded in an os.system call for virtualenv creation. A crafted path containing command separators or subshell syntax can result in arbitrary command execution on the host.
answer = input(f'{color.YELLOW}Would you like to create a venv in the desired directory: {color.END}')
if answer.lower() == 'yes' or answer.lower() == 'y':
os.system(f'python3 -m venv {path}.venv')
loading('Creating Virtual Envirement', 1)
projectName = input(f'{color.YELLOW}Choose a name for your project: {color.END}')
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
exit(1)
os.chdir(path)
os.system('source .venv/bin/activate')
run_command('pip install django')
os.system(f'django-admin startproject {projectName}')
os.chdir(f'{path}{projectName}')
projectName is taken from user input and inserted directly into os.system('django-admin startproject ...'). A malicious project name containing shell metacharacters can trigger arbitrary command execution under the privileges of the user running the script.
os.chdir(path)
os.system('source .venv/bin/activate')
run_command('pip install django')
os.system(f'django-admin startproject {projectName}')
os.chdir(f'{path}{projectName}')
appName = input(f'{color.YELLOW}Choose a name for your app: {color.END}')
This command directly interpolates attacker-controlled appName into an os.system call. An adversary can exploit this to execute arbitrary shell commands instead of merely creating a Django app.
appName = input(f'{color.YELLOW}Choose a name for your app: {color.END}')
os.system(f'django-admin startapp {appName}')
create = input(f'{color.YELLOW}would you like to create a requirements file: {color.END}')
if create.lower() == 'yes' or create.lower() == 'y':
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
create = input(f'{color.YELLOW}would you like to create a requirements file: {color.END}')
if create.lower() == 'yes' or create.lower() == 'y':
os.system('pip freeze > requirements.txt')
setup = input(f'{color.YELLOW}you want to set up the files for django ? (yes or no): {color.END}')
The skill description is very broad and markets automatic environment provisioning and project bootstrapping without clearly defining when the skill should activate or what inputs and boundaries govern its behavior. In an agent ecosystem, vague trigger scope can cause the skill to be invoked in unintended contexts, leading to overbroad actions such as provisioning environments or applying defaults when the user did not explicitly request them.
No manifest is available, so the skill's intended purpose is unknown. Across the file, the code changes directories, installs packages, creates virtual environments, starts Django projects/apps, runs migrations, and writes source files via shell commands, which are broad system-modifying capabilities that are not justified by any declared purpose.
projectName influences the path used for writing settings.py, creating a path traversal or arbitrary file overwrite risk if malicious values such as ../ segments are accepted. Although the script appears aimed at local scaffolding, overwriting attacker-chosen files on the host can still damage the environment or plant malicious configuration.
lines.insert(index, f'\t\'{appName}\'\n')
lines.insert(index, '\t\'rest_framework\',\n')
break
with open(f'../{projectName}/settings.py', 'w') as f:
f.writelines(lines)
os.system('touch urls.py')
os.system('touch serializers.py')
No suspicious patterns detected.