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
- 15
- Medium
- 9
- 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
- 24
- 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
24 findings likely need attention, 30 look like noise. Most notable: Found 'importlib.resources', which is a module only available on Python 3.7+. This does... in /src/seclab_taskflow_agent/available_tools.py (99% confidence).
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: GHSA-7xgj-8392-5q4r in fastmcp==3.2.0 — ## Maintainer assessment and remediation This report is accepted as a FastMCP authorization vulnera
fastmcp==3.2.0 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 99% confidence
CVE found: CVE-2026-96760 in authlib==1.6.12 — Authlib (prior to 1.9.0) contains a signature verification bypass vulnerability. The JsonWebSignatur
authlib==1.6.12 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 98% confidence
CVE found: CVE-2026-114605 in dnspython==2.8.0 — ### Impact A maliciously crafted DNS message may cause dns.name.from_wire_parser() to use excessive
dnspython==2.8.0 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 98% confidence
CVE found: CVE-2026-114615 in authlib==1.6.12 — ## Summary `OctKey.import_key()` carries the only guard that stops an asymmetric public key from be
authlib==1.6.12 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 98% confidence
CVE found: CVE-2026-114616 in authlib==1.6.12 — Reporter: Cavan Loughran, Celvex Group Inc. Summary Authlib's symmetric (oct) key handling accepts
authlib==1.6.12 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 97% confidence
CVE found: CVE-2026-114618 in authlib==1.6.12 — ## Description ### Summary Authlib's default RFC 7523 JWT bearer grant leaves `get_audiences()` em
authlib==1.6.12 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 95% confidence
CVE found: CVE-2026-114614 in authlib==1.6.12 — ### Summary `authlib.common.security.is_secure_transport()` is used throughout Authlib to enforce th
authlib==1.6.12 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 95% confidence
CVE found: PYSEC-2026-4320 in certifi==2025.6.15 — Certifi versions before 2026.10.18 include the `emSign ECC Root CA - G3` root certificate in their b
certifi==2025.6.15 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 94% confidence
CVE found: CVE-2026-114620 in authlib==1.6.12 — ### Summary Authlib's RFC 9101 (JAR) extension passes the attacker-controlled `request_uri` authori
authlib==1.6.12 -
- Engine
- Dependency checker · CVEs, typosquats and risky installs
- Counts towards
- Supply chain
- File
- pyproject.toml
- Likely real
- Yes, 94% confidence
CVE found: CVE-2026-114617 in authlib==1.6.12 — ### Summary `OpenIDMixin.parse_id_token()` reads the `nonce_supported` claim from the ID token it i
authlib==1.6.12 -
- 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/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
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/publish-to-pypi.yaml line 71
- 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: pypa/gh-action-pypi-publish@v1.14.2 # immutable release -
- Engine
- Semgrep · Pattern-based code analysis
- Counts towards
- Vulnerability
- File
- /.github/workflows/publish-to-testpypi.yaml line 84
- 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: pypa/gh-action-pypi-publish@v1.14.2 # 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/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
- 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 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
- 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
- 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 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 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
- /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
- /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
- /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
- 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/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
- /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
- /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_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
- 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.