Skip to content

zip-dirs

A variant of zip-archive where the extraction target is a base directory plus one or more sub-path segments taken from the URL. This lets a single config serve many destinations — for example, extracting per-branch or per-environment bundles under one root without a config file per destination.

config/app-name.json:

config/app-name.json
{
"type": "ZIP_DIRS",
"apiKeys": {
"REPLACE_WITH_A_LONG_RANDOM_SECRET": "gitlab-ci"
},
"dir": "/opt/app-name",
"delete": false
}
.gitlab-ci.yml job
curl \
--data-binary @configs.zip \
--fail \
-H "api-key: $UPLOAD_KEY" \
https://dc-agent.example.com/dc-agent/zip-dirs/app-name/$CI_COMMIT_REF_NAME/config

POST /dc-agent/zip-dirs/{name}/{subdir...} — {name} selects the config file; every segment after it is appended to dir as the extraction target.

Name Description Default Required
dir Base directory; the URL sub-path is appended to it — yes
delete Mirror mode: delete files and directories under the target dir that are not in the uploaded ZIP false no
apiKeys Accepted secrets → owner labels — yes (without it every call gets 401)
type ZIP_DIRS; must match the endpoint — another type gets 401, a missing or misspelled one is accepted with a warning in the agent log — recommended

Each sub-path segment is checked against a strict whitelist (0-9 a-z A-Z . - _); any other character rejects the request, and so do the segments . and ... The resolved target must stay inside the canonical dir — a link inside dir that leads out is rejected too. Without a sub-path (/zip-dirs/{name}) the archive is extracted straight into dir.

Missing sub-directories are created only after the api-key is accepted: an unauthorized request creates nothing.

With dir = /opt/app-name and a URL of .../zip-dirs/app-name/main/config, the archive is extracted under:

/opt/app-name/main/config

Extraction is Zip-Slip guarded exactly as zip-archive. Success returns HTTP 200; an illegal segment or a traversal attempt returns an error.

By default (delete: false) files are only added or overwritten — anything already under the target directory is left untouched. Set delete: true to make the target directory exactly mirror the archive: after extracting, every file under the resolved target dir that is not in the ZIP is removed, and directories left empty by that are removed too.