Compare commits

..

No commits in common. "9087f1e6d666fe0292409e3c819680c18526e108" and "371161bbe7024a29a25c5e19bfcbc0804fe9ad2c" have entirely different histories.

9 changed files with 128 additions and 241 deletions

View File

@ -228,7 +228,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- -
name: Configure AWS Credentials name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with: with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@ -256,7 +256,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- -
name: Configure AWS Credentials name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with: with:
role-to-assume: arn:aws:iam::175142243308:role/official_gha_cicd_login_action role-to-assume: arn:aws:iam::175142243308:role/official_gha_cicd_login_action
aws-region: us-east-1 aws-region: us-east-1
@ -303,7 +303,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- -
name: Configure AWS Credentials name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with: with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@ -332,7 +332,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- -
name: Configure AWS Credentials name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3 uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with: with:
role-to-assume: arn:aws:iam::175142243308:role/official_gha_cicd_login_action role-to-assume: arn:aws:iam::175142243308:role/official_gha_cicd_login_action
aws-region: us-east-1 aws-region: us-east-1

View File

@ -35,12 +35,12 @@ jobs:
node-version: ${{ env.NODE_VERSION }} node-version: ${{ env.NODE_VERSION }}
- -
name: Initialize CodeQL name: Initialize CodeQL
uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 uses: github/codeql-action/init@e0647621c2984b5ed2f768cb892365bf2a616ad1 # v4.37.2
with: with:
languages: javascript-typescript languages: javascript-typescript
build-mode: none build-mode: none
- -
name: Perform CodeQL Analysis name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 uses: github/codeql-action/analyze@e0647621c2984b5ed2f768cb892365bf2a616ad1 # v4.37.2
with: with:
category: "/language:javascript-typescript" category: "/language:javascript-typescript"

View File

