Back to skill

Security audit

Axiom Markdown Link Auditor

Security checks for vulnerabilities and agentic risk

Overview

The skill is not clearly harmful, but it materially overstates its capabilities and its optional remote link checks are not safely scoped or clearly warned.

Install only if you need a simple single-file Markdown link extractor with optional external status checks. Do not rely on it for internal link validation, orphan-page reporting, or directory audits unless the implementation is fixed, and avoid running remote checks on untrusted documents or networks with sensitive internal services.

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
axiom_markdown_link_auditor.py:83
Finding

Server-Side Request Forgery Through Unrestricted Markdown URLs

Content
View full analysis

Vulnerability Details

File Location: axiom_markdown_link_auditor.py:83-95, 131-137
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: Medium

Vulnerable Code

python
def check_url(url: str, timeout: int = 5) -> dict:
    """
    Check a single URL via HEAD request.

    Returns dict with: url, status, ok, error
    """
    # Skip non-HTTP schemes
    if not url.startswith(("http://", "https://")):
        return {
            "url": url,
            "status": None,
            "ok": None,
            "skipped": True,
            "reason": f"Non-HTTP scheme: {url.split(':')[0]}",
        }

    try:
        req = urllib.request.Request(url, method="HEAD")
        req.add_header("User-Agent", "axiom-markdown-link-auditor/0.1")
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return {
                "url": url,
                "status": resp.status,
                "ok": 200 <= resp.status < 400,
                "skipped": False,
            }
python
if check_remote:
    broken = []
    for link in links:
        url = link["url"]
        if not url.startswith(("http://", "https://")):
            continue
        check = check_url(url, timeout=timeout)
        if not check.get("ok") and not check.get("skipped"):
            broken.append({**link, **check})

Technical Analysis

The application extracts URLs from potentially untrusted Markdown and sends HEAD requests to them when remote checking is enabled. Validation only checks whether the string starts with http:// or https://.

It does not resolve and validate the destination address, reject loopback or private networks, block link-local and reserved addresses, enforce a destination allowlist, or revalidate redirect targets. Consequently, an attacker who controls audited Markdown can cause the host running the auditor to initiate requ ...[truncated 1975 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse URLs with urllib.parse.urlsplit() and require the normalized scheme to be exactly http or https.
  2. Reject URLs containing credentials, malformed hostnames, ambiguous numeric IP representations, or unsupported ports.
  3. Resolve the hostname before connecting and validate every resolved address with Python's ipaddress module.
  4. Reject loopback, private, link-local, multicast, reserved, and unspecified IPv4 and IPv6 addresses.
  5. Prevent DNS rebinding by ensuring the connection uses an address that was validated, rather than resolving the hostname independently after validation.
  6. Disable redirects or explicitly validate the scheme, hostname, and resolved addresses of every redirect target.
  7. Prefer an explicit domain allowlist in CI or other sensitive environments.
  8. Apply network-level egress controls so the process cannot reach metadata services or internal management networks.
  9. Preserve strict connection and overall request timeouts, and add limits for the number of checked links.
  10. Add tests covering loopback, RFC1918 private ranges, IPv6 local addresses, link-local metadata addresses, redirects to internal hosts, and DNS rebinding scenarios.
  11. Clearly document that --check-remote performs network requests based on URLs contained in the audited document.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description promises three main capabilities: broken internal link detection, dead external link checking via HEAD, and orphan page reporting. The code only clearly implements external HTTP/HTTPS checking (optional) and generic extraction/counting of links from one Markdown document. Non-HTTP links are explicitly skipped rather than validated, so internal links are not checked for existence. There is also no repository/site graph analysis needed to identify orphan pages; the tool processes only one file at a time. Additionally, it includes image and bare URL extraction not mentioned in the description. Because key promised behaviors are missing, the description does not accurately represent the actual code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The declared description is for a functional Markdown link auditor with specific capabilities: broken internal-link detection, dead external-link checks via HEAD, and orphan-page reporting. However, the provided code is only a test file. It exercises functions named extract_links, check_url, and audit, confirming parsing of Markdown links/images/bare URLs and some remote-check toggling, but it does not itself implement the described functionality. From the tests, there is no sign of orphan-page analysis, no clear internal-link validation behavior, and no confirmation that remote checks are performed using HEAD requests. Because the supplied code chunk’s actual role and demonstrated capabilities materially differ from the declared purpose, this is a mismatch.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README advertises an optional remote link check using HEAD requests but does not clearly warn that enabling this feature will make outbound network connections to every external URL found in the markdown. This can leak IP address, user agent, access timing, and possibly internal document references to third-party hosts, which is a meaningful privacy and operational risk in a docs-maintenance context.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code includes prominent natural-language instructions and limitations in French, and the CLI output/description does not indicate that the language is configurable or that the tool is intentionally region-specific. That creates a language-policy issue because users are implicitly forced into a specific language without opt-in.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest describes a markdown link auditor that should find broken internal links and report orphan pages. In the implementation, audit() only counts extracted links and, when enabled, checks remote HTTP(S) URLs; there is no logic to resolve local markdown targets, validate anchors, traverse a docs tree, or compute orphaned pages.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring uses French-only natural-language instructions and limitation notes ('LIMITATIONS CONNUES', 'AUDITE LES LIENS...') with no indication that language is configurable or intentionally restricted to a region-specific use case. This is a natural-language locale policy concern because the skill appears to impose a language choice without user opt-in.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This manifest only lists file metadata and does not provide any invocation description, trigger phrases, or scope constraints. For a manifest file, the absence of activation specificity can make it unclear when the skill should activate versus when it should not.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

Most user-facing instructions and descriptions are presented only in French, which can amount to a language policy violation when no opt-in or locale justification is provided. The file does not indicate that the skill is intentionally region-specific or offer an alternative language.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill description explicitly advertises optional HEAD requests to external links but does not warn that enabling this behavior causes outbound network access. In CI or restricted environments, even HEAD requests can disclose metadata, contact untrusted hosts, trigger policy violations, or create SSRF-like risk if user-controlled documentation contains arbitrary URLs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

Le fichier est rédigé en français de bout en bout, y compris la description d’usage, sans indiquer de possibilité de langue alternative ou de justification de contrainte locale. Selon la règle de politique linguistique, imposer une langue spécifique sans opt-in utilisateur peut constituer une violation de politique en langage naturel.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The top-level docstring presents the tool as a markdown link checker and explicitly mentions only anchor-validation and redirect limitations, implying broader link auditing support. In practice, the code never verifies whether local relative links exist or whether pages are orphaned, so the documentation overstates what is implemented.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.