Scan report
GitHubSecurityLab / seclab-taskflow-agent
Could an attacker exploit mistakes in this code?
Serious issues. Review the high-severity findings before using it.
- High
- 9
- Medium
- 7
- Low
- 25
Sources: Bandit, Semgrep, pip-audit
Does this code look like it is trying to cause harm?
Minor issues. Worth a glance, unlikely to be urgent.
- High
- 0
- Medium
- 0
- Low
- 5
Sources: YARA, ClamAV, GuardDog, dependency checker
- Likely real
- 16
- Uncertain
- 0
- Likely noise
- 30
The risk classifier rates every finding for how likely it is to be a real issue. Likely noise still counts, just much less.
What we found, in plain English
This repository has a high vulnerability score of 86, which means there are many obvious coding mistakes that could let attackers exploit the code in ways they don't expect. While the malicious-pattern score is very low at 2, this indicates the code itself does not appear to be intentionally harmful, but rather just outdated or poorly written. The most serious issues involve using Python features and libraries that only work on newer versions of the language, which will break if older systems try to run this project. Additionally, several dependencies have known security flaws that could allow attackers to steal secrets or inject malicious commands into the system. The scan also found a specific risk where a GitHub Actions workflow might accidentally execute code with your own credentials if not configured correctly, and there is a chance that hardcoded secrets are being logged in the application logs.
Written by a local language model from the findings below. The risk scores come from the classifier, not from this summary.
Detections by engine
Score over time
Overall score each time this repository was scanned.
Findings
Highest severity first. Select a finding to see the code and what it means.
-
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/available_tools.py line 14
- Likely real
- Yes, 99% confidence
Found 'importlib.resources', which is a module only available on Python 3.7+. This does not work in lower versions, and therefore is not backwards compatible. Use importlib_resources instead for older Python versions.
import importlib.resources -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/shell_utils.py line 22
- Likely real
- Yes, 99% confidence
the `encoding` argument to Popen is only available on Python 3.6+
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 99% confidence
CVE found: PYSEC-2026-4175 in urllib3==2.7.0 — ## Impact urllib3 supports configuring TLS independently for an HTTPS proxy and the target server.
urllib3==2.7.0 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 99% confidence
CVE found: PYSEC-2026-2132 in click==8.2.1 — Pallets Click, versions 8.3.2 and below, contain a command injection vulnerability in the click.edit
click==8.2.1 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 99% confidence
CVE found: PYSEC-2026-4176 in urllib3==2.7.0 — ### Impact urllib3's streaming API is designed for the efficient handling of large HTTP responses b
urllib3==2.7.0 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 97% confidence
CVE found: PYSEC-2026-4177 in urllib3==2.7.0 — ## Impact urllib3's [streaming API](https://urllib3.readthedocs.io/en/2.7.0/advanced-usage.html#str
urllib3==2.7.0 -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/release.yml line 52
- Likely real
- Yes, 57% confidence
Using variable interpolation `${{...}}` with `github` context data in a `run:` step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. `github` context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with `env:` to store the data and use the environment variable in the `run:` script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
run: | gh attestation verify oci://ghcr.io/${{ env.USER }}/${{ env.IMAGE_NAME }}:${{ github.event.inputs.release_tag }} -R ${{ github.repository }} -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/release.yml line 36
- Likely real
- Yes, 57% confidence
Using variable interpolation `${{...}}` with `github` context data in a `run:` step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. `github` context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with `env:` to store the data and use the environment variable in the `run:` script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
run: | echo ${{ secrets.GHCR_TOKEN }} | docker login ghcr.io -u GitHubSecurityLab --password-stdin python release_tools/publish_docker.py ${{ env.REGISTRY }}/${{ env.USER }}/${{ env.IMAGE_NAME }} ${{ github.event.inputs.release_tag }} DIGEST=$(cat /tmp/digest.txt) echo "digest=$DIGEST" >> $GITHUB_OUTPUT -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /docker/Dockerfile line 48
- Likely real
- Probably noise, 22% confidence
By not specifying a USER, a program in the container may run as 'root'. This is a security hazard. If an attacker can control a process running as root, they may have control over the container. Ensure that the last USER in a Dockerfile is a USER other than 'root'.
ENTRYPOINT ["python", "-m", "seclab_taskflow_agent"] -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/_stream.py line 134
- Likely real
- Yes, 99% confidence
Detected a python logger call with a potential hardcoded secret "token usage model=%s input=%d output=%d " "cache_write=%d cache_read=%d" being logged. This may lead to secret credentials being exposed. Make sure that the logger is not logging sensitive information.
logging.info( "token usage model=%s input=%d output=%d " "cache_write=%d cache_read=%d", event.model, event.input_tokens, event.output_tokens, event.cache_write_tokens, event.cache_read_tokens, ) -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/codeql.yml line 35
- Likely real
- Yes, 52% confidence
GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. `uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608`.
uses: github/codeql-action/init@v4.36.0 # immutable release -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/codeql.yml line 42
- Likely real
- Yes, 52% confidence
GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. `uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608`.
uses: github/codeql-action/analyze@v4.36.0 # immutable release -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/publish-to-pypi.yaml line 66
- Likely real
- Yes, 52% confidence
GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. `uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608`.
uses: actions/attest@v4.1.0 # immutable release -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/publish-to-testpypi.yaml line 79
- Likely real
- Yes, 52% confidence
GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. `uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608`.
uses: actions/attest@v4.1.0 # immutable release -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/release.yml line 43
- Likely real
- Yes, 52% confidence
GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. `uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608`.
uses: actions/attest@v4.1.0 # immutable release -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/publish_docker.py line 31
- Likely real
- Probably noise, 25% confidence
Probable insecure usage of temp file/directory.
30 print(f"Image digest: {digest}") 31 with open("/tmp/digest.txt", "w") as f: 32 f.write(digest) -
- Engine
- GuardDog · Supply-chain attack heuristics
- Counts towards
- Malicious pattern
- File
- /src/seclab_taskflow_agent/capi.py line 176
- Likely real
- Yes, 93% confidence
Detects reading of environment variables (credential access, often contains secrets) [threat-runtime-environment-read]
return token token = os.getenv("COPILOT_TOKEN") if token: return token -
- Engine
- GuardDog · Supply-chain attack heuristics
- Counts towards
- Malicious pattern
- File
- /src/seclab_taskflow_agent/capi.py line 173
- Likely real
- Yes, 93% confidence
Detects reading of environment variables (credential access, often contains secrets) [threat-runtime-environment-read]
"""Get the AI API token from AI_API_TOKEN or COPILOT_TOKEN env vars.""" token: str | None = os.getenv("AI_API_TOKEN") if token: return token -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/shell_utils.py line 7
- Likely real
- Probably noise, 13% confidence
Consider possible security implications associated with the subprocess module.
6 import logging 7 import subprocess 8 import tempfile -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 6
- Likely real
- Probably noise, 13% confidence
Consider possible security implications associated with the subprocess module.
5 import shutil 6 import subprocess 7 import sys -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/publish_docker.py line 4
- Likely real
- Probably noise, 13% confidence
Consider possible security implications associated with the subprocess module.
3 4 import subprocess 5 import sys -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/mcp_servers/codeql/client.py line 9
- Likely real
- Probably noise, 13% confidence
Consider possible security implications associated with the subprocess module.
8 import re 9 import subprocess 10 import tempfile -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/mcp_transport.py line 29
- Likely real
- Probably noise, 13% confidence
Consider possible security implications associated with the subprocess module.
28 import socket 29 import subprocess 30 import time -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 43
- Likely real
- Probably noise, 12% confidence
Starting a process with a partial executable path
42 try: 43 subprocess.run(["git", "init", "-b", "main"], cwd=dest_dir, check=True) 44 print(f"Initialized new git repository in {dest_dir} with 'main' as the default branch") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 51
- Likely real
- Probably noise, 12% confidence
Starting a process with a partial executable path
50 try: 51 branches = subprocess.check_output(["git", "branch"], cwd=dest_dir, text=True) 52 if "main" not in branches: -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 53
- Likely real
- Probably noise, 12% confidence
Starting a process with a partial executable path
52 if "main" not in branches: 53 subprocess.run(["git", "checkout", "-b", "main"], cwd=dest_dir, check=True) 54 print("Created and switched to 'main' branch.") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 56
- Likely real
- Probably noise, 12% confidence
Starting a process with a partial executable path
55 else: 56 subprocess.run(["git", "checkout", "main"], cwd=dest_dir, check=True) 57 print("Switched to 'main' branch.") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 72
- Likely real
- Probably noise, 12% confidence
Starting a process with a partial executable path
71 try: 72 subprocess.run(["git", "add", "-f", rel_path], check=True) 73 print(f"git add {rel_path}") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/publish_docker.py line 9
- Likely real
- Probably noise, 12% confidence
Starting a process with a partial executable path
8 def get_image_digest(image_name, tag): 9 result = subprocess.run( 10 ["docker", "buildx", "imagetools", "inspect", f"{image_name}:{tag}"], 11 stdout=subprocess.PIPE, 12 check=True, 13 text=True, 14 ) 15 for line in result.stdout.splitlines(): -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/publish_docker.py line 23
- Likely real
- Probably noise, 12% confidence
Starting a process with a partial executable path
22 # Build 23 subprocess.run( 24 ["docker", "buildx", "build", "--platform", "linux/amd64", "-t", f"{image_name}:{tag}", dest_dir], check=True 25 ) 26 # Push -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/publish_docker.py line 27
- Likely real
- Probably noise, 12% confidence
Starting a process with a partial executable path
26 # Push 27 subprocess.run(["docker", "push", f"{image_name}:{tag}"], check=True) 28 print(f"Pushed {image_name}:{tag}") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/publish_docker.py line 23
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
22 # Build 23 subprocess.run( 24 ["docker", "buildx", "build", "--platform", "linux/amd64", "-t", f"{image_name}:{tag}", dest_dir], check=True 25 ) 26 # Push -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 43
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
42 try: 43 subprocess.run(["git", "init", "-b", "main"], cwd=dest_dir, check=True) 44 print(f"Initialized new git repository in {dest_dir} with 'main' as the default branch") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 51
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
50 try: 51 branches = subprocess.check_output(["git", "branch"], cwd=dest_dir, text=True) 52 if "main" not in branches: -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 53
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
52 if "main" not in branches: 53 subprocess.run(["git", "checkout", "-b", "main"], cwd=dest_dir, check=True) 54 print("Created and switched to 'main' branch.") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 56
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
55 else: 56 subprocess.run(["git", "checkout", "main"], cwd=dest_dir, check=True) 57 print("Switched to 'main' branch.") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/copy_files.py line 72
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
71 try: 72 subprocess.run(["git", "add", "-f", rel_path], check=True) 73 print(f"git add {rel_path}") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/shell_utils.py line 22
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
21 logging.info("Executing: %s", cmd) 22 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") 23 stdout, stderr = p.communicate() -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/mcp_transport.py line 156
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
155 try: 156 self.process = subprocess.Popen( 157 self.cmd, 158 stdout=subprocess.PIPE, 159 stderr=subprocess.PIPE, 160 text=True, 161 bufsize=1, 162 universal_newlines=True, 163 env=self.env, 164 ) 165 -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/mcp_servers/codeql/client.py line 79
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
78 self.stderr_log = open(self.stderr_log, "a") 79 p = subprocess.Popen( 80 self.codeql_cli + server_cmd, 81 text=True, 82 bufsize=1, 83 universal_newlines=True, 84 stdin=subprocess.PIPE, 85 stdout=subprocess.PIPE, 86 stderr=self.stderr_log, 87 ) 88 -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /src/seclab_taskflow_agent/mcp_servers/codeql/client.py line 34
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
33 print(f"Executing: {cmd}") 34 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") 35 stdout, stderr = p.communicate() -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/publish_docker.py line 27
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
26 # Push 27 subprocess.run(["docker", "push", f"{image_name}:{tag}"], check=True) 28 print(f"Pushed {image_name}:{tag}") -
- Engine
- Bandit · Python security linter
- Counts towards
- Vulnerability
- File
- /release_tools/publish_docker.py line 9
- Likely real
- Probably noise, 3% confidence
subprocess call - check for execution of untrusted input.
8 def get_image_digest(image_name, tag): 9 result = subprocess.run( 10 ["docker", "buildx", "imagetools", "inspect", f"{image_name}:{tag}"], 11 stdout=subprocess.PIPE, 12 check=True, 13 text=True, 14 ) 15 for line in result.stdout.splitlines(): -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Probably noise, 2% confidence
Loose version constraint: 'Jinja2>=3.1.0' — attacker could push malicious update
Jinja2>=3.1.0 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Probably noise, 2% confidence
Loose version constraint: 'github-copilot-sdk>=0.2.2,<0.3' — attacker could push malicious update
github-copilot-sdk>=0.2.2,<0.3 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Probably noise, 2% confidence
Loose version constraint: 'anthropic>=0.50,<1' — attacker could push malicious update
anthropic>=0.50,<1
No findings match these filters.