T09 · Insecure Skill Coding Practices
- Location
scripts/notebook_executor.py:138- Finding
Arbitrary Python Code Injection Through Notebook Parameters
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a notebook creation and execution helper, but it gives an agent high-impact code execution paths with weak scoping and unsafe input handling.
Install only if you will use it on trusted notebooks and trusted parameter values. Review generated notebooks before running them, provide explicit output paths to avoid overwriting originals, and prefer an isolated environment with restricted filesystem and network access.
scripts/notebook_executor.py:138Arbitrary Python Code Injection Through Notebook Parameters
scripts/notebook_creator.py:218Arbitrary Python Code Injection Through Notebook Template Fields
scripts/notebook_executor.py:164Predictable Temporary Notebook Path Enables Symlink File Overwrite
The declared description claims a comprehensive notebook management system including creation, execution, debugging, and analysis. The supplied code only implements notebook creation from templates and saving the resulting .ipynb file. While some generated templates contain code cells for analysis or model training, the script itself does not run those notebooks, debug them, inspect existing notebooks, or provide broader management operations. Therefore the description materially overstates the implemented capabilities.
The description significantly overstates the implemented functionality. The supplied code is focused narrowly on executing existing Jupyter notebooks, with timeout handling, optional parameter injection, error detection, and basic output extraction. It does not create notebooks, provide a broader management system, or implement meaningful debugging or analysis capabilities beyond simple error reporting and output summarization. This is a material description-to-behavior mismatch in primary scope and advertised capabilities.
The declared description claims a full notebook management system covering creation, execution, debugging, and analysis. The supplied code chunk is specifically a unit test file for notebook creation functionality. It imports NotebookCreator and checks template-based notebook generation, metadata, JSON validity, output path handling, and related creation features. There is no implementation in this chunk for executing notebooks, debugging them, managing existing notebooks, or performing analysis beyond embedding template text. Because the observed behavior is much narrower and primarily a test harness, the description materially overstates and misrepresents what this code chunk actually does.
The declared description says the skill is a complete Jupyter notebook management system with creation, execution, debugging, and analysis capabilities. However, the supplied code chunk is only a unit/integration test file (tests/test_executor.py). It exercises NotebookExecutor and NotebookCreator, but does not itself provide those management capabilities. Its direct behavior is creating temporary notebooks, invoking executor methods, and asserting expected results. While the tested components appear related to notebook execution and creation, this chunk’s actual role is test automation, not a complete management system. Therefore the description does not accurately represent what this supplied code chunk actually does.
Referenced artifact was not completely inspected
- `scripts/notebook_creator.py` - Template-based notebook generation
Referenced artifact was not completely inspected
- `scripts/notebook_creator.py` - Template-based notebook generation
Running 'jupyter nbconvert --execute' causes all code cells in the notebook to execute, which can perform arbitrary actions such as reading secrets, modifying files, or making network requests. In this skill context, notebook execution is a core feature, so the absence of a prominent safety disclosure and trust boundary makes accidental execution of untrusted notebooks significantly dangerous.
The documentation describes executing notebooks and notes that output defaults to overwriting the input notebook, but it does not prominently warn that notebook execution runs arbitrary code and can modify files. In this skill context, that omission is meaningful because Jupyter notebooks are executable artifacts and overwrite behavior can destroy user work or facilitate unsafe execution if a user supplies an untrusted notebook.
The README suggests invoking the skill with very broad natural-language prompts like 'Create a data analysis notebook for my sales data' and 'Run it with my Q4_sales.csv file' without clearly stating when the skill should or should not take control. In an agent environment, vague activation boundaries can cause unintended triggering for ordinary data-assistance requests, leading the agent to create or execute notebooks and handle files when the user may not have intended an execution-capable workflow.
The skill advertises and instructs use of file read/write and shell-backed notebook operations, but it does not declare any explicit tool scope such as permissions or allowed-tools. In an agent ecosystem, missing scope boundaries can let the skill be invoked with broader-than-expected capabilities, increasing the chance of arbitrary notebook execution, file modification, and shell command use against user data or the host environment.
The trigger conditions are broad enough to activate on generic data-analysis requests, not just explicit notebook management tasks. Overbroad activation can cause the agent to select a high-privilege skill unnecessarily, exposing users to unintended file access, notebook execution, or shell-backed operations in contexts where safer, narrower skills would suffice.
Environment-based activation on merely detecting notebook files in the working directory is ambiguous and can trigger this skill without clear user intent. In a system that can read, write, and execute notebooks, passive discovery-based activation raises the risk of processing sensitive files or running notebooks the user never asked to touch.
The executor defaults to overwriting the input notebook when no output path is provided, and later replaces the destination with the executed temporary notebook. In a notebook-management skill, this can silently destroy the original file, including evidence, comments, metadata, or prior outputs, which is especially risky when operating on user-supplied notebooks.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
if verbose:
print(f"🔧 Running: {' '.join(cmd)}")
result = subprocess.run(
cmd,
capture_output=True,
text=True,
The dependency is specified with only a lower bound, so builds may resolve to different versions over time. This weakens supply-chain control, reduces reproducibility, and can allow vulnerable or incompatible releases to be installed without review.
##Core Dependencies
jupyter>=1.0.0
nbformat>=5.0.0
nbconvert>=6.0.0
ipykernel>=6.0.0
Using an unpinned nbformat version means the environment can silently drift to newer releases. That increases supply-chain and reproducibility risk because a future vulnerable or breaking version could be installed unexpectedly.
##Core Dependencies
jupyter>=1.0.0
nbformat>=5.0.0
nbconvert>=6.0.0
ipykernel>=6.0.0
nbconvert is unpinned despite being a package with a history of security advisories, including file read/write and XSS issues. Without an exact version, deployments may pull in an affected release, making notebook conversion workflows riskier.
##Core Dependencies
jupyter>=1.0.0
nbformat>=5.0.0
nbconvert>=6.0.0
ipykernel>=6.0.0
# Data Science Libraries
The manifest references nbconvert without pinning a specific version, and nbconvert has multiple known advisories including path traversal and XSS issues. Because this skill manages notebooks and likely converts or exports them, the context makes uncertain nbconvert versions more dangerous than in a generic project.
An unpinned ipykernel dependency allows uncontrolled upgrades that may introduce security flaws or incompatible runtime behavior. In a notebook execution skill, kernel packages are especially sensitive because they sit in the code-execution path.
jupyter>=1.0.0
nbformat>=5.0.0
nbconvert>=6.0.0
ipykernel>=6.0.0
# Data Science Libraries
pandas>=1.3.0
pandas is unpinned, so the installed version may vary by install time or mirror state. This creates reproducibility issues and may expose the environment to vulnerable releases or dependency conflicts.
ipykernel>=6.0.0
# Data Science Libraries
pandas>=1.3.0
numpy>=1.20.0
matplotlib>=3.3.0
seaborn>=0.11.0
pandas has at least one disputed advisory related to unsafe deserialization, and the manifest does not prove a safe version is installed. The risk is lower than execution-oriented notebook packages, but uncertainty remains because notebooks often load external data and serialized objects.
numpy is specified with a lower bound only, which permits unintended upgrades. Since it is a foundational dependency, version drift can propagate risk broadly across the environment.
# Data Science Libraries
pandas>=1.3.0
numpy>=1.20.0
matplotlib>=3.3.0
seaborn>=0.11.0
scikit-learn>=1.0.0
numpy has multiple historical advisories and is not pinned, so affected versions cannot be ruled out. As a core dependency used broadly across the notebook stack, a vulnerable numpy release can expand blast radius across many operations.
matplotlib is unpinned, so installations are not deterministic and may consume vulnerable or incompatible releases. While not always directly exploitable, this still weakens supply-chain hygiene.
# Data Science Libraries
pandas>=1.3.0
numpy>=1.20.0
matplotlib>=3.3.0
seaborn>=0.11.0
scikit-learn>=1.0.0
seaborn is not version-pinned, which allows dependency drift and reduces confidence in the security and stability of deployed environments. This is a standard supply-chain hardening issue.
pandas>=1.3.0
numpy>=1.20.0
matplotlib>=3.3.0
seaborn>=0.11.0
scikit-learn>=1.0.0
# Advanced Notebook Tools