1
0
Fork 0
mirror of https://code.forgejo.org/forgejo/runner.git synced 2025-09-15 18:57:01 +00:00

fix(security): ensure unique names for container images created by actions (#924)

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/924
This commit is contained in:
earl-warren 2025-09-01 12:23:26 +00:00
commit 77ea273a14
No known key found for this signature in database
GPG key ID: F128CBE6AB3A7201
11 changed files with 79 additions and 5 deletions

View file

@ -277,7 +277,6 @@ func removeGitIgnore(ctx context.Context, directory string) error {
return nil return nil
} }
// TODO: break out parts of function to reduce complexicity
func execAsDocker(ctx context.Context, step actionStep, actionName, basedir string, localAction bool) error { func execAsDocker(ctx context.Context, step actionStep, actionName, basedir string, localAction bool) error {
logger := common.Logger(ctx) logger := common.Logger(ctx)
rc := step.getRunContext() rc := step.getRunContext()
@ -291,10 +290,11 @@ func execAsDocker(ctx context.Context, step actionStep, actionName, basedir stri
// Apply forcePull only for prebuild docker images // Apply forcePull only for prebuild docker images
forcePull = rc.Config.ForcePull forcePull = rc.Config.ForcePull
} else { } else {
// "-dockeraction" enshures that "./", "./test " won't get converted to "act-:latest", "act-test-:latest" which are invalid docker image names if localAction {
image = fmt.Sprintf("%s-dockeraction:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-"), "latest") image = fmt.Sprintf("runner-local-docker-action-%s:latest", common.MustRandName(16))
image = fmt.Sprintf("act-%s", strings.TrimLeft(image, "-")) } else {
image = strings.ToLower(image) image = fmt.Sprintf("runner-remote-docker-action-%s:latest", common.Sha256(step.getStepModel().Uses))
}
contextDir, fileName := filepath.Split(filepath.Join(basedir, action.Runs.Image)) contextDir, fileName := filepath.Split(filepath.Join(basedir, action.Runs.Image))
anyArchExists, err := container.ImageExistsLocally(ctx, image, "any") anyArchExists, err := container.ImageExistsLocally(ctx, image, "any")

View file

@ -245,6 +245,8 @@ func TestRunner_RunEvent(t *testing.T) {
{workdir, "local-action-fails-schema-validation", "push", "Job 'test' failed", platforms, secrets}, {workdir, "local-action-fails-schema-validation", "push", "Job 'test' failed", platforms, secrets},
{workdir, "local-action-docker-url", "push", "", platforms, secrets}, {workdir, "local-action-docker-url", "push", "", platforms, secrets},
{workdir, "local-action-dockerfile", "push", "", platforms, secrets}, {workdir, "local-action-dockerfile", "push", "", platforms, secrets},
{workdir + "/local-action-dockerfile-tag/example1", "local-action-dockerfile-example1", "push", "", platforms, secrets},
{workdir + "/local-action-dockerfile-tag/example2", "local-action-dockerfile-example2", "push", "", platforms, secrets},
{workdir, "local-action-via-composite-dockerfile", "push", "", platforms, secrets}, {workdir, "local-action-via-composite-dockerfile", "push", "", platforms, secrets},
{workdir, "local-action-js", "push", "", platforms, secrets}, {workdir, "local-action-js", "push", "", platforms, secrets},

View file

@ -0,0 +1,4 @@
example1 and example2 eacho use a local actions that have the same
path (actions/docker-local) but do not behave the same. This verifies
that the locally built images have different names and do not collide
despite both being called with `uses: ./actions/docker-local.

View file

@ -0,0 +1,8 @@
# Container image that runs your code
FROM code.forgejo.org/oci/alpine:latest
# Copies your code file from your action repository to the filesystem path `/` of the container
COPY entrypoint.sh /entrypoint.sh
# Code file to execute when the docker container starts up (`entrypoint.sh`)
ENTRYPOINT ["/entrypoint.sh"]

View file

@ -0,0 +1,12 @@
inputs:
who-to-greet:
outputs:
whoami:
description: 'The time we greeted you'
runs:
using: 'docker'
image: 'Dockerfile'
env:
WHOAMI: ${{ inputs.who-to-greet }}
args:
- ${{ inputs.who-to-greet }}

View file

@ -0,0 +1,3 @@
#!/bin/sh
echo ::set-output "name=whoami::example1 $WHOAMI"

View file

@ -0,0 +1,11 @@
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./actions/docker-local
id: dockerlocal
with:
who-to-greet: 'SOMEONE'
- run: '[[ "${{ steps.dockerlocal.outputs.whoami }}" == "example1 SOMEONE" ]]'

View file

@ -0,0 +1,8 @@
# Container image that runs your code
FROM code.forgejo.org/oci/alpine:latest
# Copies your code file from your action repository to the filesystem path `/` of the container
COPY entrypoint.sh /entrypoint.sh
# Code file to execute when the docker container starts up (`entrypoint.sh`)
ENTRYPOINT ["/entrypoint.sh"]

View file

@ -0,0 +1,12 @@
inputs:
who-to-greet:
outputs:
whoami:
description: 'The time we greeted you'
runs:
using: 'docker'
image: 'Dockerfile'
env:
WHOAMI: ${{ inputs.who-to-greet }}
args:
- ${{ inputs.who-to-greet }}

View file

@ -0,0 +1,3 @@
#!/bin/sh
echo ::set-output "name=whoami::example2 $WHOAMI"

View file

@ -0,0 +1,11 @@
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./actions/docker-local
id: dockerlocal
with:
who-to-greet: 'SOMEONE'
- run: '[[ "${{ steps.dockerlocal.outputs.whoami }}" == "example2 SOMEONE" ]]'