mirror of
https://github.com/actions/checkout.git
synced 2026-05-13 20:49:56 +08:00
Merge 5a3004714a into 900f2210b1
This commit is contained in:
commit
346b579c6a
|
|
@ -160,6 +160,13 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||
# running from unless specified. Example URLs are https://github.com or
|
||||
# https://my-ghes-server.example.com
|
||||
github-server-url: ''
|
||||
|
||||
# Suppress the warning when pull_request_target checks out a non-default branch
|
||||
# from the workflow repository. Only set this to true when you understand the
|
||||
# security risk of running untrusted pull request code in a privileged context.
|
||||
# https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/
|
||||
# Default: false
|
||||
dangerously-checkout-non-default-branch: ''
|
||||
```
|
||||
<!-- end usage -->
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,15 @@ describe('input-helper tests', () => {
|
|||
beforeEach(() => {
|
||||
// Reset inputs
|
||||
inputs = {}
|
||||
github.context.eventName = 'push'
|
||||
github.context.ref = 'refs/heads/some-ref'
|
||||
github.context.sha = '1234567890123456789012345678901234567890'
|
||||
github.context.payload = {
|
||||
repository: {
|
||||
default_branch: 'main'
|
||||
}
|
||||
} as any
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
|
|
@ -65,6 +74,8 @@ describe('input-helper tests', () => {
|
|||
}
|
||||
|
||||
// Restore @actions/github context
|
||||
github.context.eventName = originalContext.eventName
|
||||
github.context.payload = originalContext.payload
|
||||
github.context.ref = originalContext.ref
|
||||
github.context.sha = originalContext.sha
|
||||
|
||||
|
|
@ -150,6 +161,75 @@ describe('input-helper tests', () => {
|
|||
expect(settings.commit).toBeFalsy()
|
||||
})
|
||||
|
||||
it('warns when pull_request_target checks out a non-default branch', async () => {
|
||||
github.context.eventName = 'pull_request_target'
|
||||
inputs.ref = 'some-other-ref'
|
||||
|
||||
await inputHelper.getInputs()
|
||||
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'Checking out a non-default branch from pull_request_target'
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
it('does not warn when pull_request_target checks out the default branch name', async () => {
|
||||
github.context.eventName = 'pull_request_target'
|
||||
inputs.ref = 'main'
|
||||
|
||||
await inputHelper.getInputs()
|
||||
|
||||
expect(core.warning).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not warn when pull_request_target checks out the fully qualified default branch', async () => {
|
||||
github.context.eventName = 'pull_request_target'
|
||||
inputs.ref = 'refs/heads/main'
|
||||
|
||||
await inputHelper.getInputs()
|
||||
|
||||
expect(core.warning).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not warn when pull_request_target checks out the default branch sha', async () => {
|
||||
github.context.eventName = 'pull_request_target'
|
||||
inputs.ref = '1234567890123456789012345678901234567890'
|
||||
|
||||
await inputHelper.getInputs()
|
||||
|
||||
expect(core.warning).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not warn when dangerously-checkout-non-default-branch suppresses the warning', async () => {
|
||||
github.context.eventName = 'pull_request_target'
|
||||
inputs.ref = 'some-other-ref'
|
||||
inputs['dangerously-checkout-non-default-branch'] = 'true'
|
||||
|
||||
await inputHelper.getInputs()
|
||||
|
||||
expect(core.warning).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not warn when pull_request checks out a non-default branch', async () => {
|
||||
github.context.eventName = 'pull_request'
|
||||
inputs.ref = 'some-other-ref'
|
||||
|
||||
await inputHelper.getInputs()
|
||||
|
||||
expect(core.warning).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not warn when pull_request_target checks out a different repository', async () => {
|
||||
github.context.eventName = 'pull_request_target'
|
||||
inputs.repository = 'some-owner/some-other-repo'
|
||||
inputs.ref = 'some-other-ref'
|
||||
|
||||
await inputHelper.getInputs()
|
||||
|
||||
expect(core.warning).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('sets workflow organization ID', async () => {
|
||||
const settings: IGitSourceSettings = await inputHelper.getInputs()
|
||||
expect(settings.workflowOrganizationId).toBe(123456)
|
||||
|
|
|
|||
|
|
@ -98,6 +98,14 @@ inputs:
|
|||
github-server-url:
|
||||
description: The base URL for the GitHub instance that you are trying to clone from, will use environment defaults to fetch from the same instance that the workflow is running from unless specified. Example URLs are https://github.com or https://my-ghes-server.example.com
|
||||
required: false
|
||||
dangerously-checkout-non-default-branch:
|
||||
description: >
|
||||
Suppress the warning when pull_request_target checks out a non-default
|
||||
branch from the workflow repository. Only set this to true when you
|
||||
understand the security risk of running untrusted pull request code in a
|
||||
privileged context.
|
||||
https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/
|
||||
default: false
|
||||
outputs:
|
||||
ref:
|
||||
description: 'The branch, tag or SHA that was checked out'
|
||||
|
|
|
|||
22
dist/index.js
vendored
22
dist/index.js
vendored
|
|
@ -2008,7 +2008,8 @@ function getInputs() {
|
|||
const isWorkflowRepository = qualifiedRepository.toUpperCase() ===
|
||||
`${github.context.repo.owner}/${github.context.repo.repo}`.toUpperCase();
|
||||
// Source branch, source version
|
||||
result.ref = core.getInput('ref');
|
||||
const inputRef = core.getInput('ref');
|
||||
result.ref = inputRef;
|
||||
if (!result.ref) {
|
||||
if (isWorkflowRepository) {
|
||||
result.ref = github.context.ref;
|
||||
|
|
@ -2027,6 +2028,16 @@ function getInputs() {
|
|||
}
|
||||
core.debug(`ref = '${result.ref}'`);
|
||||
core.debug(`commit = '${result.commit}'`);
|
||||
// Warn when pull_request_target checks out non-default code from the workflow repository.
|
||||
// This event runs in the base repository context, so checking out PR-controlled code can be risky.
|
||||
const suppressNonDefaultBranchWarning = (core.getInput('dangerously-checkout-non-default-branch') || 'false').toUpperCase() === 'TRUE';
|
||||
if (github.context.eventName === 'pull_request_target' &&
|
||||
isWorkflowRepository &&
|
||||
inputRef &&
|
||||
!suppressNonDefaultBranchWarning &&
|
||||
!isDefaultBranchRef(inputRef)) {
|
||||
core.warning('Checking out a non-default branch from pull_request_target can put untrusted pull request code in a privileged context. If this is intentional, set dangerously-checkout-non-default-branch: true. Consider using pull_request or pull_request plus workflow_run instead. See https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/');
|
||||
}
|
||||
// Clean
|
||||
result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE';
|
||||
core.debug(`clean = ${result.clean}`);
|
||||
|
|
@ -2098,6 +2109,15 @@ function getInputs() {
|
|||
return result;
|
||||
});
|
||||
}
|
||||
function isDefaultBranchRef(ref) {
|
||||
var _a;
|
||||
const defaultBranch = (_a = github.context.payload.repository) === null || _a === void 0 ? void 0 : _a.default_branch;
|
||||
if (defaultBranch &&
|
||||
(ref === defaultBranch || ref === `refs/heads/${defaultBranch}`)) {
|
||||
return true;
|
||||
}
|
||||
return ref.toUpperCase() === github.context.sha.toUpperCase();
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
|||
`${github.context.repo.owner}/${github.context.repo.repo}`.toUpperCase()
|
||||
|
||||
// Source branch, source version
|
||||
result.ref = core.getInput('ref')
|
||||
const inputRef = core.getInput('ref')
|
||||
result.ref = inputRef
|
||||
if (!result.ref) {
|
||||
if (isWorkflowRepository) {
|
||||
result.ref = github.context.ref
|
||||
|
|
@ -78,6 +79,24 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
|||
core.debug(`ref = '${result.ref}'`)
|
||||
core.debug(`commit = '${result.commit}'`)
|
||||
|
||||
// Warn when pull_request_target checks out non-default code from the workflow repository.
|
||||
// This event runs in the base repository context, so checking out PR-controlled code can be risky.
|
||||
const suppressNonDefaultBranchWarning =
|
||||
(
|
||||
core.getInput('dangerously-checkout-non-default-branch') || 'false'
|
||||
).toUpperCase() === 'TRUE'
|
||||
if (
|
||||
github.context.eventName === 'pull_request_target' &&
|
||||
isWorkflowRepository &&
|
||||
inputRef &&
|
||||
!suppressNonDefaultBranchWarning &&
|
||||
!isDefaultBranchRef(inputRef)
|
||||
) {
|
||||
core.warning(
|
||||
'Checking out a non-default branch from pull_request_target can put untrusted pull request code in a privileged context. If this is intentional, set dangerously-checkout-non-default-branch: true. Consider using pull_request or pull_request plus workflow_run instead. See https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/'
|
||||
)
|
||||
}
|
||||
|
||||
// Clean
|
||||
result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE'
|
||||
core.debug(`clean = ${result.clean}`)
|
||||
|
|
@ -163,3 +182,16 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
|||
|
||||
return result
|
||||
}
|
||||
|
||||
function isDefaultBranchRef(ref: string): boolean {
|
||||
const defaultBranch = (github.context.payload.repository as any)
|
||||
?.default_branch
|
||||
if (
|
||||
defaultBranch &&
|
||||
(ref === defaultBranch || ref === `refs/heads/${defaultBranch}`)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
return ref.toUpperCase() === github.context.sha.toUpperCase()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user