Back to skill

Security audit

Octodns

Security checks for vulnerabilities and agentic risk

Overview

This DNS automation skill is purpose-aligned but needs Review because it can change live DNS and handles powerful credentials with weak safeguards.

Install only if you are comfortable reviewing and tightening the scripts first. Use least-privilege DNS tokens limited to test zones, avoid the webhook example as written, do a dry run before every apply, do not run automated --doit flows without approvals, and store provider credentials in a proper secrets manager or locked-down files with masked input and restrictive permissions.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (7)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/dynamic-dns.md:165
Finding
Unauthenticated webhook permits arbitrary DNS modification and path traversal<![CDATA[ ## Vulnerability Details **File Location**: `references/dynamic-dns.md:165-197` **Vulnerability Type**: Missing authentication, missing authorization, path traversal, and unsafe automatic DNS deployment **Risk Level**: Critical ### Vulnerable Code ```python @app.route('/update', methods=['POST']) def update_dns(): data = request.json # Update zone file zone_file = f"config/{data['zone']}.yaml" with open(zone_file, 'r') as f: zone = yaml.safe_load(f) zone[data['name']] = { 'type': data['type'], 'value': data['value'], 'ttl': data.get('ttl', 300) } with open(zone_file, 'w') as f: yaml.dump(zone, f) # Sync result = subprocess.run([ 'scripts/sync.sh', '--zone', data['zone'], '--doit' ], capture_output=True, text=True) return { 'success': result.returncode == 0, 'output': result.stdout } if __name__ == '__main__': app.run(port=5000) ``` ### Technical Analysis The documented webhook accepts arbitrary JSON and performs a privileged DNS update without authenticating or authorizing the caller. There is no zone allowlist, request signature, API token, replay protection, or validation of record names, types, values, and TTLs. The attacker-controlled `zone` is also inserted directly into a filesystem path: ```python zone_file = f"config/{data['zone']}.yaml" ``` Values such as `../target` can escape the intended `config` directory and address another YAML file available to the process. After modifying the file, the handler invokes `sync.sh` with `--doit`, immediately applying the change rather than performing a preview or requiring approval. Although Flask binds to loopback by default in this exact example, any local process can call it, and a deployment that exposes or proxies the service would make the vulnerability remotely reachable. ### Attack Path 1. The operator implements and starts the ...[truncated 934 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require authenticated requests using a strong API token, mutual TLS, or signed requests. - Authorize each identity against an explicit zone and operation allowlist. - Bind to loopback explicitly unless remote access is required; if exposed, place the service behind authenticated TLS. - Parse and validate the request against a strict schema. - Allowlist supported DNS record types and validate values according to their record type. - Restrict TTLs to an approved range. - Resolve the requested file with `pathlib.Path.resolve()` and verify that it remains beneath the intended configuration directory. - Reject zone values containing separators, traversal components, control characters, or invalid DNS syntax. - Run a dry-run first and require approval for the exact generated plan before executing `--doit`. - Use narrowly scoped DNS credentials and keep an immutable audit log of the caller, requested change, preview, approval, and provider response. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sync.sh:31
Finding
Unsafe command construction allows octoDNS argument injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sync.sh:31-77` **Vulnerability Type**: Argument injection and unsafe shell word splitting **Risk Level**: High ### Vulnerable Code ```bash # Default to dry-run (no --doit flag) MODE="" ZONE="" # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --doit) MODE="--doit" shift ;; --zone) ZONE="$2" shift 2 ;; --config) CONFIG_FILE="$2" shift 2 ;; *) echo "Unknown option: $1" echo "Usage: $0 [--doit] [--zone ZONE] [--config FILE]" echo "" echo " (no flags) = dry-run (preview only)" echo " --doit = actually apply changes" exit 1 ;; esac done # Build command CMD="octodns-sync --config-file=$CONFIG_FILE $MODE" if [ -n "$ZONE" ]; then CMD="$CMD $ZONE" fi echo "Running: $CMD" echo "" # Execute and capture output OUTPUT=$($CMD 2>&1) ``` ### Technical Analysis The script constructs an executable command as one scalar string and then expands it unquoted. Bash consequently performs word splitting and pathname expansion on the generated string. A config path or zone containing whitespace, wildcard characters, or option-like components can be interpreted as multiple octoDNS arguments rather than one value. This is not equivalent to evaluating arbitrary shell operators because expansion output is not reparsed as shell syntax. It nevertheless creates a concrete argument-injection boundary into a tool capable of changing live DNS. The parser also accesses `$2` without first verifying that a value exists for `--zone` or `--config`, allowing malformed invocations to fail unpredictably under `set -e`. ### Attack Path 1. An attacker or untrusted automation influences a `--zone` or `--config` value. 2. The value is concatenated into `CMD`. 3. `OUTPUT=$($CMD 2>&1)` expands ...[truncated 622 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use a Bash array so each value remains one argument: ```bash cmd=(octodns-sync "--config-file=$CONFIG_FILE") if [[ "$MODE" == "--doit" ]]; then cmd+=(--doit) fi if [[ -n "$ZONE" ]]; then cmd+=(-- "$ZONE") fi printf 'Running:' printf ' %q' "${cmd[@]}" printf '\n' set +e OUTPUT=$("${cmd[@]}" 2>&1) EXIT_CODE=$? set -e ``` Additionally: - Verify that `--zone` and `--config` have following values before reading `$2`. - Reject zone names beginning with `-`. - Validate zones with strict DNS-name rules. - Resolve and constrain config paths to an approved directory. - Prefer a fixed, reviewed production configuration instead of accepting arbitrary paths during live apply operations. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/add-zone.sh:22
Finding
Unvalidated zone and provider values permit octoDNS YAML configuration injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/add-zone.sh:22-52` **Vulnerability Type**: YAML injection through untrusted configuration values **Risk Level**: High ### Vulnerable Code ```bash ZONE_INPUT="$1" # Add trailing dot if not present if [[ ! "$ZONE_INPUT" =~ \.$ ]]; then ZONE="${ZONE_INPUT}." else ZONE="$ZONE_INPUT" fi # Get provider if [ -n "$2" ]; then PROVIDER="$2" else PROVIDER=$(get_default_provider "$AGENT_CONFIG") fi # Check if zone already exists in config if grep -q "^ ${ZONE}" "$CONFIG_FILE"; then echo "✓ Zone $ZONE already exists in production.yaml" exit 0 fi echo "Adding $ZONE to production.yaml..." echo "Provider: $PROVIDER" # Add the zone with proper YAML indentation cat >> "$CONFIG_FILE" <<EOF ${ZONE}: sources: - config targets: - ${PROVIDER} EOF ``` The same pattern appears when generating a temporary dump configuration in `scripts/dump.sh:52-65`: ```bash cat > "$TEMP_CONFIG" <<EOF --- providers: easydns: class: octodns_easydns.EasyDnsProvider token: env/EASYDNS_TOKEN api_key: env/EASYDNS_API_KEY portfolio: env/EASYDNS_PORTFOLIO zones: ${ZONE}: sources: - ${PROVIDER} EOF ``` ### Technical Analysis Zone and provider values are inserted directly into YAML without quoting, escaping, structural validation, or serialization. Shell arguments can contain newline characters, colons, comment markers, anchors, and other YAML syntax. A crafted value can therefore introduce additional keys or alter the generated `zones`, `sources`, or `targets` structure. The existence check also treats the zone as a regular expression: ```bash grep -q "^ ${ZONE}" "$CONFIG_FILE" ``` Regex metacharacters can produce false matches and bypass or distort the intended duplicate check. ### Attack Path 1. An attacker or untrusted caller supplies a crafted zone or provider containing YAML syntax and newlines. 2. `add-zone.sh` or `dump.sh` interpolates the value in ...[truncated 525 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Validate zone names using strict DNS rules before any file operation. - Maintain an explicit allowlist mapping provider identifiers to known provider configurations. - Reject newlines, control characters, YAML metacharacters, path separators, and values beginning with `-`. - Generate YAML with a real serializer, such as a short Python program using `yaml.safe_dump`, rather than a here-document. - Parse the generated file with `yaml.safe_load` and verify its exact expected schema before use. - Use fixed-string matching where appropriate, such as `grep -F`, although structured YAML parsing is preferable. - Do not permit the same untrusted value to define both a filesystem name and a YAML key without separate validation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/init_config.sh:10
Finding
Zone path traversal permits writing files outside the configuration directory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/init_config.sh:10-67` **Vulnerability Type**: Path traversal and arbitrary YAML file creation **Risk Level**: High ### Vulnerable Code ```bash if [ -z "$1" ]; then echo "Usage: $0 <zone>" echo "Example: $0 example.com" exit 1 fi ZONE="$1" # Create config directory mkdir -p "$CONFIG_DIR" # Create zone file template ZONE_FILE="${CONFIG_DIR}/${ZONE}.yaml" if [ ! -f "$ZONE_FILE" ]; then cat > "$ZONE_FILE" <<EOF --- # ${ZONE} DNS zone # Root A record '': ttl: 300 type: A value: 192.0.2.1 # www subdomain www: ttl: 300 type: CNAME value: ${ZONE}. EOF echo "✓ Created config/${ZONE}.yaml" fi ``` ### Technical Analysis The user-supplied zone is treated as a filesystem path component without validation or canonicalization. Values containing `../` can escape `CONFIG_DIR`. The script checks only whether the destination already exists; it does not verify that the resolved path remains beneath the intended directory. The appended `.yaml` suffix limits the destination filename but does not prevent traversal to another writable YAML path. ### Attack Path 1. A caller invokes the script with a traversal value such as `../../some/writable/target`. 2. The script forms `CONFIG_DIR/../../some/writable/target.yaml`. 3. Filesystem path resolution escapes the project configuration directory. 4. If the target does not already exist and its parent is writable, the script creates the YAML file there. 5. Another application or workflow may subsequently consume the attacker-created file. ### Impact Assessment The caller can create a YAML file outside the project configuration directory with the privileges of the user running the script. The practical scope is limited to writable paths and filenames ending in `.yaml`, but this can still alter other applications' configuration or create files in sensitive workflow locations. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Accept only canonical DNS zone names. - Reject `/`, `\`, `..`, whitespace, control characters, and empty labels. - Normalize the destination and verify containment before writing: ```bash case "$ZONE" in *[!A-Za-z0-9.-]*|*/*|*..*) echo "Invalid zone name" >&2 exit 1 ;; esac ``` - Prefer a robust DNS-name parser over shell patterns. - Resolve the parent directory and destination through a trusted language API and verify that the destination is a child of `CONFIG_DIR`. - Create files with exclusive semantics to avoid symlink or race-related replacement. - Refuse symlink destinations and inspect every parent component where the threat model includes other local users. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lib/secure-creds.sh:5
Finding
Credential paths are embedded in Python source and secret-file permissions are not enforced<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib/secure-creds.sh:5-64,111-145` **Vulnerability Type**: Python source injection and insecure credential handling **Risk Level**: High ### Vulnerable Code ```bash get_credentials_dir() { local skill_dir="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}" local agent_config="${skill_dir}/.agent-config.json" # Try to read from agent config if [ -f "$agent_config" ]; then local creds_path=$(python3 -c " import json, os, sys try: config = json.load(open('$agent_config')) path = config.get('credentials_path', '../.credentials') # Resolve relative to agent_config location abs_path = os.path.abspath(os.path.join(os.path.dirname('$agent_config'), path)) print(abs_path) except: sys.exit(1) " 2>/dev/null) ``` ```bash check_credential_file_permissions() { local file="$1" if [ ! -f "$file" ]; then echo "Error: Credential file not found: $file" >&2 return 1 fi if [ "$(uname)" = "Darwin" ]; then local perms=$(stat -f "%Lp" "$file") else local perms=$(stat -c "%a" "$file") fi if [ "$perms" != "600" ] && [ "$perms" != "400" ]; then echo "⚠️ Warning: $file has insecure permissions: $perms" >&2 echo " Recommended: chmod 600 $file" >&2 fi return 0 } ``` ```bash local creds_file="${creds_dir}/${provider}.json" # Check permissions before loading check_credential_file_permissions "$creds_file" # Load credentials based on provider if [ "$provider" = "easydns" ]; then export EASYDNS_TOKEN=$(python3 -c "import json; print(json.load(open('$creds_file'))['api_token'])" 2>/dev/null) export EASYDNS_API_KEY=$(python3 -c "import json; print(json.load(open('$creds_file'))['api_key'])" 2>/dev/null) export EASYDNS_PORTFOLIO=$(python3 -c "import json; print(json.load(open('$creds_file')).get('portfolio', ''))" 2>/dev/null) elif [ "$provider" = "route5 ...[truncated 2827 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never interpolate paths into Python source. Pass them as arguments: ```bash python3 - "$creds_file" <<'PY' import json import sys with open(sys.argv[1], encoding="utf-8") as handle: data = json.load(handle) print(data["api_token"]) PY ``` - Validate provider identifiers against a fixed allowlist and map each identifier to a fixed credential filename. - Set `umask 077` before creating credential directories or files. - Create the directory with mode `700` and credential files with mode `600`. - Fail closed when a credential file or any relevant parent directory has unsafe permissions. - Use `read -s` for secrets and print a newline after input. - Generate JSON with a serializer rather than a here-document. - Replace the hard-coded personal path with a user-selected path under an appropriate secure configuration directory. - Minimize environment-variable exposure; pass credentials through a provider-supported secret mechanism where possible. - Clear exported credentials when no longer required and prevent child processes that do not need them from inheriting them. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sync.sh:67
Finding
Destructive DNS deletion checks occur only after changes are applied<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sync.sh:67-94` **Vulnerability Type**: Missing pre-apply safety gate for destructive operations **Risk Level**: High ### Vulnerable Code ```bash # Build command CMD="octodns-sync --config-file=$CONFIG_FILE $MODE" if [ -n "$ZONE" ]; then CMD="$CMD $ZONE" fi echo "Running: $CMD" echo "" # Execute and capture output OUTPUT=$($CMD 2>&1) EXIT_CODE=$? # Display output echo "$OUTPUT" # Safety check: warn about deletes if echo "$OUTPUT" | grep -q "Delete <"; then echo "" echo "⚠️ WARNING: This sync will DELETE records!" echo "⚠️ Review the 'Delete' lines above carefully." if [ -n "$MODE" ]; then echo "⚠️ Run again with --doit to apply (currently in apply mode)" else echo "⚠️ This was a preview. Deletes will happen if you run with --doit" fi echo "" fi ``` The required behavior stated in `SAFETY.md:142-146` is: ```text 1. ALWAYS dump existing zones before making changes 2. Parse the preview output for Delete lines 3. Alert the user if deletes look suspicious 4. Require confirmation before applying changes with deletes 5. Log all changes for audit trail ``` ### Technical Analysis When `MODE` contains `--doit`, `octodns-sync` applies the desired state before its output is searched for deletion messages. The warning therefore cannot stop a destructive operation. The implementation does not force a preview, compare an approved preview to the apply operation, require confirmation, impose a deletion threshold, or create an audit log. This is particularly dangerous because octoDNS treats the YAML file as the complete desired state. Missing records may be deleted from the provider. ### Attack Path 1. A zone file is incomplete, stale, corrupted, or manipulated through another vulnerability. 2. A user or automated process invokes `sync.sh --doit`. 3. octoDNS computes and applies deletions. 4. Only after execution does the script search the output for `De ...[truncated 411 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Always execute a dry-run first, even when the user requests `--doit`. - Parse the complete structured plan before making changes. - Abort if deletions are present unless the user explicitly approves the exact deletion list. - Bind approval to a cryptographic hash of the configuration and preview so the reviewed plan cannot change before application. - Add configurable maximum deletion counts and percentage thresholds. - Require a stronger confirmation phrase for whole-zone or high-volume deletion. - Refuse apply mode when the zone has not been dumped or backed up recently. - Record the actor, configuration hash, preview, approval, command result, and timestamp in an append-only audit log. - Use narrowly scoped provider credentials and separate production from development credentials. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/install.sh:12
Finding
Unpinned package installation creates a dependency supply-chain risk<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:12-23` **Vulnerability Type**: Unpinned executable dependencies without integrity verification **Risk Level**: Medium ### Vulnerable Code ```bash # Create venv if it doesn't exist if [ ! -d "$VENV_DIR" ]; then echo "Creating virtual environment..." python3 -m venv "$VENV_DIR" fi # Activate venv source "${VENV_DIR}/bin/activate" # Install packages pip install --quiet --upgrade pip pip install --quiet octodns octodns-easydns ``` The dynamic DNS CI example repeats the issue in `references/dynamic-dns.md:238-248`: ```yaml - name: Install octoDNS run: | pip install octodns octodns-easydns - name: Sync DNS env: EASYDNS_TOKEN: ${{ secrets.EASYDNS_TOKEN }} EASYDNS_API_KEY: ${{ secrets.EASYDNS_API_KEY }} EASYDNS_PORTFOLIO: ${{ secrets.EASYDNS_PORTFOLIO }} run: | octodns-sync --config-file=dns/config/production.yaml --doit ``` ### Technical Analysis The installer downloads and executes the newest versions satisfying unconstrained package names. There is no lockfile, exact version pin, package hash, signed artifact verification, or reviewed constraints file. It also upgrades pip automatically, introducing an additional mutable executable dependency. The CI example later provides DNS credentials to the installed code and performs a live synchronization. A compromised upstream release, package-index account, distribution path, or unexpectedly incompatible release could execute in a high-impact credential-bearing environment. ### Attack Path 1. An upstream package account, release process, or package distribution channel is compromised, or an unsafe new release is published. 2. The user runs `scripts/install.sh` or the documented CI workflow. 3. pip resolves and installs the changed package because no version or hash is constrained. 4. Package installation code executes under the invoking account. 5. During later DNS synchronization, installed provider code ...[truncated 431 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin every package to an exact reviewed version. - Generate and commit a lock or constraints file. - Require cryptographic hashes with `pip install --require-hashes`. - Download and review artifacts through a controlled dependency-update process. - Avoid automatically upgrading pip during routine installation. - Use an internal package mirror or allowlisted artifact repository where appropriate. - Run dependency vulnerability and provenance checks in CI. - Pin GitHub Actions to immutable commit SHAs rather than mutable major-version tags. - Test dependency updates in an isolated environment before granting access to production DNS credentials. - Use least-privilege provider tokens restricted to the necessary zones and operations. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The description presents the skill as a broad DNS-as-code management utility supporting many providers and use cases such as syncing, deploying, bulk-updating, and migrating zones. The actual code shown only scaffolds initial octoDNS config for a single zone and a single provider target (easyDNS), plus a YAML provider source. It creates template files and prints guidance, but does not perform DNS synchronization, deployment, migration, or interaction with multiple providers. While this script is related to octoDNS setup, the behavior in the provided chunk is materially narrower than the declared purpose, especially regarding multi-provider support and active DNS operations.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description focuses on DNS zone management through octoDNS across multiple providers. However, this code chunk does not manage DNS zones, records, providers, synchronization, deployment, or migration. Its primary purpose is instead to verify security hygiene around credentials and configuration files for the skill. While this may be a supporting utility within a DNS-related project, the actual behavior of the provided code chunk is materially different from the declared purpose and introduces undeclared capabilities related to local security/config auditing.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
scripts/sync.sh --zone example.com --doit
else
    echo "Validation failed"
    rm config/example.com.yaml.tmp
    exit 1
fi
```
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).

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises and instructs shell execution (`scripts/install.sh`, `scripts/dump.sh`, `scripts/sync.sh`) but does not declare any explicit tool scope or permissions boundary. In an agent setting, missing tool constraints can let the skill invoke shell actions without clear policy enforcement, which is risky here because the documented operations can modify live DNS state and cause destructive changes.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The webhook example exposes an HTTP endpoint that accepts untrusted JSON, writes to zone files, and then triggers live DNS synchronization. This turns documentation for DNS management into an unauthenticated remote control path for infrastructure changes, enabling unauthorized record modification, service hijacking, or denial of service if copied into real environments.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The webhook-triggered update flow describes accepting HTTP requests that directly modify DNS records and run a sync, but it omits any prominent warning about the sensitivity of these actions. In practice, users may deploy this pattern without access controls or change review, creating an easy path to unauthorized production DNS changes.

External Transmission

Medium
Category
Data Exfiltration
Content
Trigger updates:

```bash
curl -X POST http://localhost:5000/update \
  -H "Content-Type: application/json" \
  -d '{
    "zone": "example.com",
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The CI/CD example performs live production DNS changes using production credentials with --doit, but it does not prominently warn that the workflow applies real infrastructure modifications. This increases the risk of accidental outages or malicious changes if repository events, workflow edits, or credential handling are not tightly controlled.

External Transmission

Medium
Category
Data Exfiltration
Content
echo "DNS sync failed:" >> "$LOG"
    echo "$sync_output" >> "$LOG"
    # Alert
    curl -X POST https://monitoring.example.com/alert \
      -d "DNS sync failed for example.com"
fi
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The guide presents `scripts/sync.sh --zone example.com --doit` as the apply step without an explicit warning that this action can create, modify, or delete live DNS records. In a DNS migration context, destructive changes can cause outages, mail disruption, or service misrouting if the reviewed YAML or target state is incorrect.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This shell script performs a file write by appending a new zone entry to production.yaml, which can affect production behavior. Although it prints progress messages, there is no confirmation prompt, cautionary comment, or user-facing warning that the command will modify a production config file.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Warn if permissions are too open (should be 600 or 400)
    if [ "$perms" != "600" ] && [ "$perms" != "400" ]; then
        echo "⚠️  Warning: $file has insecure permissions: $perms" >&2
        echo "   Recommended: chmod 600 $file" >&2
    fi
    
    return 0
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Warn if permissions are too open (should be 600 or 400)
    if [ "$perms" != "600" ] && [ "$perms" != "400" ]; then
        echo "⚠️  Warning: $file has insecure permissions: $perms" >&2
        echo "   Recommended: chmod 600 $file" >&2
    fi
    
    return 0
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Warn if permissions are too open (should be 600 or 400)
    if [ "$perms" != "600" ] && [ "$perms" != "400" ]; then
        echo "⚠️  Warning: $file has insecure permissions: $perms" >&2
        echo "   Recommended: chmod 600 $file" >&2
    fi
    
    return 0
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The manifest describes a DNS-management skill for managing and syncing zones with octoDNS, but this script implements a separate capability to read a local credentials file and export provider secrets into the environment. While provider authentication may be used operationally, exposing a dedicated credential-hydration helper is not described in the manifest's stated user-facing scope.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script exports API credentials into the process environment without warning, which increases the chance they will be exposed to child processes, debugging output, shell history workflows, or crash reports. In an automation/agent context, environment variables are a common propagation channel, so broadly exporting DNS credentials can unintentionally grant other invoked tools access to the same secrets.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The setup script collects DNS provider credentials and persists them in plaintext JSON files under a fixed local credentials directory. These secrets can be exposed through local compromise, backups, accidental sharing, or weak file permissions, and the skill context increases risk because DNS credentials can enable domain hijacking, traffic redirection, or outage-causing changes.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script writes sensitive API credentials to disk without any warning about plaintext storage or steps to protect the resulting file. In a DNS-management skill, exposed provider credentials are especially dangerous because they may allow an attacker to modify zone records, redirect traffic, obtain certificates, or disrupt service.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The credential prompts use normal `read` calls, so the API token and key are echoed on the terminal and may be visible to shoulder surfers, screen recordings, terminal logs, or shared sessions. Because these are DNS provider secrets, disclosure can lead directly to unauthorized DNS changes and domain-level compromise.

Intent-Code Divergence

Low
Confidence
84% confidence
Finding
The script is presented as agent configuration, but it also provisions and stores provider credentials, which is a broader and more sensitive behavior than the comment suggests. That mismatch can mislead reviewers or users and reduce scrutiny around secret handling, increasing the chance that sensitive operations are executed without informed consent.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
config/dump.yaml:9

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
config/example-production.yaml:13

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/migration.md:26

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/dump.sh:59

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/init_config.sh:36

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
SKILL.md:139