A security advisory tells me that a version has a problem. It does not tell me which of my projects installed that version, built with it, or still runs it.

That gap was the starting point for my October 23 security review. I wanted a checklist broad enough to cover the projects, then evidence for each result. A list of alarming headlines would not answer the useful question: what needs attention here?

The first pass covered repository inventory, official advisory checks, and selected source and configuration review. Production verification is a separate part of the work. This post describes the method and the limits of the evidence, without publishing sensitive project details.

Start with the thing that actually runs

A repository is a convenient unit to list. It is a poor substitute for a service inventory.

One repository can contain several applications. A fork may be an experiment that never deployed. A static site can use a vulnerable runtime during its build even though the public site serves only HTML. A worker can depend on a managed runtime that its package manifest does not describe.

For each project, the useful chain is:

  1. Find the repository and the revision being reviewed.
  2. Identify its applications, manifests, lockfiles, build jobs, and deployment configuration.
  3. Map those applications to their deployed services.
  4. Identify the build image and the runtime actually in use.
  5. Match the relevant advisory to those versions and configurations.
  6. Verify the result after any patch and deployment.

Stopping at step two can still produce useful findings. The report needs to say where it stopped.

Keep the evidence level beside the finding

I separate the claim from the evidence that supports it.

  • An advisory confirms what the vendor says is affected.
  • A source file confirms what the reviewed revision declares or implements.
  • A lockfile gives evidence about resolved dependencies for that revision.
  • A build record shows what a particular build used.
  • A deployment record and runtime check show what reached a service.
  • A controlled test can verify a specific security property in that environment.

These answer different questions. A patched lockfile does not prove the patched build deployed. A successful build does not prove that session revocation works. A route that returns 401 without credentials has not yet passed a cross-account authorization test.

I also keep uncertainty visible. A control can be present in source while its production configuration remains unknown. A test that could not run remains untested. It does not become a pass because the review found nothing obvious.

The October advisories changed what needed checking

The following examples were checked against their linked sources on October 23, 2026. They are a dated snapshot, not a permanent list of the newest patches. Check the current vendor guidance before changing a system.

Node.js matters at build time too

The October 21 Node.js security release addresses issues in supported release lines, including DNS handling, certificate verification, and Brotli decompression. The Brotli issue matters where an application processes attacker-controlled compressed data.

For a project review, I need more than a search for node in a Dockerfile. I need the version used by the build worker, scheduled jobs, and any server process. A broad major-version declaration does not establish the patch level of a completed build.

Framework advisories have feature-specific conditions

The October 14 Next.js update lists fixes in 15.5.28 and 16.4.1. Its advisories cover different features, including Server Actions, image optimization, and cached functions.

That means checking the resolved framework version and the application’s features. A static export and a server application can have the same dependency version but different exposure. Neither should be classified from the package name alone. Follow the vendor’s upgrade guidance even when a feature appears unused.

Certificate trust can live in several places

Render’s eMudhra advisory separates system certificate stores from certificate bundles shipped by language libraries. It also covers static-site builds that use Node.js or make HTTPS requests. Render explicitly says its platform was not compromised by this vulnerability.

Its guidance lists Node.js 22.23.4, 24.22.1, or 26.12.1, or a later release in the same major branch. It also lists Python certifi 2026.10.19 or later and Bun 1.4.4 or later.

That produces several checks: identify the trust store each client uses, update the relevant bundle, rebuild the image where needed, and verify the deployed result. Updating the operating system alone can leave a bundled trust store unchanged.

PHP needs a runtime check after the image update

Render’s PHP2Shell advisory links the upstream disclosure and lists patched PHP releases: 8.5.12, 8.4.27, 8.3.36, and 8.2.35, or later releases in those branches.

The practical detail is distribution backports. A distribution can ship the fix while retaining an older upstream version number. The right evidence is its security advisory and installed package revision.

The process serving web requests also needs checking. An updated command-line binary does not establish that an old PHP-FPM process has been replaced.

PHP’s October 23 follow-up adds a narrow session upload-progress case involving a runtime change of session serializer. It recommends setting session.upload_progress.enabled=0 until the next regular bugfix release. Applications that never change the serializer at runtime can keep the feature enabled. The latest configuration guidance therefore belongs beside the version check. A version copied from an earlier summary is not the whole review.

A compromised package needs a different response

The LiteLLM team’s October 21 incident report confirms compromised 1.107.0 packages and Docker images. It also says the official source tag did not contain the malicious files. The published artifact and the source tag were different pieces of evidence.

