# Vulnerable NGINX built from source with AddressSanitizer so the heap overflow
# in the rewrite/escape copy pass faults with an ATTRIBUTABLE backtrace.
#
# NGINX_REF selects the exact upstream tag:
#   release-1.30.0  -> last VULNERABLE release  (CVE-2026-42945, default)
#   release-1.30.1  -> first PATCHED release     (discriminator)
#
# Symbolization: built with -g -O1 -fno-omit-frame-pointer and NOT stripped, so
# ASan can name the rewrite/escape frames (ngx_escape_uri,
# ngx_http_script_copy_capture_code, ngx_http_script_regex_end_code).
FROM ubuntu:22.04

ARG NGINX_REF=release-1.30.0
ARG NGINX_COMMIT_EXPECTED

ENV DEBIAN_FRONTEND=noninteractive

# Build toolchain + nginx dependencies. ASan ships with gcc (libasan).
# llvm-symbolizer/binutils help ASan resolve frames to function names.
RUN apt-get update && apt-get install -y --no-install-recommends \
        ca-certificates \
        git \
        gcc \
        make \
        binutils \
        libpcre3-dev \
        zlib1g-dev \
        libssl-dev \
        procps \
        curl \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /build

# Clone the exact upstream tag. Source stays UNMODIFIED (no patching).
RUN git clone --depth 1 --branch "${NGINX_REF}" https://github.com/nginx/nginx.git src \
    && cd src \
    && echo "checked out: $(git rev-parse HEAD)" \
    && if [ -n "${NGINX_COMMIT_EXPECTED}" ] && [ "$(git rev-parse HEAD)" != "${NGINX_COMMIT_EXPECTED}" ]; then \
         echo "COMMIT MISMATCH: got $(git rev-parse HEAD) want ${NGINX_COMMIT_EXPECTED}" >&2; exit 1; \
       fi \
    # Prove source is pristine: working tree must be clean.
    && test -z "$(git status --porcelain)" || (echo "SOURCE NOT PRISTINE" >&2; git status --porcelain; exit 1)

# Configure + build with AddressSanitizer instrumentation.
# The rewrite module is built by default whenever PCRE is found (libpcre3-dev).
# -fno-omit-frame-pointer + -g keep the backtrace readable; -O1 keeps frames.
RUN cd src \
    && ./auto/configure \
        --prefix=/usr/local/nginx \
        --with-cc-opt="-fsanitize=address -fno-omit-frame-pointer -g -O1" \
        --with-ld-opt="-fsanitize=address" \
    && make -j"$(nproc)" \
    && make install \
    && ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx \
    # Record the built version + tag for the version-pin check.
    && /usr/local/nginx/sbin/nginx -v 2>/tmp/nginx-version.txt; cat /tmp/nginx-version.txt \
    && cp /tmp/nginx-version.txt /usr/local/nginx/nginx-version.txt \
    && git -C /build/src rev-parse HEAD > /usr/local/nginx/nginx-commit.txt

# Vulnerable config: the required two-directive location shape.
COPY config/nginx.conf /usr/local/nginx/conf/nginx.conf
COPY config/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh \
    && mkdir -p /usr/local/nginx/logs \
    # FIX (recovery): the worker drops to the unprivileged 'nobody' user. Make
    # the nginx logs dir writable by that worker so ASan can also drop its
    # report there if it ever uses that path; the primary ASan log_path is /tmp
    # (1777) which the worker can always write. Without this the prior run hit
    # EACCES on logs/asan.log.<pid> and ASan aborted WITHOUT dumping the
    # backtrace anywhere, losing the criterion's strongest channel.
    && chown -R nobody:nogroup /usr/local/nginx/logs \
    && chmod 0777 /usr/local/nginx/logs

EXPOSE 80
ENTRYPOINT ["/entrypoint.sh"]
