Back to skill

Security audit

Create and manage a sorted directory structure in AWS S3

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but its bulk S3 upload script can move more data than intended and has weak argument handling that deserves careful review before installation.

Review before installing. Use this only with a dedicated source directory you control, inspect for symlinks, prefer --dry-run first, use least-privilege AWS credentials restricted to the intended bucket and prefix, and avoid passing untrusted values to --storage-class.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
SKILL.md:104
Finding

Unsafe Recursive Deletion of a Predictable Staging Directory

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 104-109
Vulnerability Type: Unsafe recursive deletion using a fixed directory path
Risk Level: Medium

Technical Analysis

The documented synchronization workflow assigns a predictable, relative path to STAGING_DIR and recursively deletes that path before creating the staging structure:

bash
SOURCE_DIR="./files"
STAGING_DIR="./staging"
BUCKET="my-bucket"

# Create staging directory with prefix structure
rm -rf "$STAGING_DIR"
mkdir -p "$STAGING_DIR"

The quoting prevents argument splitting, but it does not make the deletion intrinsically safe. If ./staging already contains unrelated user data, following the documented example permanently deletes that data. The example also does not verify that the path was created exclusively for this operation, reject symbolic-link components in the path, or constrain deletion to a securely generated temporary directory.

The executable script uses mktemp -d, so this finding specifically concerns the alternative workflow provided in the skill documentation.

Attack Path

  1. A user has an existing directory named staging under the working directory, or runs the example from an unexpected directory containing such a path.
  2. The user copies and executes the documented “Efficient Bulk Sync” workflow.
  3. STAGING_DIR resolves to the pre-existing relative path ./staging.
  4. rm -rf "$STAGING_DIR" recursively deletes its contents before the upload begins.

Impact Assessment

Exploitation does not grant additional operating-system privileges; deletion occurs with the permissions of the user executing the example. Within that privilege boundary, all accessible content under the selected ./staging path can be permanently removed. The primary impact is local data loss and disruption of other processes that use the same directory.

Remediation
View remediation

Remediation Suggestions

  • Replace the fixed staging directory with a securely generated temporary directory:

    bash
    STAGING_DIR=$(mktemp -d) || exit 1
    cleanup() {
      rm -rf -- "$STAGING_DIR"
    }
    trap cleanup EXIT
    
  • Refuse to continue if temporary-directory creation fails.

  • Use rm -rf -- "$STAGING_DIR" so a path beginning with a hyphen cannot be interpreted as an option.

  • Keep the staging directory outside the source directory and document that it is temporary.

  • Do not present destructive cleanup of a fixed relative directory as the recommended workflow.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
s3-bulk-upload.sh:116
Finding

Source Symlinks Can Upload Files Outside the Selected Directory

Content
View full analysis

Vulnerability Details

File Location: s3-bulk-upload.sh, lines 116-151
Vulnerability Type: Symlink traversal and unintended local-file disclosure
Risk Level: High

Technical Analysis

Both upload modes treat symbolic links to regular files as eligible input. In Bash, [[ -f "$file" ]] follows a symbolic link and returns true when its target is a regular file.

The synchronization mode explicitly resolves each accepted path with realpath and creates another symlink to the resolved target:

