Back to skill

Security audit

SageMaker Training Job

Security checks for vulnerabilities and agentic risk

Overview

This SageMaker training skill is mostly purpose-aligned, but it has unsafe artifact download/extraction behavior and broad source packaging that could overwrite local files or upload unintended private files.

Review this before installing or using. Use a dedicated S3 bucket and least-privilege temporary AWS credentials, run dry-run from a tightly scoped source directory, avoid broad project roots, and use --no-download unless you trust the job output. Do not extract downloaded model artifacts from untrusted training code or shared S3 prefixes until the downloader validates paths and archive members.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sagemaker_train.py:317
Finding

S3 Object Keys Can Escape the Local Artifact Directory

Content
View full analysis
{local}") s3.download_file(bucket, key, str(local)) ``` ### Technical Analysis The relative local path is derived directly from an S3 object key. Although the object listing is constrained by an S3 prefix, the remaining key can contain traversal components such as `../`. Joining such a value with `output_dir` does not guarantee that the resulting path remains beneath that directory. The code does not resolve the destination path or perform a containment check before creating parent directories and downloading the object. For example, an object key resembling: ```text sagemaker/output/JOB/../../.config/example ``` can produce a destination outside the intended output directory. Exploitation requires an attacker, compromised training process, or other principal to have permission to create objects under the downloaded S3 prefix. ### Attack Path 1. A training job, compromised execution role, or another bucket writer creates an S3 object under the artifact prefix. 2. The portion after the expected prefix contains one or more `../` path components. 3. The user completes or resumes the affected SageMaker job with artifact downloading enabled. 4. `download_artifacts()` constructs the local destination without canonicalization. 5. The AWS SDK writes the object outside the selected output directory. ### Impact Assessment The attacker can overwrite or create files accessible to the operating-system account running the Skill. T ...[truncated 378 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sagemaker_train.py:329
Finding

Downloaded Model Archives Are Extracted Without Member Validation

Content
View full analysis
{extract_dir}") with tarfile.open(model_tar, "r:gz") as tar: tar.extractall(extract_dir) ``` ### Technical Analysis The Skill automatically extracts a remotely generated `model.tar.gz` using `tar.extractall()` without explicitly validating archive members. A malicious archive may contain: - Absolute member paths. - Member names containing `../`. - Symbolic links or hard links targeting locations outside the extraction directory. - Special-file entries that are inappropriate for model artifacts. The archive originates from a SageMaker training job and is downloaded from S3. A malicious training script, compromised container image, compromised execution role, or bucket writer could therefore control its contents. ### Attack Path 1. An attacker controls or compromises the training code, training container, execution role, or relevant S3 artifact prefix. 2. The attacker creates a `model.tar.gz` containing a traversal path, absolute path, or unsafe link. 3. The SageMaker job reports successful completion or the malicious archive is placed at the expected artifact location. 4. The user runs the Skill with automatic download enabled. 5. The archive is extracted without validating its members. 6. Crafted entries may be written outside `output_dir/model` or may establish unsafe filesystem links. ### Impact Assessment Successful exploitation can create or overwrite files writable by the local account running the Skill. The impact can include project corruption, configuration modification, user-level code execution through overwritten s ...[truncated 308 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sagemaker_train.py:176
Finding

Source Packaging Can Upload Unintended Sensitive Files

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
references/setup.md:296
Finding

Dependency Installation Guidance Is Unpinned and Non-Reproducible

