Skip to content

fix(security): mitigate polynomial ReDoS in formatter and parser #252

fix(security): mitigate polynomial ReDoS in formatter and parser

fix(security): mitigate polynomial ReDoS in formatter and parser #252

name: Release Please
on:
push:
branches:
- main
workflow_dispatch:
inputs:
tag_name:
description: 'Release tag name (e.g. v1.26.0)'
required: true
concurrency:
group: release-please
cancel-in-progress: false
permissions:
contents: write
pull-requests: write
pages: write
packages: write
jobs:
release-please:
runs-on: macos-latest
outputs:
tag_name: ${{ steps.release.outputs['apps/web--tag_name'] || github.event.inputs.tag_name }}
release_created: ${{ steps.release.outputs['apps/web--release_created'] || (github.event_name == 'workflow_dispatch' && 'true') }}
steps:
- uses: googleapis/release-please-action@v4
id: release
if: ${{ github.event_name == 'push' }}
with:
token: ${{ secrets.GITHUB_TOKEN }}
# Update screenshots when a new release is created
update-screenshots:
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- uses: pnpm/action-setup@v5.0.0
- uses: actions/setup-node@v6
with:
cache: pnpm
node-version: latest
- name: Install dependencies
run: pnpm install
- name: Install Playwright browsers
run: npx playwright install chromium
- name: Generate screenshots
run: pnpm screenshot
- uses: peter-evans/create-pull-request@v8
with:
commit-message: 'chore: update screenshots for ${{ needs.release-please.outputs.tag_name }} [skip ci]'
title: 'chore: update screenshots for ${{ needs.release-please.outputs.tag_name }} [skip ci]'
body: |
Auto-generated screenshots update for ${{ needs.release-please.outputs.tag_name }}
## Desktop Screenshots
| Setup | Orchestrate |
|-------|-------------|
| ![Setup](https://raw.githubusercontent.com/${{ github.repository }}/chore/update-screenshots/docs/screenshots/pc/setup.png) | ![Orchestrate](https://raw.githubusercontent.com/${{ github.repository }}/chore/update-screenshots/docs/screenshots/pc/orchestrate.png) |
## Mobile Screenshots
| Setup | Orchestrate |
|-------|-------------|
| <img src="https://raw.githubusercontent.com/${{ github.repository }}/chore/update-screenshots/docs/screenshots/mobile/setup.png" width="300" /> | <img src="https://raw.githubusercontent.com/${{ github.repository }}/chore/update-screenshots/docs/screenshots/mobile/orchestrate.png" width="300" /> |
base: main
branch: chore/update-screenshots
delete-branch: true
add-paths: docs/screenshots/
checkout-full-src:
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
ref: ${{ needs.release-please.outputs.tag_name }}
- uses: actions/setup-go@v6
with:
go-version: '1.24'
cache: false
- run: go version
- name: Download wing vendor
run: |
git submodule update --init --recursive
export GOMODCACHE="${PWD}"/go-mod
go mod download -modcacherw
cd dae-core && go mod download -modcacherw && cd ..
find "$GOMODCACHE" -maxdepth 1 ! -name "cache" ! -name "go-mod" -exec rm -rf {} \;
sed -i 's/#export GOMODCACHE=$(PWD)\/go-mod/export GOMODCACHE=$(PWD)\/go-mod/' Makefile
working-directory: wing
- name: Create full source ZIP archive and Signature
run: |
zip -9vr daed-full-src.zip . -x .git/\*
- uses: actions/upload-artifact@v7
with:
name: daed-full-src.zip
path: daed-full-src.zip
build-web:
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- uses: pnpm/action-setup@v5.0.0
- uses: actions/setup-node@v6
with:
cache: pnpm
node-version: latest
- name: Build
env:
NODE_OPTIONS: --max-old-space-size=4096
run: |
pnpm install
pnpm build --filter daed
- uses: actions/upload-artifact@v7
with:
name: web
path: apps/web/dist
# Publish GitHub Pages when a new release is created
publish-gh-pages:
needs: [release-please, build-web]
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: macos-latest
steps:
- uses: actions/download-artifact@v8
with:
name: web
path: dist/
- uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
build-bundle:
needs: [release-please, build-web]
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
strategy:
matrix:
goos: [linux]
goarch: [386, riscv64]
include:
# BEGIN Linux ARM64
- goos: linux
goarch: arm64
# END Linux ARM64
# BEGIN Linux AMD64 v1 v2 v3
- goos: linux
goarch: amd64
goamd64: v1
- goos: linux
goarch: amd64
goamd64: v2
- goos: linux
goarch: amd64
goamd64: v3
# END Linux AMD64 v1 v2 v3
# BEGIN Linux mips
- goos: linux
goarch: mips64
cgo_enabled: 1
cc: mips64-linux-gnuabi64-gcc
- goos: linux
goarch: mips64le
cgo_enabled: 1
cc: mips64el-linux-gnuabi64-gcc
- goos: linux
goarch: mipsle
cgo_enabled: 1
cc: mipsel-linux-gnu-gcc
- goos: linux
goarch: mips
cgo_enabled: 1
cc: mips-linux-gnu-gcc
# END Linux mips
fail-fast: false
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOAMD64: ${{ matrix.goamd64 }}
CGO_ENABLED: ${{ matrix.cgo_enabled || 0 }}
CC: ${{ matrix.cc }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.release-please.outputs.tag_name }}
fetch-depth: 0
submodules: recursive
- uses: actions/setup-go@v6
with:
go-version: '1.24'
cache: false
- run: go version
- name: Get the version
id: get_version
env:
REF: ${{ needs.release-please.outputs.tag_name }}
run: |
tag=${REF}
version=${tag}
package_version="${tag:1}"
echo "VERSION=$version" >> $GITHUB_OUTPUT
echo "VERSION=$version" >> $GITHUB_ENV
echo "PACKAGE_VERSION=$package_version" >> $GITHUB_OUTPUT
echo "PACKAGE_VERSION=$package_version" >> $GITHUB_ENV
- name: Get the filename
id: get_filename
run: |
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOAMD64\"].friendlyName" -r < install/friendly-filenames.json)
echo "GOOS: $GOOS, GOARCH: $GOARCH, RELEASE_NAME: $_NAME"
echo "BUNDLE_NAME=daed-$_NAME" >> $GITHUB_OUTPUT
- name: Install mips build dependencies
if: ${{ startsWith(matrix.goarch, 'mips') }}
run: |
sudo apt-get update
sudo apt-get install -y gcc-mips64-linux-gnuabi64 gcc-mips64el-linux-gnuabi64 gcc-mips-linux-gnu gcc-mipsel-linux-gnu
- uses: actions/download-artifact@v8
with:
name: web
path: dist/
- name: make
run: |
mkdir -p ./bundled/
export VERSION=${{ steps.get_version.outputs.VERSION }}
export GOFLAGS="-trimpath -modcacherw"
export OUTPUT=bundled/${{ steps.get_filename.outputs.BUNDLE_NAME }}
make
cp ./install/daed.service ./bundled/
cp ./install/daed.desktop ./bundled/
cp -r ./install/icons/ ./bundled/
curl -L -o ./bundled/geoip.dat https://github.com/v2rayA/dist-v2ray-rules-dat/raw/master/geoip.dat
curl -L -o ./bundled/geosite.dat https://github.com/v2rayA/dist-v2ray-rules-dat/raw/master/geosite.dat
- name: Upload artifact - bundle
uses: actions/upload-artifact@v7
with:
name: ${{ steps.get_filename.outputs.BUNDLE_NAME }}
path: bundled/*
- name: Smoking test
if: matrix.goarch == 'amd64' && matrix.goamd64 == 'v1'
run: ./bundled/${{ steps.get_filename.outputs.BUNDLE_NAME }} --version
- name: Build Linux packages
run: |
mkdir -p ./output_packages/
sudo apt install -y libarchive-tools rpm
sudo gem install fpm -v 1.15.1
pushd bundled || exit 1
if [ "$GOARCH" == 'mips64' ] || [ "$GOARCH" == 'mips64le' ] || [ "$GOARCH" == 'mipsle' ] || [ "$GOARCH" == 'mips' ];then
echo "Skip pacman package build for Arch Linux has never been port to MIPS family, Debian package and RPM package are enough."
ARCH_PACMAN=''
else
ARCH_PACMAN='pacman'
fi
for package_manager in deb rpm $ARCH_PACMAN; do
if [ "$package_manager" == 'pacman' ];then
if [ "$GOARCH" == 'arm64' ];then
package_arch='aarch64'
else
package_arch="$GOARCH"
fi
elif [ "$package_manager" == 'rpm' ];then
if [ "$GOARCH" == 'arm64' ];then
package_arch='aarch64'
else
package_arch="$GOARCH"
fi
elif [ "$package_manager" == 'deb' ];then
package_arch="$GOARCH"
fi
fpm -s dir -t "$package_manager" -a $package_arch --version "$PACKAGE_VERSION" \
--url 'https://github.com/daeuniverse/daed' --description "daed, A Modern Dashboard For dae." \
--maintainer "daed@dae.v2raya.org" --name daed --license 'MIT AGPL' \
--package daed-linux-$GOARCH$GOAMD64.$package_manager \
--after-install ../install/package_after_install.sh \
--after-remove ../install/package_after_remove.sh \
./geoip.dat=/usr/share/daed/geoip.dat ./geosite.dat=/usr/share/daed/geosite.dat \
./daed.service=/usr/lib/systemd/system/daed.service \
./daed.desktop=/usr/share/applications/daed.desktop \
./icons/16x16.png=/usr/share/icons/hicolor/16x16/apps/daed.png \
./icons/32x32.png=/usr/share/icons/hicolor/32x32/apps/daed.png \
./icons/64x64.png=/usr/share/icons/hicolor/64x64/apps/daed.png \
./icons/128x128.png=/usr/share/icons/hicolor/128x128/apps/daed.png \
./icons/256x256.png=/usr/share/icons/hicolor/256x256/apps/daed.png \
./icons/512x512.png=/usr/share/icons/hicolor/512x512/apps/daed.png \
./icons/1024x1024.png=/usr/share/icons/hicolor/1024x1024/apps/daed.png \
./${{ steps.get_filename.outputs.BUNDLE_NAME }}=/usr/bin/daed
done
popd || exit 1
cp bundled/daed-linux-$GOARCH$GOAMD64.deb ./output_packages/installer-${{ steps.get_filename.outputs.BUNDLE_NAME }}.deb
cp bundled/daed-linux-$GOARCH$GOAMD64.rpm ./output_packages/installer-${{ steps.get_filename.outputs.BUNDLE_NAME }}.rpm
if [ "$ARCH_PACMAN" == 'pacman' ];then
cp bundled/daed-linux-$GOARCH$GOAMD64.pacman ./output_packages/installer-${{ steps.get_filename.outputs.BUNDLE_NAME }}.pkg.tar.zst
fi
ls ./output_packages/ | grep -E ".deb|.rpm|.pkg.tar.zst"
- if: ${{ env.GOARCH != 'mips' && env.GOARCH != 'mipsle' && env.GOARCH != 'mips64' && env.GOARCH != 'mips64le' }}
uses: nanoufo/action-upload-artifacts-and-release-assets@v2.0
with:
path: |
output_packages/*
upload-release:
needs: [release-please, checkout-full-src, build-bundle]
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- uses: actions/download-artifact@v8
with:
path: release/
- name: Prepare files for upload
run: |
set -euo pipefail
# Parallel execution helper function
# Usage: parallel_exec <function_name> <input_list>
parallel_exec() {
local func_name="$1"
shift
export -f "$func_name"
echo "$@" | tr ' ' '\n' | xargs -P 8 -I {} bash -c 'set -e; '"$func_name"' "$@"' _ {}
}
cp release/*/*.deb ./
cp release/*/*.rpm ./
cp release/*/*.pkg.tar.zst ./
cp release/*/*.zip ./
# Create zip archives in parallel
create_zip() {
local dir="$1"
zip -9r "../${dir}.zip" "$dir" && echo "✓ Created ${dir}.zip"
}
cd release
dirs=$(ls -d daed-linux* web)
parallel_exec create_zip $dirs
cd ..
# Verify all zip files
verify_zip() {
local dir="$1"
if [[ ! -f "${dir}.zip" ]]; then
echo "✗ Failed to create ${dir}.zip" && exit 1
fi
unzip -t "${dir}.zip" > /dev/null 2>&1 || { echo "✗ ${dir}.zip is corrupted"; exit 1; }
echo "✓ Verified ${dir}.zip"
}
parallel_exec verify_zip $dirs
# Generate checksums in parallel
generate_dgst() {
local package="$1"
echo "$(md5 -q "$package") $package md5" >> "$package.dgst"
echo "$(shasum -a 1 "$package") sha1" >> "$package.dgst"
echo "$(shasum -a 256 "$package") sha256" >> "$package.dgst"
echo "$(shasum -a 512 "$package") sha512" >> "$package.dgst"
echo "✓ Generated checksums for $package"
}
packages=$(ls | grep -E "\.deb$|\.pkg\.tar\.zst$|\.rpm$|\.zip$")
parallel_exec generate_dgst $packages
echo "Show files are going to upload..."
ls -lh | grep -E ".deb|.pkg.tar.zst|.rpm|.zip"
- name: Upload Release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ needs.release-please.outputs.tag_name }}
run: |
set -euo pipefail
# Parallel execution helper function
parallel_exec() {
local func_name="$1"
shift
export -f "$func_name"
echo "$@" | tr ' ' '\n' | xargs -P 8 -I {} bash -c 'set -e; '"$func_name"' "$@"' _ {}
}
upload_file() {
local file="$1"
gh release upload "$TAG_NAME" "$file" --clobber
echo "✓ Uploaded $file"
}
export TAG_NAME
files=$(ls | grep -E "\.deb$|\.pkg\.tar\.zst$|\.rpm$|\.zip$|\.dgst$")
parallel_exec upload_file $files
# Publish container image when release is created
publish-container-image:
needs: [release-please, build-web]
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
ref: ${{ needs.release-please.outputs.tag_name }}
- uses: actions/download-artifact@v8
with:
name: web
path: apps/web/dist/
- name: Prepare Tag
id: prep
env:
REF: ${{ needs.release-please.outputs.tag_name }}
run: |
tag=${REF:1}
echo "IMAGE=daeuniverse/daed" >> $GITHUB_OUTPUT
echo "TAG=$tag" >> $GITHUB_OUTPUT
- uses: docker/setup-qemu-action@v4
- uses: docker/setup-docker-action@v5
with:
daemon-config: |
{
"debug": true,
"features": {
"containerd-snapshotter": true
}
}
- uses: docker/setup-buildx-action@v4
id: buildx
- uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/login-action@v4
with:
registry: quay.io
username: ${{ github.repository_owner }}
password: ${{ secrets.QUAY_PASS }}
- uses: docker/build-push-action@v7
with:
context: .
build-args: DAED_VERSION=${{ steps.prep.outputs.TAG }}
builder: ${{ steps.buildx.outputs.name }}
file: publish.Dockerfile
target: prod
platforms: linux/386,linux/amd64,linux/arm64
push: true
load: true
tags: |
${{ github.repository }}:latest
${{ github.repository }}:${{ steps.prep.outputs.TAG }}
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ steps.prep.outputs.TAG }}
quay.io/${{ github.repository }}:latest
quay.io/${{ github.repository }}:${{ steps.prep.outputs.TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max