T09 · Insecure Skill Coding Practices
- Location
skill_composer.py:151- Finding
Arbitrary Python Source Injection Through Generated Workflow Steps
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent workflow builder, but it can automatically persist executable Python generated from unsafely handled user and registry text.
Review carefully before installing. Use an isolated environment, do not expose the Streamlit UI to untrusted users, disable automatic registry updates if possible, inspect every generated FLOW before running it, constrain registry and output paths, and pin dependencies with a lockfile.
skill_composer.py:151Arbitrary Python Source Injection Through Generated Workflow Steps
skill_composer.py:169Registry Metadata Can Inject Python Into Generated Workflows
skill_scanner_integration.py:140Security Scanner Fails Open and Reports Accepted Risk as Passed
skill_scanner_integration.py:128Path-Only Scan Cache Permits Time-of-Check to Time-of-Use Bypass
requirements.txt:4Unpinned and Unnecessarily Broad Third-Party Dependency Installation
The skill claims orchestration but also appears to include filesystem traversal, Python file reading, AST analysis, caching, and malicious-pattern scanning. Those extra capabilities expand the attack surface and may expose local source code or sensitive files if scan scope is not constrained, especially in a tool that automatically composes and persists workflows.
The skill claims orchestration but also appears to include filesystem traversal, Python file reading, AST analysis, caching, and malicious-pattern scanning. Those extra capabilities expand the attack surface and may expose local source code or sensitive files if scan scope is not constrained, especially in a tool that automatically composes and persists workflows.
The skill claims orchestration but also appears to include filesystem traversal, Python file reading, AST analysis, caching, and malicious-pattern scanning. Those extra capabilities expand the attack surface and may expose local source code or sensitive files if scan scope is not constrained, especially in a tool that automatically composes and persists workflows.
The skill claims orchestration but also appears to include filesystem traversal, Python file reading, AST analysis, caching, and malicious-pattern scanning. Those extra capabilities expand the attack surface and may expose local source code or sensitive files if scan scope is not constrained, especially in a tool that automatically composes and persists workflows.
Referenced artifact was not completely inspected
- `skill_scanner_integration.py` - Security scanning
The README states that Flow will compose and register new skills, but it does not clearly warn that this process persists generated artifacts to disk for future reuse. In a system that transforms user requests and third-party skills into executable workflows, undisclosed write/persistence behavior can lead to accidental storage of unsafe code, sensitive prompts, or unreviewed automation artifacts.
The skill advertises capabilities that imply file access, code generation, networking, and shell interaction, but it does not declare any explicit tool scope or permissions boundary. For an orchestrator that composes and saves workflows, this omission increases the chance of over-broad execution and makes it difficult for users or a host platform to constrain dangerous actions.
The skill states that it tracks skill usage and saves newly composed workflows for reuse, but it does not warn users in the description that their requests and generated artifacts may be persisted. This creates privacy and governance risk because sensitive prompts, workflow logic, or operational metadata could be stored unexpectedly and reused later.
A broadly worded natural-language invocation can cause the skill to trigger on vague requests and perform powerful orchestration or code-generation steps without sufficiently specific user intent. In a skill that may read files, compose workflows, and save outputs, accidental invocation can lead to unintended actions or over-collection of data.
The code composes a new skill and, when auto_update_registry is enabled, immediately persists and registers it without any explicit user confirmation or dry-run safeguard. In an orchestrator that turns natural-language requests into executable workflows, this can cause unintended local state changes, persistence of unsafe/generated artifacts, and trust-boundary issues if a user did not intend filesystem or registry modification.
The docstring says _load_skill will "Load a skill module," and load_components is documented as loading component skills. In reality, _load_skill just returns {"path": path, "loaded": True} without importing or validating a module, which actively contradicts the documented behavior of real component loading.
The generated execute docstring states it will execute the flow, and _execute_step says it will execute a single step. However, the code merely iterates over textual steps and returns canned completed statuses, never invoking loaded components or performing the described workflow actions, which contradicts the intent expressed in the inline documentation.
The README describes scanning and processing user requests and skills but omits privacy and system-impact warnings about handling potentially sensitive content and analyzing untrusted skill files. Users may incorrectly assume that scanning is harmless, when it may involve reading local files, storing metadata, or processing proprietary code and prompts.
The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens reproducibility and can unintentionally introduce vulnerable or breaking releases through the supply chain.
# Flow - Intelligent Skill Orchestrator Dependencies
# Core dependencies
streamlit>=1.28.0
pandas>=2.0.0
# Natural Language Processing
The manifest does not pin streamlit, and the package has multiple known advisories. Without an exact version, it is impossible to verify whether deployments are using a safe release; in this context, Streamlit is often network-facing, so unresolved advisories can materially increase exposure.
Using pandas with only a minimum version means the installed package may vary by environment and time. That creates supply-chain uncertainty and may expose deployments to newly introduced vulnerable releases or incompatible behavior.
# Core dependencies
streamlit>=1.28.0
pandas>=2.0.0
# Natural Language Processing
nltk>=3.8.0
Pandas has known advisory history, and the missing pin prevents verification of whether an affected version is installed. While the practical exploitability depends on how pandas features are used, the unresolved version ambiguity is still a real supply-chain security concern.
An unpinned nltk dependency allows dependency resolution to drift to later versions without review. In a skill that performs NLP processing, this increases the risk of pulling a release with security flaws affecting parsing, corpus handling, or network-related functionality.
pandas>=2.0.0
# Natural Language Processing
nltk>=3.8.0
spacy>=3.6.0
# Security scanning
NLTK has multiple known advisories, and the current constraint does not establish whether a safe version will be installed. In an orchestrator skill that processes natural language and may interact with external resources or corpora, unverifiable NLP package versions are more concerning than a generic library drift issue.
Specifying spacy as >=3.6.0 permits uncontrolled upgrades during installation. This is a supply-chain hygiene issue because it prevents deterministic builds and may introduce vulnerable versions without explicit approval.
# Natural Language Processing
nltk>=3.8.0
spacy>=3.6.0
# Security scanning
bandit>=1.7.5
Leaving bandit unpinned makes builds non-reproducible and may introduce compromised or vulnerable tool versions. Although this is a security-scanning tool rather than runtime application code, toolchain integrity still matters because a bad version could miss findings or behave insecurely in CI.
spacy>=3.6.0
# Security scanning
bandit>=1.7.5
safety>=2.3.0
# Code analysis
Using safety with only a minimum version allows uncontrolled dependency resolution. Because this package is itself used for vulnerability assessment, an unexpected version can affect both trustworthiness and reproducibility of security checks.
# Security scanning
bandit>=1.7.5
safety>=2.3.0
# Code analysis
ast-grep>=0.12.0
Safety has known advisories and is not pinned, so the environment may resolve to an affected version without visibility. Because this is a security tool, vulnerable or unreliable versions can undermine confidence in dependency-audit results even if they are not directly exposed at runtime.
The ast-grep dependency is not pinned, so installations may pull different versions over time. This is a supply-chain and reproducibility weakness that can change analysis behavior or introduce vulnerable releases.
safety>=2.3.0
# Code analysis
ast-grep>=0.12.0
pylint>=2.17.0
An unpinned pylint dependency allows future installs to resolve unpredictably. That creates a low-severity supply-chain risk and can affect the reliability of static analysis in CI or local development.
# Code analysis
ast-grep>=0.12.0
pylint>=2.17.0
Detected: suspicious.dynamic_code_execution