Content
View full analysis
=4.0 optuna>=3.0 shap>=0.40 ``` and states: ```text SageMaker automatically installs these before running your script. ``` ### Technical Analysis The project instructs users to install packages without exact reviewed versions, cryptographic hashes, or a lock file. The example training requirements use open-ended lower bounds, allowing future releases to be selected automatically. Python package installation can execute package-provided build or installation logic. A compromised upstream release, dependency-resolution change, unsafe package index configuration, or malicious transitive dependency could therefore introduce code not represented in the audited project. No evidence was found that the named packages are currently malicious. The vulnerability is the absence of reproducible and integrity-verified dependency controls. ### Attack Path 1. A user follows the setup instructions or submits a training job containing the example requirements. 2. `pip` resolves the latest package versions and transitive dependencies available from the configured index. 3. An upstream package, release, dependency, or index resolution path has been compromised or unexpectedly changed. 4. Installation executes or imports code from the unreviewed dependency. 5. That code runs with the privileges and network access of the local environment or SageMaker training container. ...[truncated 499 chars]
Remediation
View remediation
=version` with reviewed exact versions in examples. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says this skill submits and manages SageMaker training jobs end-to-end. The supplied code does none of that orchestration. Instead, it parses CLI arguments, optionally queries SageMaker for metadata about an existing training job, and computes an estimated cost using hardcoded hourly rates and a spot-discount assumption. While it touches SageMaker training-job metadata, its primary purpose is materially different from the declared behavior, so this is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a training-job submission/orchestration capability for SageMaker, including packaging code, uploading data/artifacts, launching jobs, monitoring them, and downloading outputs. The supplied code does none of that. Its sole function is read-only inspection of existing SageMaker training jobs via list_training_jobs and describe_training_job. While listing job status is loosely related to SageMaker training, the primary purpose is materially different from the declared purpose, and most advertised capabilities are absent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents the skill as an end-to-end AWS SageMaker remote training orchestrator. The actual code chunk is instead a simple local/SageMaker-compatible test training entrypoint used for smoke testing. Its primary purpose is to verify the training-container contract by reading CLI args, emitting metrics, and saving a dummy model file. That is materially different from packaging code, interacting with AWS/S3, launching remote jobs, managing compute types, or polling results. This is a clear description-behavior mismatch based on the supplied code chunk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/sagemaker_train.py (reported line 160)May include surrounding context.

python
# Patterns to exclude from source packaging
SOURCE_EXCLUDE_PATTERNS = {
    "__pycache__", ".pyc", ".pyo", ".git", ".gitignore",
    ".env", ".venv", "venv", "node_modules", ".DS_Store",
    ".ipynb_checkpoints", "__MACOSX", ".eggs", "*.egg-info",
}

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill advertises shell, file read/write, and environment access capabilities but does not declare any explicit tool scope restrictions. In an agent ecosystem, missing permission boundaries can let the skill access local files, environment-provided AWS credentials, and execute commands more broadly than users expect, increasing the blast radius if invoked incorrectly or paired with unsafe scripts.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Overly broad trigger phrases such as generic references to 'SageMaker' or 'cloud training' can cause unintended invocation of a skill that has shell, file, and environment access. In this context, accidental activation is more dangerous because the skill is designed to interact with AWS resources and may consume credentials, incur cloud cost, or act on local project files without sufficiently specific user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The guide explicitly recommends exporting long-lived AWS access keys as environment variables on a personal PC, but does not warn about the operational risk: such credentials can be exposed through shell history, inherited subprocess environments, shared terminals, CI logs, crash dumps, or local compromise. In an AWS-focused skill that launches cloud jobs and accesses S3, these keys grant meaningful account access and increase the blast radius if mishandled.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/sagemaker_smoke_test.py (reported line 34)May include surrounding context.

python
train_launcher = skill_dir / "sagemaker_train.py"
    cost_script = skill_dir / "sagemaker_cost.py"
    output_dir = Path("/tmp/sagemaker-smoke-test-output")
    job_name = f"smoke-test-{int(__import__('time').time())}"

    python = sys.executable
    errors = []

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/sagemaker_smoke_test.py (reported line 55)May include surrounding context.

python
print(f"\n--- Step 1: Local script test ---")
    local_model_dir = Path("/tmp/sagemaker-smoke-test-local")
    local_model_dir.mkdir(parents=True, exist_ok=True)
    result = subprocess.run(
        [python, str(train_script), "--epochs", "1", "--model-dir", str(local_model_dir)],
        capture_output=True, text=True
    )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/sagemaker_smoke_test.py (reported line 97)May include surrounding context.

python
"--poll-interval", "15",
    ]

    result = subprocess.run(cmd, capture_output=False)
    if result.returncode != 0:
        print(f"  ❌ SageMaker job failed (exit code {result.returncode})")
        errors.append("sagemaker_job")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/sagemaker_smoke_test.py (reported line 117)May include surrounding context.

python
# --- Step 3: Cost check ---
    print(f"\n--- Step 3: Cost check ---")
    result = subprocess.run(
        [python, str(cost_script), "--job-name", job_name, "--region", args.region],
        capture_output=True, text=True
    )

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
55% 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 · scripts/sagemaker_train.py (reported line 217)May include surrounding context.

python
def upload_to_s3(s3, local_path, bucket, key):
    """Upload a file to S3."""
    print(f"  Uploading to s3://{bucket}/{key} ...")
    s3.upload_file(local_path, bucket, key)
    return f"s3://{bucket}/{key}"

Static analysis

No suspicious patterns detected.