Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions .github/workflows/Dockerfile.alpine-php-test-nts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# syntax=docker/dockerfile:1.7
# Alpine test image with PHP built from source in NTS mode
# Used for testing the extension on musl-based systems

ARG PHP_VERSION=8.3
ARG PHP_SRC_REF=PHP-${PHP_VERSION}

FROM alpine:3.21 AS base
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]

ENV TZ=Etc/UTC \
LC_ALL=C.UTF-8 \
LANG=C.UTF-8 \
PHP_VERSION=${PHP_VERSION}

RUN apk add --no-cache \
bash curl git wget make gcc g++ autoconf bison re2c pkgconf \
libxml2-dev sqlite-dev curl-dev openssl-dev \
libzip-dev oniguruma-dev libjpeg-turbo-dev libpng-dev libwebp-dev \
icu-dev readline-dev libxslt-dev mariadb-connector-c-dev \
linux-headers xz tar ca-certificates \
nginx mariadb mariadb-client \
python3 py3-pip py3-flask py3-requests py3-psutil \
procps

FROM base AS php-build
ARG PHP_SRC_REF
WORKDIR /usr/src
RUN git clone --depth 1 --branch "${PHP_SRC_REF}" https://github.com/php/php-src.git
WORKDIR /usr/src/php-src

RUN sed -i 's/\[\([0-9]\+\.[0-9]\+\.[0-9]\+\)-dev\]/[\1]/' configure.ac
RUN ./buildconf --force

RUN mkdir -p /usr/local/etc/php/conf.d

RUN ./configure \
--prefix=/usr/local \
--with-config-file-path=/usr/local/lib \
--with-config-file-scan-dir=/usr/local/etc/php/conf.d \
--enable-fpm \
--enable-mbstring \
--enable-pcntl \
--enable-cgi \
--with-extra-version="" \
--with-curl \
--with-mysqli \
--with-openssl \
--with-zlib \
--with-zip \
--disable-zts \
&& make -j"$(nproc)" \
&& make install \
&& strip /usr/local/bin/php /usr/local/sbin/php-fpm || true

FROM base AS final
COPY --from=php-build /usr/local /usr/local

RUN EXTENSION_DIR=$(php -i | grep "^extension_dir" | awk '{print $3}') && \
if [ -z "$EXTENSION_DIR" ]; then \
echo "Error: Could not determine extension_dir"; \
exit 1; \
fi && \
mkdir -p "$EXTENSION_DIR"

RUN php -v | grep -v "ZTS" >/dev/null || (echo "ERROR: ZTS is enabled but should be NTS!" && exit 1) && \
Copy link
Copy Markdown
Contributor

@aikido-pr-checks aikido-pr-checks Bot Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ZTS guard uses php -v | grep -v "ZTS", which can still succeed when ZTS is enabled because other php -v lines don’t contain "ZTS", so the error branch may never run.

Suggested change
RUN php -v | grep -v "ZTS" >/dev/null || (echo "ERROR: ZTS is enabled but should be NTS!" && exit 1) && \
RUN php -v | grep "ZTS" >/dev/null && (echo "ERROR: ZTS is enabled but should be NTS!" && exit 1) || true && \
php -v | grep -v "ZTS" >/dev/null && \
Details

✨ AI Reasoning
​​1) The block is trying to fail the image build if PHP was compiled with ZTS.
2) It uses php -v | grep -v "ZTS" >/dev/null to decide success.
3) php -v outputs multiple lines; even if the version line contains "ZTS", other lines typically do not, so grep -v "ZTS" still outputs something and exits 0.
4) This means the code can silently pass the ZTS check when ZTS is enabled, contradicting the intended control-flow guard.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

php -m | grep -E 'curl|mysqli' >/dev/null

ENV PATH="/usr/local/bin:${PATH}"

RUN ln -sf /usr/local/bin/php /usr/bin/php && \
ln -sf /usr/local/sbin/php-fpm /usr/sbin/php-fpm || true && \
ln -sf /usr/local/bin/php-cgi /usr/bin/php-cgi

# Create /etc/httpd so the test harness uses the CentOS-style php-fpm config path
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RUN starting at line 75 chains many filesystem modifications, config writes, php-fpm tests, and symlink commands with &&/||. Split into smaller RUN steps to improve readability and isolate failures.

Details

✨ AI Reasoning
​A single RUN line performs many file system creations, symlink operations, multiple echo redirects to create config, php-fpm tests and an mv — all chained with many && and ||. This combines many distinct side-effecting steps into one line, increasing cognitive load and hiding failures in complex chaining.

🔧 How do I fix it?
Break long lines to enhance clarity. Aim for a maximum of 80-120 characters per line, depending on the context and coding standards.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

