T03 · Remote Payload Retrieval and Execution
- Location
scripts/init_wiremock.py:31- Finding
Remote WireMock JAR Is Downloaded and Executed Without Integrity Verification
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This integration-testing skill is broadly legitimate, but its helper scripts make persistent shell changes, install or execute unverified dependencies, and may leave local test services running.
Review and edit the helper scripts before running them. Prefer a virtual environment with pinned dependencies, verify downloaded artifacts, avoid automatic ~/.bashrc changes, keep Testcontainers cleanup enabled unless you explicitly choose otherwise, bind test services to loopback, and remove any lingering containers or shell exports after use.
scripts/init_wiremock.py:31Remote WireMock JAR Is Downloaded and Executed Without Integrity Verification
scripts/setup_testcontainers.py:28Unpinned Python Dependencies Are Installed at Runtime
scripts/setup_testcontainers.py:49Testcontainers Setup Persistently Disables Automatic Container Cleanup
scripts/start_localstack.py:109LocalStack Setup Persistently Overrides AWS Credentials and Endpoint Configuration
scripts/start_localstack.py:153LocalStack Signal Handler Exits Without Terminating the Child Service
templates/sftp-integration-tests.py:20SFTP Test Server Uses Unverified Host Keys, Predictable Credentials, and Broad Port Publishing
A description-behavior mismatch is dangerous because it can mislead users and orchestrators into approving a skill for harmless integration testing while it performs persistent host changes, package installation, and cleanup suppression. In particular, modifying ~/.bashrc, disabling Testcontainers Ryuk cleanup, and installing packages on the host can leave lasting side effects, weaken isolation assumptions, and cause lingering containers or altered environments beyond the test session.
Potential security issue detected. Manual review is recommended.
from testcontainers.core.docker_client import DockerClient
def test_with_network():
client = DockerClient()
network = client.client.networks.create("test-network")
with DockerContainer("nginx:latest") \
Potential security issue detected. Manual review is recommended.
from testcontainers.core.docker_client import DockerClient
def test_with_network():
client = DockerClient()
network = client.client.networks.create("test-network")
with DockerContainer("nginx:latest") \
The skill advertises code and operational capabilities involving containers, networked services, helper scripts, and writable setup actions, but it declares no explicit tool scope such as permissions or allowed-tools. That creates an overbroad trust boundary where an agent may invoke file, shell, or network actions without user-visible restriction, increasing the chance of unintended host modification or external connectivity during test setup.
The documentation instructs users to pull localstack/localstack:latest, which is a mutable tag and can resolve to different images over time. That weakens reproducibility and can expose users to unexpected or compromised upstream image changes in test environments.
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.
aws s3 ls aws s3 mb s3://test-bucket aws s3 cp file.txt s3://test-bucket/
### Environment Variables
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
# Test with authorization header
headers = {"Authorization": "Bearer token123"}
response = requests.get(
"http://localhost:8080/api/protected",
headers=headers
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def check_java():
"""Check if Java is available (WireMock requires Java)"""
try:
result = subprocess.run(
['java', '-version'],
capture_output=True,
text=True
The script downloads an executable JAR from the internet at runtime using curl and then later executes it with Java, but it performs no checksum, signature, or other integrity verification. If the download source, network path, or local artifact is tampered with, this becomes arbitrary code execution on the developer or CI host.
print(f"📥 Downloading WireMock {wiremock_version}...")
try:
subprocess.run(
['curl', '-L', '-o', wiremock_jar, wiremock_url],
check=True
)
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
# Check if port is already in use
try:
response = requests.get(f"http://localhost:{port}/__admin")
print(f"⚠️ Port {port} is already in use")
return None
except requests.exceptions.ConnectionError:
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
# Check if port is already in use
try:
response = requests.get(f"http://localhost:{port}/__admin")
print(f"⚠️ Port {port} is already in use")
return None
except requests.exceptions.ConnectionError:
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
# Check if port is already in use
try:
response = requests.get(f"http://localhost:{port}/__admin")
print(f"⚠️ Port {port} is already in use")
return None
except requests.exceptions.ConnectionError:
This process launch executes the JAR obtained earlier, so the security risk depends on the trustworthiness of jar_path and the downloaded artifact. In this script, jar_path comes from an unverified network download, making this an effective arbitrary code execution sink if the JAR is malicious or replaced locally.
# Start WireMock
try:
process = subprocess.Popen(
['java', '-jar', jar_path, '--port', str(port)],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def check_docker():
"""Check if Docker is running and accessible"""
try:
result = subprocess.run(
['docker', 'version'],
capture_output=True,
text=True
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def check_docker():
"""Check if Docker is running and accessible"""
try:
result = subprocess.run(
['docker', 'version'],
capture_output=True,
text=True
The script automatically installs Python packages at runtime via pip install without pinning versions, validating hashes, or asking for confirmation. This creates a supply-chain exposure: a compromised package, typosquatted dependency, or unexpected latest-version change could execute arbitrary code during installation under the user's account.
for package in packages:
try:
subprocess.run(
[sys.executable, '-m', 'pip', 'install', package],
check=True
)
The script persistently appends environment-variable exports to the user's ~/.bashrc, changing future shell behavior beyond the immediate test setup. Persistent profile modification is risky because it affects unrelated sessions, is hard for users to notice or revert, and here enables settings like disabling Ryuk cleanup that may leave test containers/resources behind.
The script modifies ~/.bashrc silently and without prior warning or confirmation, which is unsafe for a setup helper intended for developers. Unexpected persistence can undermine user trust, create difficult-to-trace environment changes, and in this case may globally alter container/test behavior in subsequent sessions.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"""Install LocalStack CLI"""
try:
# Check if localstack is already installed
result = subprocess.run(
['localstack', '--version'],
capture_output=True,
text=True
Automatically running pip install localstack causes the script to fetch and execute code from an external package source without user confirmation, version pinning, or integrity verification. That expands trust to the network, package index, and dependency chain, creating supply-chain and unexpected-environment-modification risk.
# Install LocalStack
print("📥 Installing LocalStack...")
try:
subprocess.run(
['pip', 'install', 'localstack'],
check=True
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
print(f" Services: {', '.join(services)}")
try:
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
Appending AWS-related environment variables to ~/.bashrc persistently changes the user's shell environment beyond the lifetime of the test session. This can misdirect future AWS CLI or SDK usage to LocalStack or test credentials, causing confusion, unintended data operations, or interference with legitimate AWS workflows.
Persistently writing AWS environment exports into ~/.bashrc without a prompt or clear warning violates the principle of least surprise and can silently alter future command behavior. Because the variables affect AWS authentication and endpoints, users may unknowingly run tools against LocalStack or with test credentials in later sessions.
The cleanup handler claims LocalStack will stop automatically but does not terminate the spawned process, which can leave a background service running unexpectedly. A lingering LocalStack instance may continue exposing local service endpoints, consume resources, and create confusion about whether test infrastructure is still active.
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.
# Upload test file
test_content = b'Hello, LocalStack S3!'
s3_client.put_object(
Bucket=bucket_name,
Key='test-file.txt',
Body=test_content
No suspicious patterns detected.