Its remediation section warns that starting the affected Python environment, including through pip, can execute the payload again. This review does not establish that one of my projects installed the package.

For a supply-chain incident, installation history, cached artifacts, image digests, and build provenance matter. A current manifest alone cannot establish whether an earlier build consumed a compromised artifact. Suspected environments need a controlled incident-response process, not an ordinary dependency-update command.

A broad checklist needs small, testable questions

The OWASP Application Security Verification Standard is useful for turning vague security goals into verification requirements. My project checklist also needs operational checks around builds, deployments, and recovery.

The checklist grew to 206 requirements across 12 areas, informed by 67 official references:

  • Current advisories: 28.
  • Project and deployment inventory: 10.
  • Dependencies and package integrity: 14.
  • Secrets and credentials: 12.
  • Build and release pipelines: 16.
  • Authentication and authorization: 22.
  • APIs and server-side input handling: 24.
  • Browser and web controls: 14.
  • Cloud and container configuration: 20.
  • AI systems and agents: 22.
  • Data protection: 12.
  • Operations and recovery: 12.

That is the size of the checklist, not the number of tests completed. It is a practical, source-informed selection and does not establish ASVS certification.

Some representative questions show the level of detail:

  • Can each deployed service be mapped to a repository and build revision?
  • Which runtime and certificate bundle did the build and service actually use?
  • Does the resolved dependency fall inside the advisory’s affected range?
  • Can a pull request from an untrusted fork reach deployment credentials?
  • Does the server check ownership before returning or changing an object?
  • Do old sessions stop working after revocation on another device?
  • Are uploaded files and remote URLs checked at the point they are used?
  • Can a guest repeatedly trigger a paid AI call without a bounded budget?
  • Does an agent need separate approval before a consequential action?
  • Can logs or generated artifacts expose credentials or private content?
  • Are data-store permissions and retention rules enforced?
  • Can an isolated restore recover the data the service needs?

These are questions in the checklist, not claims that every test ran or passed.

Each check has a stable identifier, an applicability condition, required evidence, and a safe verification method. The result can distinguish a confirmed finding, a potential finding, a source pass, a runtime pass, not applicable, unknown, blocked, or not assessed.

The last four states are useful. They keep a missing runtime, a permission boundary, or an irrelevant feature from becoming a misleading green tick.

The wording matters. “Check authentication” is too broad. “Use two authorized test accounts and verify that one cannot read the other’s object” gives the tester a protected boundary and an observable result.

The same applies to recovery. “Backups enabled” checks configuration. Restoring a backup into an isolated environment checks whether recovery works. Both belong in the record, with different evidence.

What the first pass can honestly say

The first pass inventoried 223 repositories and made 37 targeted source inspections. It recorded 20 qualified findings or evidence gaps. These counts describe the scope of that pass, not confirmed vulnerabilities or completed tests. It did not inspect every code path or execute all 206 requirements across every project.

A separate local audit is still in progress. Its coverage is not included in these first-pass counts.

The inventory includes forks and collaborative repositories. Access to a repository does not by itself authorize testing a deployed service. Responsibility and testing scope need to be clear first.

No live runtime or deployment verification, authenticated security tests, installed-package scans, full-history secret scans, or exploit tests ran in that audit pass. No fixes were applied. Where the available access could not establish a control, the result remains unknown.

Source evidence helps decide the next verification step. A declared version, an enabled feature, a resolved transitive dependency, and a deployed configuration each answer a different question. I keep project-specific evidence in the private findings record while those questions remain open.

The private findings record needs the affected project, reviewed revision, evidence, confidence, and next verification step. This public post does not need secret values, private account information, or a route-by-route map of unresolved weaknesses.

I did not treat a notification, a matching package name, or an old version string as proof of a breach. I also did not treat the absence of those signals as proof that the projects were secure.

A fix needs its own evidence

The next useful action depends on the finding.

For a dependency patch, the work is to choose the supported fixed release, update the resolved dependency, run the relevant tests, rebuild, deploy, and confirm what is running. The advisory’s exact affected range matters more than a summary’s oldest suggested upgrade.

For an authorization concern, the work is to trace the guard and run a bounded test with approved accounts and synthetic data. A plausible source path is a candidate finding until the surrounding controls are understood.

For an unknown runtime, the work is to obtain the deployment evidence. Re-reading the manifest will not answer a question about the live process.

For a suspected supply-chain compromise, preserve the relevant evidence and follow the current incident guidance from a clean environment. Updating a version is only one part of that response.

The useful end state is a closed record with proof. Until then, keep the item open and say what evidence is missing.