RUN mkdir -p /etc/httpd && \
mkdir -p /etc/php-fpm.d && \
mkdir -p /run/php-fpm && \
mkdir -p /var/run && \
mkdir -p /var/log/php-fpm && \
mkdir -p /usr/local/etc/php-fpm.d && \
mkdir -p /usr/local/etc/php/conf.d && \
ln -sf /usr/local/etc/php/conf.d /etc/php.d || true && \
echo "[global]" > /usr/local/etc/php-fpm.conf && \
echo "pid = /run/php-fpm/php-fpm.pid" >> /usr/local/etc/php-fpm.conf && \
echo "error_log = /var/log/php-fpm/error.log" >> /usr/local/etc/php-fpm.conf && \
echo "daemonize = yes" >> /usr/local/etc/php-fpm.conf && \
echo "include=/usr/local/etc/php-fpm.d/*.conf" >> /usr/local/etc/php-fpm.conf && \
echo "include=/etc/php-fpm.d/*.conf" >> /usr/local/etc/php-fpm.conf && \
echo "[www]" > /usr/local/etc/php-fpm.d/www.conf && \
echo "user = root" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "group = root" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "listen = 127.0.0.1:9000" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "listen.owner = root" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "listen.group = root" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "pm = dynamic" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "pm.max_children = 5" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "pm.start_servers = 2" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "pm.min_spare_servers = 1" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "pm.max_spare_servers = 3" >> /usr/local/etc/php-fpm.d/www.conf && \
php-fpm -t -y /usr/local/etc/php-fpm.conf 2>&1 | grep -v "Nothing matches the include pattern" || true && \
php-fpm -t -y /usr/local/etc/php-fpm.conf >/dev/null 2>&1 || \
(echo "PHP-FPM config test failed" && exit 1) && \
ln -sf /usr/local/etc/php-fpm.conf /etc/php-fpm.conf

# Configure nginx to include /etc/nginx/conf.d/ (expected by test harness)
RUN mkdir -p /etc/nginx/conf.d && \
awk '/include.*http\.d/{print; print " include /etc/nginx/conf.d/*.conf;"; next}1' \
/etc/nginx/nginx.conf > /tmp/nginx.conf && \
mv /tmp/nginx.conf /etc/nginx/nginx.conf

# MySQL socket path for mysqli
RUN echo "mysqli.default_socket = /var/lib/mysql/mysql.sock" > /usr/local/etc/php/conf.d/mysql-socket.ini

# MariaDB helper script
RUN mkdir -p /usr/local/bin /var/lib/mysql /run/mysqld && \
printf '%s\n' \
'#!/bin/sh' \
'set -e' \
'mkdir -p /var/lib/mysql /run/mysqld' \
'chown -R mysql:mysql /var/lib/mysql /run/mysqld' \
'if [ ! -d /var/lib/mysql/mysql ]; then' \
' mysql_install_db --user=mysql --datadir=/var/lib/mysql' \
'fi' \
'mysqld --user=mysql --datadir=/var/lib/mysql --socket=/var/lib/mysql/mysql.sock &' \
'pid=$!' \
'for i in $(seq 1 30); do mysqladmin --socket=/var/lib/mysql/mysql.sock ping --silent 2>/dev/null && break; sleep 1; done' \
'mysql --socket=/var/lib/mysql/mysql.sock -u root -e "CREATE DATABASE IF NOT EXISTS db;" || true' \
'mysql --socket=/var/lib/mysql/mysql.sock -u root -e "ALTER USER '"'"'root'"'"'@'"'"'localhost'"'"' IDENTIFIED BY '"'"'pwd'"'"'; FLUSH PRIVILEGES;" || true' \
'wait $pid' \
> /usr/local/bin/start-mariadb && \
chmod +x /usr/local/bin/start-mariadb

WORKDIR /work
CMD ["bash"]
53 changes: 53 additions & 0 deletions .github/workflows/Dockerfile.build-extension-alpine-nts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# syntax=docker/dockerfile:1.7
# Alpine image with PHP built from source in NTS mode
# Used for building the PHP extension on musl-based systems

ARG PHP_VERSION=8.3
ARG PHP_SRC_REF=PHP-${PHP_VERSION}

FROM alpine:3.21 AS base
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]

ENV TZ=Etc/UTC \
LC_ALL=C.UTF-8 \
LANG=C.UTF-8

RUN apk add --no-cache \
bash curl git wget make gcc g++ autoconf bison re2c pkgconf \
libxml2-dev sqlite-dev curl-dev openssl-dev \
libzip-dev oniguruma-dev libjpeg-turbo-dev libpng-dev libwebp-dev \
icu-dev readline-dev libxslt-dev mariadb-connector-c-dev \
linux-headers xz tar ca-certificates

FROM base AS php-src
ARG PHP_SRC_REF
WORKDIR /usr/src
RUN git clone --depth 1 --branch "${PHP_SRC_REF}" https://github.com/php/php-src.git
WORKDIR /usr/src/php-src
RUN ./buildconf --force