bash
for file in "$SOURCE_DIR"/*; do
  [[ -f "$file" ]] || continue
  local basename
  basename=$(basename "$file")
  local prefix
  prefix=$(get_prefix "$basename")

  mkdir -p "$staging_dir/$prefix"
  ln -s "$(realpath "$file")" "$staging_dir/$prefix/$basename"
done

The individual mode has the same trust-boundary issue because it accepts the symlink with -f and passes it to aws s3 cp, which reads the referenced file:

bash
for file in "$SOURCE_DIR"/*; do
  [[ -f "$file" ]] || continue
  local basename
  basename=$(basename "$file")
  local prefix
  prefix=$(get_prefix "$basename")
  local dest="s3://$BUCKET/$prefix/$basename"

  if $DRY_RUN; then
    echo "[DRY RUN] $file -> $dest"
  else
    echo "Uploading: $basename -> $prefix/$basename"
    # shellcheck disable=SC2086
    if aws s3 cp "$file" "$dest" $STORAGE_FLAG --quiet; then
      ((uploaded++))
    else
      echo "  Failed: $basename" >&2
      ((failed++))
    fi
  fi
done

Consequently, the selected source-directory boundary is not enforced. An attacker who can place a symlink in that directory can cause a readable file anywhere else on the local filesystem to be uploaded.

Attack Path

  1. An attacker obtains write access to the chosen source directory but cannot directly read a sensitive file available to the account that will execute the uploader.
  2. The attacker creates a link suc ...[truncated 1213 chars]
Remediation
View remediation

Remediation Suggestions

  • Reject symbolic links before accepting an input:

    bash
    [[ -f "$file" && ! -L "$file" ]] || continue
    
  • Canonicalize both the source root and candidate path, then verify that the candidate remains below the canonical source root.

  • To reduce time-of-check/time-of-use exposure, operate on file descriptors or copy accepted files into a private staging directory rather than staging symlinks.

  • If symlink support is intentional, require an explicit option and prominently warn that targets outside the source directory may be uploaded.

  • Ensure the source directory is not writable by less-trusted users while the upload is running.

T09 · Insecure Skill Coding Practices

Error
Location
s3-bulk-upload.sh:91
Finding

Unvalidated Storage-Class Value Permits AWS CLI Option Injection

Content
View full analysis

Vulnerability Details

File Location: s3-bulk-upload.sh, lines 91-151
Vulnerability Type: Argument injection through unquoted string expansion
Risk Level: High

Technical Analysis

Although the help text lists four supported storage classes, the script does not enforce that allowlist. It concatenates the user-controlled value into a scalar string:

bash
# Build storage class flag
STORAGE_FLAG=""
if [[ -n "$STORAGE_CLASS" ]]; then
  STORAGE_FLAG="--storage-class $STORAGE_CLASS"
fi

That scalar is later expanded without quotes in both AWS CLI calls:

bash
# shellcheck disable=SC2086
aws s3 sync "$staging_dir" "s3://$BUCKET/" $STORAGE_FLAG
bash
# shellcheck disable=SC2086
if aws s3 cp "$file" "$dest" $STORAGE_FLAG --quiet; then

Because unquoted expansion performs shell word splitting, whitespace within STORAGE_CLASS creates additional command-line arguments. Shell metacharacters embedded in the variable are not re-evaluated as shell syntax, so this is not arbitrary shell-command execution. It is nevertheless AWS CLI argument injection.

An attacker or unsafe wrapper able to influence the storage-class argument can add AWS options rather than supplying only one storage-class value. Depending on AWS CLI parsing and configuration, injected options may alter endpoint selection, profile or region behavior, TLS validation, include/exclude processing, or other request semantics. In particular, endpoint redirection can transmit uploaded file content and AWS SigV4 authorization metadata to an attacker-controlled service. The AWS secret access key itself is not normally sent over the network, but signed request material and uploaded data are exposed.

Attack Path

  1. An attacker controls the --storage-class value through a wrapper, automation input, job parameter, or direct invocation.
  2. The attacker supplies a whitespace-containing value intended to create extra arguments ...[truncated 1338 chars]
Remediation
View remediation

Remediation Suggestions

  • Enforce the documented storage-class allowlist:

    bash
    case "$STORAGE_CLASS" in
      ""|STANDARD|STANDARD_IA|GLACIER_IR|INTELLIGENT_TIERING)
        ;;
      *)
        echo "Error: unsupported storage class" >&2
        exit 1
        ;;
    esac
    
  • Build optional arguments with a Bash array rather than a scalar string:

    bash
    storage_args=()
    if [[ -n "$STORAGE_CLASS" ]]; then
      storage_args=(--storage-class "$STORAGE_CLASS")
    fi
    
    aws s3 sync "$staging_dir" "s3://$BUCKET/" "${storage_args[@]}"
    aws s3 cp "$file" "$dest" "${storage_args[@]}" --quiet
    
  • Reject values containing whitespace, control characters, or a leading hyphen as defense in depth.

  • Avoid disabling ShellCheck warning SC2086 for security-sensitive command construction.

  • If command parameters originate from automation or remote users, validate them at both the caller boundary and inside this script.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (15)

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 · SKILL.md (reported line 193)May include surrounding context.

bash
BUCKET="my-bucket"
echo "test" | aws s3 cp - "s3://${BUCKET}/_test_access.txt" && \
  aws s3 rm "s3://${BUCKET}/_test_access.txt" && \
  echo "Bucket access OK"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill prominently instructs users to run upload commands against S3 using active AWS credentials, but it does not clearly warn that these examples transmit local files to a remote cloud bucket. In an agent-skill context, omission of an explicit exfiltration warning increases the chance of unintentional disclosure of sensitive local data.

Content

No source excerpt is available for this finding.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This command uploads a local file to S3, which is inherently a data egress operation. In this skill the behavior is expected, but it is still security-relevant because running it with sensitive files or the wrong bucket could exfiltrate data outside the intended boundary.

Content

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

PREFIX="_other" fi

aws s3 cp "$FILE" "s3://${BUCKET}/${PREFIX}/${FILE}"

text

## Bulk Upload

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

The bulk loop uploads every file in the source directory to S3, creating substantial exfiltration risk if the directory contents are broader than intended. Because this is bulk behavior, mistakes can leak many files quickly under the caller's credentials.

Content

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

PREFIX="_other" fi

aws s3 cp "$FILE" "s3://${BUCKET}/${PREFIX}/${BASENAME}" done

text

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The sync-based workflow is designed for efficient remote transfer to S3 and therefore carries the same core exfiltration risk as copy-based uploads, potentially at larger scale. In an agent context, convenience features can make unintended disclosure faster and less noticeable.

Content

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

Efficient Bulk Sync

For large uploads, stage files with symlinks then use aws s3 sync:

bash
SOURCE_DIR="./files"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The staging workflow includes unconditional local deletion with rm -rf on a user-controlled path variable, but the documentation does not clearly warn that the staging directory will be destroyed. Even though the example uses a fixed path, copy-paste or adaptation errors could lead to accidental local data loss.

Content

No source excerpt is available for this finding.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

This aws s3 sync command performs the actual bulk remote upload of the staged directory to S3. If the staging directory contains unexpected files or symlink-resolved sensitive content, the command can expose a large dataset in a single operation.

Content

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

md
done

# Sync entire staging directory to S3
aws s3 sync "$STAGING_DIR" "s3://${BUCKET}/"

# Clean up
rm -rf "$STAGING_DIR"

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The access test writes data to S3, which is still a cloud egress action, though only a trivial test object is transferred. The security concern is lower here, but the documentation should still note that executing the test modifies remote bucket contents using active credentials.

Content

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

bash
BUCKET="my-bucket"
echo "test" | aws s3 cp - "s3://${BUCKET}/_test_access.txt" && \
  aws s3 rm "s3://${BUCKET}/_test_access.txt" && \
  echo "Bucket access OK"

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

These storage-class examples are still examples of uploading local files to S3, so they represent remote data transfer. While demonstrative, they normalize exfiltration-capable commands without accompanying safety guidance.

Content

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

bash
# Standard (default)
aws s3 cp file.txt s3://bucket/prefix/file.txt

# Infrequent Access (cheaper storage, retrieval fee)
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class STANDARD_IA

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This example uploads a file to S3 with a different storage class, but the security characteristic is unchanged: local data is sent to remote cloud storage. The danger remains accidental disclosure to the wrong bucket or account.

Content

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

md
aws s3 cp file.txt s3://bucket/prefix/file.txt

# Infrequent Access (cheaper storage, retrieval fee)
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class STANDARD_IA

# Glacier Instant Retrieval (archive with fast access)
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class GLACIER_IR

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This Glacier example still performs an S3 upload, so sensitive local content could be transmitted off-host or out of organizational boundaries. Storage class choice does not reduce the confidentiality risk of uploading the wrong file.

Content

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

md
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class STANDARD_IA

# Glacier Instant Retrieval (archive with fast access)
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class GLACIER_IR

# Intelligent Tiering (auto-optimize based on access patterns)
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class INTELLIGENT_TIERING

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The Intelligent Tiering example also uploads local content to S3, preserving the same exfiltration risk profile as the other examples. In aggregate, repeated upload examples without strong warnings make accidental misuse more likely.

Content

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

aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class GLACIER_IR

Intelligent Tiering (auto-optimize based on access patterns)

aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class INTELLIGENT_TIERING

text

Add `--storage-class` to bulk upload loops for cost optimization on infrequently accessed files.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Content

Scanner excerpt · s3-bulk-upload.sh (reported line 17)May include surrounding context.

sh
Options:
  --storage-class CLASS   S3 storage class (STANDARD, STANDARD_IA, GLACIER_IR, INTELLIGENT_TIERING)
  --dry-run               Show what would be uploaded without uploading
  --sync                  Use staging + aws s3 sync (faster for many files)
  -h, --help              Show this help message

Examples:

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This line executes aws s3 sync to upload a staged directory to an arbitrary bucket supplied by the caller. While the script's stated purpose is bulk S3 upload, it can still enable unintended data exfiltration if used on sensitive local files or pointed at an attacker-controlled bucket, especially because there is no allowlist, confirmation, or restriction on destination buckets.

Content

Scanner excerpt · s3-bulk-upload.sh (reported line 137)May include surrounding context.

sh
else
    echo "Syncing to s3://$BUCKET/..."
    # shellcheck disable=SC2086
    aws s3 sync "$staging_dir" "s3://$BUCKET/" $STORAGE_FLAG
  fi
}

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This line performs aws s3 cp for each file to a user-controlled S3 destination. In context, the capability is intentional, but it still represents a real exfiltration primitive because any file in the chosen source directory can be transferred off-host without safeguards around sensitive content, approved destinations, or operator confirmation.

Content

Scanner excerpt · s3-bulk-upload.sh (reported line 159)May include surrounding context.

sh
else
      echo "Uploading: $basename -> $prefix/$basename"
      # shellcheck disable=SC2086
      if aws s3 cp "$file" "$dest" $STORAGE_FLAG --quiet; then
        ((uploaded++))
      else
        echo "  Failed: $basename" >&2

Static analysis

Detected: suspicious.generated_source_template_injection

User-controlled placeholder is embedded directly into generated source code.

Critical
Code
suspicious.generated_source_template_injection
Location
SKILL.md:73