Angular CLI can copy files from outside the workspace root through symlinked asset directories
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 52/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- angular, typescript
- Lĩnh vực
- build-system, cli, security
Hướng nghiên cứu
Start by reproducing the six-command example with Angular CLI 22.2.0, then inspect the application builder's asset handling and schema.json, including the schema registry's Ajv setup. Check how symlinked asset directories and the followSymlinks option are passed to globbing. Done means the documented default prevents copying files outside the workspace while explicitly configured behavior remains covered by tests.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Command
build
Is this a regression?
- Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
No response
Description
ng build can copy files from outside the workspace into the build output when an asset directory is a symbolic link.
The application builder checks that every asset path stays inside the workspace root before globbing it:
if (!isSubDirectory(root, entry.input)) {
throw new Error(`The ${entry.input} asset path must be within the workspace root.`);
}
const cwd = path.resolve(root, entry.input);
const files = await glob(entry.glob, {
cwd,
dot: true,
ignore: entry.ignore ? defaultIgnore.concat(entry.ignore) : defaultIgnore,
followSymbolicLinks: entry.followSymlinks,
});
That check is lexical. isSubDirectory() resolves both operands with resolve(), compares them with relative(), and never calls realpath:
function isSubDirectory(parent, child) {
const resolvedParent = resolve(parent);
const resolvedChild = resolve(parent, child);
const relativePath = toPosixPath(relative(resolvedParent, resolvedChild));
return relativePath !== '..' && !relativePath.startsWith('../') && !isAbsolute(relativePath);
}
A symlink inside the project resolves inside the workspace root, passes the check, and is then used as the globber's cwd, which reads through it to the real target.
Whether the globber walks through it depends on followSymlinks, and the value that arrives there is not the documented one. schema.json declares:
"followSymlinks": {
"type": "boolean",
"default": false,
"description": "Allow glob patterns to follow symlink directories. This allows subdirectories of the symlink to be searched."
}
The schema registry builds Ajv without useDefaults:
this._ajv = new ajv.default({
strict: false,
loadSchema: (uri) => this._fetch(uri),
passContext: true,
verbose: true,
});
so schema defaults are never written into the options object. When the option is not set, entry.followSymlinks is undefined, and tinyglobby treats undefined the same as true:
followSymbolicLinks: undefined -> [ 'link/secret.txt' ]
followSymbolicLinks: false -> [ ]
followSymbolicLinks: true -> [ 'link/secret.txt' ]
The documented default is false. The effective default is true.
The containment check does hold for the direct form, which is what shows it is meant to hold:
assets: [{ "glob": "**/*", "input": "../../../outside" }]
An unhandled exception occurred: The ../../../outside asset path must be within the workspace root.
The same target reached through a symlink is copied with no warning and a successful build.
The configuration ng new generates already globs the whole public/ directory, so angular.json does not need to change:
"assets": [{ "glob": "**/*", "input": "public" }]
A symbolic link is a git object of mode 120000 whose content is a path string, so it survives clone. Nothing is executed during the build, so npm ci --ignore-scripts does not change the outcome.
Minimal Reproduction
See https://github.com/SkyZeroZx/angular-cli-symlink-asset-escape-poc
The same thing reproduces on a stock application in six commands:
npx @angular/[email protected] new repro-app --defaults --skip-git
cd repro-app
mkdir -p /tmp/outside-the-workspace
echo "this file is outside the Angular workspace" > /tmp/outside-the-workspace/secret.txt
ln -s /tmp/outside-the-workspace public/docs
ng build
find dist -name 'secret.txt'
The build completes normally and the file from outside the workspace is in the output:
dist/repro-app/browser/docs/secret.txt
Setting the option to the value the schema already documents as its default stops it:
assets: [{ "glob": "**/*", "input": "public", "followSymlinks": false }]
Exception or Error
Your Environment
Angular CLI 22.2.0
@angular/build 22.2.0
Node.js 24.21.0
npm 10.9.7
Linux x64
tinyglobby 0.2.17
Anything else relevant?
The symlink target can be an absolute path or a relative one such as ../../../.., so it does not need to know the layout of the machine that runs the build.
- Ngôn ngữ chính
- TypeScript
- Star
- 27k
- Fork
- 11.8k
- Merge trung bình
- 21 giờ 48 phút
- Pull request đã merge (30 ngày)
- 164
Chuẩn bị môi trường
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 angular/angular-cli
-
Can't use an array of hostnames in --allowedHosts cli parameter in @angular/build:dev-serverĐang mởarea: @angular/build gemini-triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
angular/angular-cli#33955 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area: @angular/cli gemini-triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
angular/angular-cli#33055 · 1 bình luận · 3 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area: @angular/build gemini-triaged
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 70/100
angular/angular-cli#34185 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area: @angular/build gemini-triaged
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
angular/angular-cli#34166 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
library builder: tslib is not added to the output package.jsonCó thể đã có người làm @alan-agius4 đã nhận 7 ngày trước. Đang mởangular/build:library area: @angular/build gemini-triaged
angular/angular-cli#34131 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của angular/angular-cli
Issue tương tự
-
bug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
StabilityNexus/Fate-EVM-Frontend#153 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
code-yeongyu/oh-my-openagent#9039 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Tencent/teamai-cli#862 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug good first issue hacktoberfest redis
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
libredb/libredb-studio#1164 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
flake
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
coder/xum#4920 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày