Back to skill

Security audit

Oura Ring Data

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its Oura Ring data purpose, but it needs review because it handles sensitive health/profile data broadly and its HTML reports have privacy and script-execution risks.

Review before installing if you plan to let an agent access your Oura account. Treat the Oura token and all outputs as sensitive health data, avoid broad all-data requests unless you asked for them, and avoid opening or sharing generated HTML reports until the HTML escaping and CDN concerns are fixed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
src/ouracli/format_html.py:122
Finding

Unescaped Oura Data Permits Script Injection in Generated HTML Reports

Content
View full analysis
{sub_human_key}{subvalue}" ) ``` ```python # Render simple KVs as table if simple_kvs: html.append("") for k, v in simple_kvs: html.append(f"{k}{v}") html.append("") ``` ```python html_parts.append(f'{title or "Oura Data"}') ``` ```python if isinstance(item, dict) and "day" in item: html_parts.append(f'

{item["day"]}

') ``` ```python if isinstance(item, dict) and "day" in item: html_parts.append(f'

{item["day"]}

') html_parts.append(format_html_item(item, level=3)) ``` ### Technical Analysis The HTML formatter inserts API-derived values directly into HTML elements without context-appropriate escaping. This includes simple values, nested dictionary values, report titles, and day headings. Oura records can include textual metadata such as user-created tags. If a field contains HTML markup or an event-handler attribute, the formatter emits it as active markup rather than text. For example: ```html ``` When the report is opened, the browser parses the injected element and executes its event handler. The formatter does not use `html.escape`, an automatically escaping template engine, a sanitizer, or a Content Security Policy that would prevent inline script execution. ### Attack Path 1. Malicious HTML is introduced into a textual Oura record, such as a user-added tag or other API-returned metadata. 2. The vict ...[truncated 1275 chars]
Remediation
View remediation
str: return escape(str(value), quote=True) ``` Apply this function to table keys, table values, titles, headings, interval values, and all other API-derived strings. 2. Prefer a template engine with automatic escaping enabled rather than assembling HTML through f-strings. 3. Treat HTML text and HTML attribute contexts separately. Attribute values must be quoted and escaped with quote escaping enabled. 4. Add a restrictive Content Security Policy, such as one that blocks inline scripts and unauthorized outbound connections. If inline chart initialization remains necessary, move it into a bundled script or authorize it with a nonce or hash. 5. Add regression tests covering at least: ```html "> & < > " ' ``` 6. Verify that generated output contains escaped text such as `<script>` rather than executable elements. ]]>

T08 · Insecure Dependencies

Note
Location
src/ouracli/format_html.py:153
Finding

Generated HTML Reports Execute External CDN JavaScript Without Integrity Verification