@ -35,87 +35,6 @@ test('getAuthList uses the default Docker Hub registry when computing scoped con
}); });
}); });
test('getAuthList supports @ scopes appended to the registry config dir', async () => {
process.env['INPUT_USERNAME'] = 'dbowie';
process.env['INPUT_PASSWORD'] = 'groundcontrol';
process.env['INPUT_SCOPE'] = '@push';
process.env['INPUT_LOGOUT'] = 'false';
const [auth] = getAuthList(getInputs());
expect(auth).toMatchObject({
configDir: path.join(Buildx.configDir, 'config', 'registry-1.docker.io') + '@push'
});
});
test('getAuthList supports repository scopes with appended actions', async () => {
process.env['INPUT_USERNAME'] = 'dbowie';
process.env['INPUT_PASSWORD'] = 'groundcontrol';
process.env['INPUT_SCOPE'] = 'docker/buildx-bin@push';
process.env['INPUT_LOGOUT'] = 'false';
const [auth] = getAuthList(getInputs());
expect(auth).toMatchObject({
configDir: path.join(Buildx.configDir, 'config', 'registry-1.docker.io', 'docker', 'buildx-bin@push')
});
});
test('getAuthList supports comma-separated scope actions', async () => {
process.env['INPUT_USERNAME'] = 'dbowie';
process.env['INPUT_PASSWORD'] = 'groundcontrol';
process.env['INPUT_SCOPE'] = 'docker/buildx-bin@pull,push';
process.env['INPUT_LOGOUT'] = 'false';
const [auth] = getAuthList(getInputs());
expect(auth).toMatchObject({
configDir: path.join(Buildx.configDir, 'config', 'registry-1.docker.io', 'docker', 'buildx-bin@pull,push')
});
});
// prettier-ignore
test.each([
'../../../../work/leaked',
'..',
'foo/../../../../etc',
'@../../../leaked',
'foo/bar@../../../leaked',
'@push@pull',
'foo/bar@push@pull',
'@push,',
'@,push',
'@pull,,push',
'@Push',
path.join(path.parse(Buildx.configDir).root, 'work', 'leaked')
])('getAuthList rejects unsafe or unsupported scope path: %s', async scope => {
expect(() => {
getAuthList({
registry: '',
username: 'dbowie',
password: 'groundcontrol',
scope,
ecr: '',
logout: false,
registryAuth: ''
});
}).toThrow(/Invalid scope/);
});
// prettier-ignore
test.each([
'../../../../work/leaked',
'..',
'foo/../../../../etc',
path.join(path.parse(Buildx.configDir).root, 'work', 'leaked')
])('getAuthList rejects unsafe registry path: %s', async registry => {
expect(() => {
getAuthList({
registry,
username: 'dbowie',
password: 'groundcontrol',
scope: '@push',
ecr: '',
logout: false,
registryAuth: ''
});
}).toThrow(/Invalid registry/);
});
test('getAuthList skips secret masking when registry-auth password is absent', async () => { test('getAuthList skips secret masking when registry-auth password is absent', async () => {
const stdoutWriteSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true); const stdoutWriteSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
const [auth] = getAuthList({ const [auth] = getAuthList({

202
dist/index.cjs generated vendored

File diff suppressed because one or more lines are too long

6
dist/index.cjs.map generated vendored

File diff suppressed because one or more lines are too long

5
dist/licenses.txt generated vendored
View File

@ -2396,12 +2396,11 @@ SOFTWARE.
----------- -----------
The following npm packages may be included in this product: The following npm package may be included in this product:
- js-yaml@5.2.1 - js-yaml@5.2.1
- js-yaml@5.2.2
These packages each contain the following license: This package contains the following license:
(The MIT License) (The MIT License)

View File

@ -30,7 +30,7 @@
"@docker/actions-toolkit": "^0.94.0", "@docker/actions-toolkit": "^0.94.0",
"http-proxy-agent": "^9.1.0", "http-proxy-agent": "^9.1.0",
"https-proxy-agent": "^9.1.0", "https-proxy-agent": "^9.1.0",
"js-yaml": "^5.2.2", "js-yaml": "^5.2.1",
"uuid": "^14.0.1" "uuid": "^14.0.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -77,33 +77,13 @@ export function scopeToConfigDir(registry: string, scope?: string): string {
if (scopeDisabled() || !scope || scope === '') { if (scopeDisabled() || !scope || scope === '') {
return ''; return '';
} }
const configRoot = path.resolve(Buildx.configDir, 'config'); let configDir = path.join(Buildx.configDir, 'config', registry === 'docker.io' ? 'registry-1.docker.io' : registry);
const registryDir = path.resolve(configRoot, registry === 'docker.io' ? 'registry-1.docker.io' : registry); if (scope.startsWith('@')) {
if (!isChildPath(configRoot, registryDir)) { configDir += scope;
throw new Error(`Invalid registry '${registry}': resolved config path escapes the Buildx config directory`); } else {
configDir = path.join(configDir, scope);
} }
const scopeParts = scope.split('@'); return configDir;
if (scopeParts.length > 2) {
throw new Error(`Invalid scope '${scope}': scope can contain at most one @ separator`);
}
const [scopePath, scopeActions] = scopeParts;
if (scopeActions !== undefined && !/^[a-z]+(,[a-z]+)*$/.test(scopeActions)) {
throw new Error(`Invalid scope '${scope}': scope actions must be lowercase names separated by commas`);
}
const scopeSuffix = scopeActions === undefined ? '' : `@${scopeActions}`;
if (scopePath === '') {
return `${registryDir}${scopeSuffix}`;
}
const configDir = path.resolve(registryDir, scopePath);
if (!isChildPath(registryDir, configDir)) {
throw new Error(`Invalid scope '${scope}': resolved config path escapes the Buildx config directory`);
}
return `${configDir}${scopeSuffix}`;
}
function isChildPath(parent: string, child: string): boolean {
const relativePath = path.relative(parent, child);
return relativePath !== '' && relativePath !== '..' && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath);
} }
function scopeDisabled(): boolean { function scopeDisabled(): boolean {

View File

@ -3174,7 +3174,7 @@ __metadata:
globals: "npm:^17.3.0" globals: "npm:^17.3.0"
http-proxy-agent: "npm:^9.1.0" http-proxy-agent: "npm:^9.1.0"
https-proxy-agent: "npm:^9.1.0" https-proxy-agent: "npm:^9.1.0"
js-yaml: "npm:^5.2.2" js-yaml: "npm:^5.2.1"
prettier: "npm:^3.8.1" prettier: "npm:^3.8.1"
typescript: "npm:^5.9.3" typescript: "npm:^5.9.3"
uuid: "npm:^14.0.1" uuid: "npm:^14.0.1"
@ -4357,17 +4357,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"js-yaml@npm:^5.2.2":
version: 5.2.2
resolution: "js-yaml@npm:5.2.2"
dependencies:
argparse: "npm:^2.0.1"
bin:
js-yaml: bin/js-yaml.mjs
checksum: 10/2b4c2933af12c97e1c4894a4f27fe9b06dab70a64a96bb50624b4429bef6bf11008bde20d868bce52a36784473314efc30078ba6025b58cf7537961e23b1ae9c
languageName: node
linkType: hard
"jsbn@npm:1.1.0": "jsbn@npm:1.1.0":
version: 1.1.0 version: 1.1.0
resolution: "jsbn@npm:1.1.0" resolution: "jsbn@npm:1.1.0"
@ -4864,12 +4853,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"nanoid@npm:^3.3.16": "nanoid@npm:^3.3.11":
version: 3.3.16 version: 3.3.11
resolution: "nanoid@npm:3.3.16" resolution: "nanoid@npm:3.3.11"
bin: bin:
nanoid: bin/nanoid.cjs nanoid: bin/nanoid.cjs
checksum: 10/8004af92b5541af1dbd23b69845b5026f777d5b7ef07163cea1837aae86e052ced8b383cecbf8a4f1b5e77ae207df96dc45e16b9e0fa3c4b761d085f1e42851b checksum: 10/73b5afe5975a307aaa3c95dfe3334c52cdf9ae71518176895229b8d65ab0d1c0417dd081426134eb7571c055720428ea5d57c645138161e7d10df80815527c48
languageName: node languageName: node
linkType: hard linkType: hard
@ -5292,13 +5281,13 @@ __metadata:
linkType: hard linkType: hard
"postcss@npm:^8.5.6": "postcss@npm:^8.5.6":
version: 8.5.22 version: 8.5.10
resolution: "postcss@npm:8.5.22" resolution: "postcss@npm:8.5.10"
dependencies: dependencies:
nanoid: "npm:^3.3.16" nanoid: "npm:^3.3.11"
picocolors: "npm:^1.1.1" picocolors: "npm:^1.1.1"
source-map-js: "npm:^1.2.1" source-map-js: "npm:^1.2.1"
checksum: 10/7944444f267f2d94c7caeed66f3da56d5b947bd4a7e57a166a5161af25c6006dd73f40e2a1a6822f3d7fccc2fa005778c03058368eb7efca1b5038aec55abd14 checksum: 10/7eac6169e535b63c8412e94d4f6047fc23efa3e9dde804b541940043c831b25f1cd867d83cd2c4371ad2450c8abcb42c208aa25668c1f0f3650d7f72faf711a8
languageName: node languageName: node
linkType: hard linkType: hard