Back to skill

Security audit

build-oled-technology-intelligence-rd

Security checks for vulnerabilities and agentic risk

Overview

This skill coherently builds a local evidence-backed technology-intelligence HTML portal, with limited file-write risk around user-chosen output directories.

Install only if you want an agent to prepare reviewed technology-intelligence data and write a local HTML portal. Use a new empty output directory, avoid symlinked paths, and be deliberate with --overwrite because it can replace generated page names in the chosen directory.

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/generate_portal.py:844
Finding

Ineffective Output-Directory Symlink Validation

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_portal.py, lines 844–870
Vulnerability Type: Symlink-following file-write weakness
Risk Level: Medium

Vulnerable Code

python
def prepare_output(path: Path, pages: set[str], overwrite: bool) -> Path:
    output = path.expanduser().resolve()
    if output.parent == output:
        fail("Refusing to use a filesystem root as the output directory")
    if output.exists() and output.is_symlink():
        fail("Output directory must not be a symbolic link")
    if output.exists() and not output.is_dir():
        fail("Output path exists and is not a directory")
    if output.exists():
        contents = list(output.iterdir())
        if contents and not overwrite:
            fail("Output directory is not empty; use --overwrite to replace expected portal pages")
        for name in pages:
            candidate = output / name
            if candidate.exists() and (candidate.is_symlink() or not candidate.is_file()):
                fail(f"Expected page path is not a regular file: {candidate}")
    else:
        output.mkdir(parents=True)
    return output


def write_pages(output: Path, pages: dict[str, str]) -> None:
    for name, content in pages.items():
        if Path(name).name != name or not name.endswith(".html"):
            fail(f"Unsafe generated filename: {name}")
        destination = output / name
        destination.write_text(content, encoding="utf-8")

Technical Analysis

The output path is passed through Path.resolve() before the code checks output.is_symlink(). Resolution dereferences a symbolic link and returns its target, so the subsequent symlink check examines the target directory rather than the path originally supplied by the user. As a result, the intended rejection of a symlinked output directory is ineffective.

When --overwrite is enabled, the renderer may replace generated filenames such as index.html, patents.html, and company or technology ...[truncated 1619 chars]

Remediation
View remediation

Remediation Suggestions

  1. Inspect the original, unresolved output path using lstat() or Path.is_symlink() before calling resolve().
  2. Validate every existing path component between a trusted base directory and the output directory, rejecting symbolic links where they are not explicitly permitted.
  3. Constrain output to an approved base directory and verify the resolved destination remains beneath that base with Path.is_relative_to() or an equivalent robust containment check.
  4. Use directory-descriptor-relative file operations with no-follow semantics, such as openat-style operations with O_NOFOLLOW, where supported.
  5. Open destination files with flags that reject symbolic links and unexpected file types, rather than relying only on a prior path check.
  6. Write to securely created temporary files in the same validated directory, flush them, and atomically replace expected regular files.
  7. Revalidate destination type immediately before replacement and minimize the interval between validation and writing.
  8. Add regression tests covering a symlinked output directory, symlinked parent components, symlinked destination files, and concurrent path replacement.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill instructs the agent to read local files, write output files, and optionally query network-exposed data sources, but it does not declare any explicit tool scope or allowed-tools boundary. This creates an authorization ambiguity: a host agent may grant broader file or network access than intended, increasing the risk of unintended data access, exfiltration, or writes outside the expected workspace if the skill is invoked in a privileged environment.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% 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/company-mapping.md (reported line 85)May include surrounding context.

md
## Alias normalization

Normalize case, surrounding punctuation, common corporate suffixes, and documented abbreviations for matching, but preserve the original source string. Do not automatically remove words that distinguish subsidiaries or business units.

Match in this order:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The JSON contract sets "languages": ["English"], which is a natural-language locale constraint. Under the policy, forcing a specific language without user opt-in or a clearly justified region-specific need is a violation, and this file does not provide such an opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The example schema specifies "language": "English", which signals an English-only expectation for records. The policy allows locale constraints only when the user can choose or when the constraint is clearly justified, neither of which is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The search-log example uses "languages": ["English"], which encodes a fixed language constraint in natural language. Because the file does not offer a language choice or explain a necessary compliance/regional reason, this conflicts with the policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The shared HTML shell fixes the document language to lang="en", which is a natural-language locale constraint. The file does not indicate user opt-in, configurability, or a documented region-specific justification for forcing English.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

Line L010 requires an English name, which is a natural-language locale constraint. The file does not indicate user opt-in for language choice or explain a justified region-specific need for enforcing English naming.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The HTML shell always emits regardless of the portal metadata, even though the input schema includes a languages field. This forces a specific locale in generated output without offering user choice or explaining why English is required.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

This code performs file writes to the user-specified output directory and, together with the overwrite flow, can replace previously generated pages. While the CLI help mentions replacement behavior, there is no runtime confirmation prompt or user-facing disclosure immediately before the write operation.

Content

No source excerpt is available for this finding.