Content
View full analysis
' ) ``` ### Technical Analysis Every generated HTML report references an executable Chart.js asset hosted by jsDelivr. Although the package version is fixed to `4.4.1`, the script element does not include a Subresource Integrity hash. The report therefore trusts the CDN, its DNS and TLS delivery path, and the corresponding package artifact each time it is opened. Third-party JavaScript included through a `script` element executes with the same browser privileges as the report itself. If the CDN response or package-delivery path is compromised, modified JavaScript can read all health information rendered in the document and send it to a remote server. Opening a report also makes an external request to jsDelivr, disclosing connection metadata such as the user's IP address and request headers. Charts are unavailable when the report is opened without network connectivity. ### Attack Path 1. A user generates an HTML health report: ```bash ouracli all "30 days" --html > report.html ``` 2. The user opens the report in a browser. 3. The browser requests `chart.umd.min.js` from jsDelivr. 4. If the CDN response, upstream package artifact, or delivery path has been compromised, the browser receives attacker-controlled JavaScript. 5. The browser executes that JavaScript in the report context. 6. The malicious script reads the report DOM and exfiltrates or alters the displayed health information. ### Impact Assessment A compromised external script can: - Read all sensitive Oura information included in the report. - Exfiltrate report contents through outbound browser requests. - Modify scores, profile details, or charts displayed to the ...[truncated 234 chars]
Remediation
View remediation
``` 3. Independently verify the integrity hash against a trusted release artifact before publishing it. 4. Add a restrictive Content Security Policy that only permits the required script source and limits outbound connections. 5. Document that generated HTML currently contacts a third party when opened and provide an offline-output option. 6. Keep the dependency version pinned and review updates before changing the bundled or CDN-hosted version. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
src/ouracli/client.py:82
Finding

Oura API Requests Lack Connection and Read Timeouts

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (57)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

This code chunk does not implement the declared skill purpose of accessing Oura Ring health data through the ouracli CLI. Instead, it contains unit tests for two visualization helper functions that render Mermaid charts from already-provided activity and heart-rate inputs. While the tested functions are health-data-related and plausibly part of a broader Oura tool, the actual code shown neither fetches Oura data nor interfaces with the CLI. That makes the primary purpose materially different from the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared purpose is an Oura Ring data access skill using the ouracli CLI. However, the provided code only contains unit tests for formatter behavior. It does not access Oura APIs, invoke a CLI, read health data, or implement domain-specific logic for Oura metrics. While formatter utilities could be a supporting component within a larger Oura tool, this specific code chunk’s actual behavior is materially different from the declared primary purpose, so this chunk is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

This code chunk is not implementing data access functionality; it is a suite of unit/integration tests for formatting and visualization helpers. While the tested data structures are Oura-like health/activity records, the actual behavior shown is limited to validating string/HTML/Markdown/chart formatting and reorganizing data by day. That is materially different from the declared purpose of accessing Oura Ring health data via CLI.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · Taskfile.yml (reported line 64)May include surrounding context.

yaml
clean:
    desc: Clean artifacts
    cmds:
      - rm -rf build/ dist/ *.egg-info htmlcov/ .coverage .pytest_cache/ .mypy_cache/ .ruff_cache/
      - find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true

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
70% confidence
Finding

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

Content

Scanner excerpt · src/ouracli/llm_help.py (reported line 17)May include surrounding context.

python
"usageContext": (
            "Use when the user needs to retrieve health metrics (sleep, activity, readiness, "
            "heart rate, SpO2, stress, workouts, etc.) from their Oura Ring. "
            "Requires an Oura Personal Access Token."
        ),
        "webUI": "https://cloud.ouraring.com",
        "apiDocs": "https://cloud.ouraring.com/v2/docs",

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · README.md (reported line 22)May include surrounding context.

md
{
  "message": "No access token header found"
}

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · src/ouracli/client.py (reported line 22)May include surrounding context.

python
{
  "message": "No access token header found"
}

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · src/ouracli/client.py (reported line 33)May include surrounding context.

python
{
  "message": "No access token header found"
}

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · tests/fixtures/heartrate_2024-11-01_to_2024-11-03.json (reported line 2)May include surrounding context.

json
{
  "message": "No access token header found"
}

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · tests/fixtures/sleep_2024-11-01_to_2024-11-14.json (reported line 2)May include surrounding context.

json
{
  "message": "No access token header found"
}

Lp1

High
Category
MCP Least Privilege
Confidence
55% confidence
Finding

The skill uses 'file_write' 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.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README instructs users to create a local environment file containing an Oura personal access token, but it provides no guidance on secure handling such as excluding the file from version control, limiting file permissions, or using a secret manager. In an AI-agent skill context that accesses sensitive health data, poor credential hygiene increases the risk of token leakage and unauthorized access to personal data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill handles highly sensitive health data and explicitly directs use of a personal access token, but it does not warn users that their sleep, heart rate, stress, and profile data may be transmitted to external services or surfaced in tool output. This can lead to uninformed disclosure of protected personal health information, especially if outputs are logged, shared, or retained by downstream systems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

These commands fetch and print sensitive health data without any explicit privacy warning, consent checkpoint, or minimization guidance. In a CLI used by agents, silent retrieval and display of health metrics can lead to accidental disclosure in logs, chat transcripts, terminals, or shared environments.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The skill manifest frames the tool as providing Oura health metrics, but this command also retrieves personal profile data, which expands access beyond the declared scope. In an agent setting, this can cause over-collection or unintended disclosure of sensitive user information because downstream systems may invoke the tool based on the narrower description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The personal_info command outputs profile data directly with no explicit warning that the result may contain sensitive personal information. This is particularly risky in agent workflows because profile data may be surfaced, logged, or forwarded without the user understanding that non-metric personal details are being accessed.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The all command retrieves all available Oura data, exceeding the manifest's metric-specific description and weakening least-privilege boundaries. In an agent context, a broad catch-all command increases the chance of collecting and exposing more sensitive data than the user requested or expected.

Content

No source excerpt is available for this finding.

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 · src/ouracli/client.py (reported line 15)May include surrounding context.

python
class OuraClient:
    """Client for interacting with the Oura API v2."""

    BASE_URL = "https://api.ouraring.com/v2"

    def __init__(self, access_token: str | None = None) -> None:
        """

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code reads a personal access token from an environment variable and local/home secrets files, which is sensitive credential handling. Although the loading behavior is documented for developers, there is no user-facing disclosure or warning in this file that the skill will access stored credentials from these locations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The client performs authenticated HTTP requests to retrieve sensitive wellness and personal information, including heart rate, sleep, stress, and personal_info data. While the docstrings describe API behavior, there is no user-facing warning, confirmation, or visible disclosure that this data will be sent over the network and fetched from a third-party service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description suggests access to health metrics like sleep, activity, heart rate, readiness, and stress, but get_all_data also collects personal_info, tags, sessions, workouts, and rest mode data. This broadens data collection beyond the user-facing scope and increases privacy risk because more sensitive behavioral and profile information may be retrieved than users expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code file embeds user-facing help text for a CLI that retrieves sensitive health and wellness data and requires a personal access token, but the documentation only describes capabilities and setup. It does not include any explicit warning that commands may expose private health information in terminal output, JSON/HTML exports, or files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The authentication instructions tell users to store a bearer token in an environment variable or secrets file, but they do not warn that the token grants access to sensitive health data and must be protected from logs, shell history, screenshots, and overly permissive file permissions. In an LLM-agent context, this can normalize unsafe secret handling and increase the chance of credential exposure or misuse.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.