FROM php-src AS php-build
RUN ./configure \
--prefix=/usr/local \
--with-config-file-path=/usr/local/lib \
--with-config-file-scan-dir=/usr/local/etc/php/conf.d \
--enable-mbstring \
--enable-pcntl \
--enable-intl \
--with-curl \
--with-mysqli \
--with-openssl \
--with-zlib \
--with-zip \
&& make -j"$(nproc)" \
&& make install \
&& strip /usr/local/bin/php || true

FROM base AS dev
COPY --from=php-build /usr/local /usr/local
RUN php -v && php -m | grep -E 'curl|mysqli' >/dev/null
ENV PATH="/usr/local/bin:${PATH}"

RUN mkdir -p /usr/local/etc/php/conf.d
WORKDIR /work
CMD ["php", "-v"]
29 changes: 29 additions & 0 deletions .github/workflows/Dockerfile.build-libs-alpine
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Alpine-based image for building Go shared libraries with custom Go fork
# that supports c-shared buildmode on musl-based systems.
FROM alpine:3.21

ARG GO_RELEASE_TAG=devel-go1.27-tlsdesc.1

RUN apk add --no-cache \
bash curl git make gcc g++ musl-dev \
protobuf protobuf-dev

RUN ARCH=$(uname -m) && \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RUN at line 11 combines architecture detection, conditional assignment, download, extraction and cleanup. Break into separate steps (detect/assign, download, extract, cleanup) for clarity and easier failure diagnosis.

Details

✨ AI Reasoning
​The RUN at line 11 contains shell architecture detection with if/elif, variable assignment, a curl download, tar extraction and cleanup — all in one line. It mixes control flow and multiple IO operations making it hard to reason about and debug.

🔧 How do I fix it?
Break long lines to enhance clarity. Aim for a maximum of 80-120 characters per line, depending on the context and coding standards.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

if [ "$ARCH" = "x86_64" ]; then GO_ARCH="amd64"; \
elif [ "$ARCH" = "aarch64" ]; then GO_ARCH="arm64"; fi && \
curl -fsSL -o /tmp/go.tar.gz \
"https://github.com/AikidoSec/go/releases/download/${GO_RELEASE_TAG}/${GO_RELEASE_TAG}.linux-${GO_ARCH}.tar.gz" && \
tar -C /usr/local -xzf /tmp/go.tar.gz && \
rm /tmp/go.tar.gz

ENV PATH="/usr/local/go/bin:${PATH}"
ENV GOPATH="/go"
ENV GOBIN="/go/bin"
ENV PATH="${GOBIN}:${PATH}"

RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

WORKDIR /workspace

CMD ["/bin/bash"]
90 changes: 90 additions & 0 deletions .github/workflows/build-alpine-php-test-images-nts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Build Alpine PHP test images (NTS)

on:
workflow_dispatch:
push:
paths:
- .github/workflows/Dockerfile.alpine-php-test-nts
- .github/workflows/build-alpine-php-test-images-nts.yml

env:
REGISTRY: ghcr.io
IMAGE_NAME: aikidosec/firewall-php-test-alpine-nts
VERSION: v1

jobs:
build-amd64:
runs-on: ubuntu-24.04
strategy:
matrix:
php_version: ['7.4','8.0','8.1','8.2','8.3','8.4','8.5']
fail-fast: false
permissions: { contents: read, packages: write }
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build & push (amd64)
uses: docker/build-push-action@v6
with:
context: .
file: .github/workflows/Dockerfile.alpine-php-test-nts
platforms: linux/amd64
push: true
build-args: |
PHP_VERSION=${{ matrix.php_version }}
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ matrix.php_version }}-amd64-${{ env.VERSION }}

build-arm64:
runs-on: ubuntu-24.04-arm
strategy:
matrix:
php_version: ['7.4','8.0','8.1','8.2','8.3','8.4','8.5']
fail-fast: false
permissions: { contents: read, packages: write }
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build & push (arm64)
uses: docker/build-push-action@v6
with:
context: .
file: .github/workflows/Dockerfile.alpine-php-test-nts
platforms: linux/arm64
push: true
build-args: |
PHP_VERSION=${{ matrix.php_version }}
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ matrix.php_version }}-arm64-${{ env.VERSION }}

publish-manifests:
runs-on: ubuntu-24.04
needs: [build-amd64, build-arm64]
strategy:
matrix:
php_version: ['7.4','8.0','8.1','8.2','8.3','8.4','8.5']
fail-fast: false
permissions: { contents: read, packages: write }
steps:
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create multi-arch manifest
run: |
IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
V=${{ matrix.php_version }}
docker buildx imagetools create \
--tag ${IMAGE}:${V}-${{ env.VERSION }} \
${IMAGE}:${V}-amd64-${{ env.VERSION }} \
${IMAGE}:${V}-arm64-${{ env.VERSION }}
Loading
Loading