Back to skill

Security audit

Issues and Branches

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed Jira and Bitbucket workflow helper that previews by default and only performs the expected Jira updates or branch pushes when applied.

Install only if you want an agent to create Jira issues, update assignee/status/sprint fields, and create Bitbucket branches on your behalf. Use low-privilege Jira and Bitbucket API tokens, keep WORKFLOW_CONFIG private, review previews before applying writes, and avoid broad repository or project permissions unless needed.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

A second description-behavior mismatch reinforces that the skill's declared combined Jira/Bitbucket functionality may not exist in practice and that reuse semantics may be absent. In security terms, misleading operational claims can cause unsafe automation decisions, especially where users expect no-write reads, idempotent reuse, or controlled branch creation across repositories.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

A second description-behavior mismatch reinforces that the skill's declared combined Jira/Bitbucket functionality may not exist in practice and that reuse semantics may be absent. In security terms, misleading operational claims can cause unsafe automation decisions, especially where users expect no-write reads, idempotent reuse, or controlled branch creation across repositories.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill invokes local Python helpers and describes operations that require shell, file access, environment/config access, and network access, but it declares no explicit tool scope or permissions boundary. This creates an authorization ambiguity where an agent may run broader-capability actions than reviewers or policy expect, increasing the chance of unintended writes to Jira/Bitbucket or misuse of local credentials.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/setup.md (reported line 3)May include surrounding context.

md
# Private configuration and usage

Set `WORKFLOW_CONFIG` to a private JSON file outside the public repository. Required issue settings: `jira_url`, `jira_project`, `jira_board_id`, `jira_sprint_field`. Branch work also requires `bitbucket_workspace` and `local_root`, where each clone is stored as `<local_root>/<repository-slug>`. Obtain the sprint field ID and board ID from your own Jira configuration; do not copy illustrative IDs without verification.

Credentials come only from `JIRA_EMAIL`, `JIRA_API_TOKEN`, `BITBUCKET_USERNAME` and `BITBUCKET_API_TOKEN`. Configure these through your usual credential manager. Do not print them or store them in request files. Use the provider's supported API-token authentication and the minimum permissions needed for the requested work.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/create_branch.py (reported line 32)May include surrounding context.

python
workspace = str(workflow_config.required(config, "bitbucket_workspace"))
        if not re.fullmatch(r"[A-Za-z0-9_-]+", workspace):
            raise ValueError("Invalid Bitbucket workspace")
        BB = "https://api.bitbucket.org/2.0/repositories/" + workspace
        LOCAL_ROOT = Path(workflow_config.required(config, "local_root")).expanduser().resolve()

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/create_branch.py (reported line 95)May include surrounding context.

python
workspace = str(workflow_config.required(config, "bitbucket_workspace"))
        if not re.fullmatch(r"[A-Za-z0-9_-]+", workspace):
            raise ValueError("Invalid Bitbucket workspace")
        BB = "https://api.bitbucket.org/2.0/repositories/" + workspace
        LOCAL_ROOT = Path(workflow_config.required(config, "local_root")).expanduser().resolve()

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/test_create_branch.py (reported line 54)May include surrounding context.

python
workspace = str(workflow_config.required(config, "bitbucket_workspace"))
        if not re.fullmatch(r"[A-Za-z0-9_-]+", workspace):
            raise ValueError("Invalid Bitbucket workspace")
        BB = "https://api.bitbucket.org/2.0/repositories/" + workspace
        LOCAL_ROOT = Path(workflow_config.required(config, "local_root")).expanduser().resolve()

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/test_public_config.py (reported line 35)May include surrounding context.

python
workspace = str(workflow_config.required(config, "bitbucket_workspace"))
        if not re.fullmatch(r"[A-Za-z0-9_-]+", workspace):
            raise ValueError("Invalid Bitbucket workspace")
        BB = "https://api.bitbucket.org/2.0/repositories/" + workspace
        LOCAL_ROOT = Path(workflow_config.required(config, "local_root")).expanduser().resolve()

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/create_branch.py (reported line 94)May include surrounding context.

python
if not repo_dir.is_relative_to(LOCAL_ROOT):
        sys.exit("ERROR repository path is outside local_root")
    from urllib.parse import urlparse
    remote = subprocess.run(["git", "remote", "get-url", "origin"], cwd=repo_dir, capture_output=True, text=True, check=True).stdout.strip()
    expected = BB.removeprefix("https://api.bitbucket.org/2.0/repositories/") + "/" + r["repo"]
    parsed = urlparse(remote if not remote.startswith("git@bitbucket.org:") else remote.replace("git@bitbucket.org:", "ssh://git@bitbucket.org/", 1))
    if parsed.hostname != "bitbucket.org" or parsed.path.strip("/").removesuffix(".git") != expected:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/create_branch.py (reported line 103)May include surrounding context.

python
sys.exit(f"ERROR no local clone at {repo_dir}; a git push is needed for Jira to index the branch")
    for cmd in (["git", "fetch", "origin", r["base_hash"]],
                ["git", "push", "origin", f"{r['base_hash']}:refs/heads/{r['name']}"]):
        if subprocess.run(cmd, cwd=repo_dir).returncode:
            sys.exit(f"ERROR {' '.join(cmd)} failed in {repo_dir}")

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/create_branch.py (reported line 163)May include surrounding context.

python
if bool(a.issue) == bool(a.input):
        p.error("Provide either an existing issue key or --input for a new issue.")
    for option in ("assignee_account_id", "status"):
        value = getattr(a, option)
        if value is not None:
            if not value.strip():
                p.error(f"{option} must not be empty.")

Static analysis

No suspicious patterns detected.