Back to skill

Security audit

jira-reader

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent read-only Jira helper, though users should configure its Jira URL and token carefully.

Install only if you intend to let the agent read Jira data available to the supplied API token. Use a narrowly scoped read-only Atlassian token, set JIRA_BASE_URL to your real Jira Cloud tenant, prefer setting JIRA_CLOUD_ID to avoid discovery, and do not use an untrusted .env or JIRA_ENV_FILE.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/jira-reader.mjs:101
Finding

Unrestricted Jira Base URL Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: scripts/jira-reader.mjs, lines 101–107
Vulnerability Type: Server-Side Request Forgery (SSRF) through an unrestricted configuration URL
Risk Level: Medium

Vulnerable code:

js
async function discoverCloudId() {
  const response = await fetch(`${config.baseUrl}/_edge/tenant_info`, { headers: { Accept: 'application/json' } });
  if (!response.ok) throw new Error(`Could not discover Jira Cloud ID from JIRA_BASE_URL: HTTP ${response.status}`);
  const data = await response.json();
  if (!data.cloudId) throw new Error('Could not discover Jira Cloud ID from JIRA_BASE_URL');
  config.cloudId = data.cloudId;
  return config.cloudId;
}

config.baseUrl originates from JIRA_BASE_URL, including values loaded from the configured environment file. Before use, it is only normalized by removing trailing slashes:

js
config.baseUrl = config.baseUrl.replace(/\/+$/, '');

Technical Analysis

discoverCloudId() performs a server-side fetch() against a URL derived directly from configuration controlled through JIRA_BASE_URL. The implementation does not:

  • Require the https: protocol.
  • Restrict the hostname to the intended Jira Cloud tenant or an approved *.atlassian.net domain.
  • Reject URL-embedded credentials or unexpected ports.
  • Block loopback, private, link-local, or other internal network destinations.
  • Disable redirects or validate every redirect destination.

Therefore, a party able to influence the process environment or the loaded .env file can cause the Skill to make an HTTP request from the Agent's network context to an unintended destination.

The authenticated Jira request itself is sent to the fixed HTTPS origin https://api.atlassian.com, so this flaw does not directly send the Jira Basic authorization header to the attacker-controlled discovery endpoint. Nevertheless, unrestricted network discovery exceeds the minimu ...[truncated 1602 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse JIRA_BASE_URL with new URL() and reject malformed values.
  2. Require the https: protocol.
  3. Reject embedded usernames and passwords, URL fragments, unexpected paths, and non-default ports.
  4. Prefer an exact allowlist containing the organization's expected Jira Cloud hostname. If wildcard support is essential, validate hostname boundaries carefully and permit only legitimate *.atlassian.net tenant hosts.
  5. Disable automatic redirects where supported, or validate every redirect destination against the same protocol and hostname policy before following it.
  6. Resolve the hostname and reject loopback, private, link-local, multicast, and reserved IP ranges for both IPv4 and IPv6. Repeat validation after DNS resolution and for redirect targets to reduce DNS rebinding risk.
  7. Prefer requiring JIRA_CLOUD_ID in controlled deployments so the discovery request is unnecessary.
  8. Add automated tests covering HTTP URLs, localhost, private IP addresses, IPv6 loopback, embedded credentials, unexpected ports, deceptive hostname suffixes, and redirects to prohibited destinations.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (15)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 29)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 30)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 31)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 32)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 33)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 34)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 35)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 36)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 46)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 47)May include surrounding context.

md
node scripts/jira-reader.mjs me

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 48)May include surrounding context.

md
node scripts/jira-reader.mjs me

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'network' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/jira-reader.mjs (reported line 5)May include surrounding context.

js
import { readFileSync } from 'node:fs';
const VERSION = '0.4.0';
loadEnvFile(process.env.JIRA_ENV_FILE || '.env');

class JiraRequestError extends Error { constructor(status, message) { super(message); this.status = status; } }

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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/jira-reader.mjs (reported line 87)May include surrounding context.

js
async function jiraUrl(path) {
  const cloudId = config.cloudId || await discoverCloudId();
  return `https://api.atlassian.com/ex/jira/${encodeURIComponent(cloudId)}${path}`;
}

async function discoverCloudId() {

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/jira-reader.mjs:5