Skip to content

Commit 9395f7f

Browse files
committed
[#2125] Added support for Composer 2.9.0 automated security audit.
1 parent 75a3548 commit 9395f7f

48 files changed

Lines changed: 306 additions & 43 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.circleci/config.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,10 @@ jobs:
280280
COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist"
281281
docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile"
282282
283+
- run:
284+
name: Audit Composer packages
285+
command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ]
286+
283287
- run:
284288
name: Validate Composer configuration is normalized
285289
command: |

.github/workflows/build-test-deploy.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ jobs:
274274
COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist"
275275
docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile"
276276
277+
- name: Audit Composer packages
278+
run: docker compose exec -T cli composer audit
279+
continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE == '1' }}
280+
277281
- name: Validate Composer configuration is normalized
278282
if: ${{ matrix.instance == 0 || strategy.job-total == 1 }}
279283
run: docker compose exec -T cli composer normalize --dry-run

.vortex/docs/.utils/variables/extra/ci.variables.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE=0
3030
# Ignore `composer normalize` failures.
3131
VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE=0
3232

33+
# Ignore `composer audit` failures.
34+
VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE=0
35+
3336
# Ignore PHPCS failures.
3437
VORTEX_CI_PHPCS_IGNORE_FAILURE=0
3538

.vortex/docs/content/drupal/composer.mdx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,23 @@ specifies key configurations for Composer's behavior in the project.
226226
This setting specifies which Composer plugins are allowed to run. It's a
227227
security measure to prevent the execution of untrusted code from third-party
228228
plugins. Each plugin needs to be explicitly allowed to ensure it can execute.
229+
- [`audit`](https://getcomposer.org/doc/06-config.md#audit): Introduced in
230+
Composer 2.9.0, this setting controls automatic security auditing of
231+
dependencies during `composer install` and `composer update`. **Vortex**
232+
enforces security best practices with the following configuration:
233+
- `block-insecure` (default: `true`): Blocks installation of packages with
234+
known security vulnerabilities unless explicitly ignored. This ensures
235+
security issues are addressed before deployment.
236+
- `abandoned` (default: `report`): Shows warnings for abandoned packages
237+
without failing the build. Allows visibility into package maintenance status
238+
while not blocking installations.
239+
- `ignore` (default: `{}`): Empty object ready for adding assessed and
240+
documented vulnerability exceptions. Use this to explicitly allow specific
241+
CVE/GHSA advisories that have been reviewed and accepted.
242+
- See
243+
[Composer Security Auditing](../workflows/development#composer-security-auditing)
244+
for comprehensive guidance on configuration options, ignoring specific
245+
advisories, running audits, and best practices.
229246
- [`discard-changes`](https://getcomposer.org/doc/06-config.md#discard-changes):
230247
When set to `true`, any local changes made to the dependencies (packages under
231248
version control like Git) are discarded without prompting when you run

.vortex/docs/content/workflows/development.mdx

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ file to `.data/db.sql` and run `ahoy import-db`.
8080

8181
See [Drupal > Provision](../drupal/provision) for more details.
8282

83-
## Environment Variable Updates
83+
## Environment variable updates
8484

8585
To update environment variables in your local development environment:
8686

@@ -305,6 +305,118 @@ Composer Patches v2.x automatically generates a `patches.lock.json` file that co
305305
composer update --lock
306306
```
307307

308+
### Composer security auditing
309+
310+
Composer 2.9.0 introduced automatic security auditing that checks your dependencies for known security vulnerabilities and abandoned packages. This feature helps you maintain a secure codebase by alerting you to potential issues during package installation and updates.
311+
312+
#### Configuration Options
313+
314+
Configure audit behavior in your `composer.json` under the `config` section:
315+
316+
```json
317+
{
318+
"config": {
319+
"audit": {
320+
"abandoned": "report",
321+
"block-insecure": true,
322+
"ignore": {
323+
"CVE-2024-1234": "The affected component is not in use in our application.",
324+
"GHSA-xxxx-yyyy-zzzz": "Mitigated by additional security measures."
325+
}
326+
}
327+
}
328+
}
329+
```
330+
331+
**Available Options:**
332+
333+
- **`block-insecure`**: Controls whether packages with security vulnerabilities block installation
334+
- `true` (**Vortex** default): Blocks installation/update of vulnerable packages unless ignored
335+
- `false`: Shows warnings but allows installation to proceed
336+
- **`abandoned`**: Controls how abandoned packages are handled
337+
- `report` (**Vortex** default): Shows abandoned packages as warnings but doesn't fail
338+
- `fail`: Audit command fails with non-zero exit code
339+
- `ignore`: Skips abandoned packages in audit reports
340+
- **`ignore`**: Ignores specific security advisories by CVE or GHSA identifier (empty by default)
341+
342+
#### When to Use `block-insecure: false`
343+
344+
**Vortex** sets `block-insecure` to `true` by default to enforce security best practices. However, you may want to set it to `false` when:
345+
346+
- You need flexibility to evaluate vulnerabilities on your timeline
347+
- No secure version is immediately available
348+
- The vulnerability doesn't affect your specific use case
349+
- You're in active development and need uninterrupted workflow
350+
351+
Keep it `true` (Vortex default) when:
352+
353+
- Working on production sites with strict security requirements
354+
- Your deployment process can handle blocked installations
355+
- You want to enforce immediate action on security vulnerabilities
356+
- Your team has resources to quickly address security issues
357+
358+
:::warning Vortex Security-First Philosophy
359+
360+
**Vortex** adopts a security-first approach by setting `block-insecure: true` as the default. This prioritizes safety in automated deployments by preventing vulnerable packages from being installed without explicit review.
361+
362+
If you need to override this setting for backwards compatibility, you can modify the `audit.block-insecure` configuration in your project's `composer.json` file. However, we strongly recommend addressing vulnerabilities by updating packages or using the `ignore` configuration for assessed exceptions, rather than routinely disabling security blocking.
363+
364+
This approach ensures security issues are explicitly acknowledged and reviewed before being accepted into your codebase.
365+
366+
:::
367+
368+
#### Ignoring Specific Advisories
369+
370+
When you've assessed a vulnerability and determined it doesn't affect your project, you can ignore it:
371+
372+
```json
373+
{
374+
"config": {
375+
"audit": {
376+
"ignore": {
377+
"CVE-2024-1234": "Component is not used in our implementation.",
378+
"GHSA-xxxx-yyyy-zzzz": "Patched via custom security fix."
379+
}
380+
}
381+
}
382+
}
383+
```
384+
385+
:::tip Document Your Decisions
386+
387+
Always include reasons when ignoring advisories into your Git commit messages. This helps your team understand why a vulnerability was deemed acceptable and makes it easier to review these decisions in the future.
388+
389+
:::
390+
391+
#### Running Audit Command
392+
393+
Check your dependencies for security issues manually:
394+
395+
```bash
396+
# Audit all installed packages
397+
composer audit
398+
399+
# Audit only production dependencies (exclude dev)
400+
composer audit --no-dev
401+
402+
# Audit packages from lock file (faster)
403+
composer audit --locked
404+
405+
# Control abandoned package behavior
406+
composer audit --abandoned=ignore # Skip abandoned packages
407+
composer audit --abandoned=report # Show but don't fail
408+
```
409+
410+
##### CI/CD Integration
411+
412+
**Vortex** automatically runs `composer audit` as part of the CI/CD pipeline to
413+
check for security vulnerabilities during builds.
414+
415+
By default, audit failures will cause the CI build to fail. You can control this
416+
behavior using a repository variable `VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE`
417+
set to `1`. When this variable is set to `1`, the audit step will run but won't
418+
fail the build if vulnerabilities are found.
419+
308420
## Resetting the codebase
309421

310422
To reset the local environment, use the `ahoy reset` command. This command will

.vortex/docs/content/workflows/releasing.mdx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Code goes "up" (from lower to higher environments) while database goes "down" (f
4747
This means that the production database is the primary source of truth - it's what code is applied to. When performing a release, you are applying a new version of code to a database within a specific environment.
4848

4949
To ensure that code changes work correctly with real data structures, the following process is followed in lower environments:
50+
5051
1. Database is copied from a higher environment to a lower one (e.g., production → stage → development)
5152
2. Code is deployed to that environment to be tested against the copied database
5253
3. Testing is performed to ensure everything works correctly
@@ -136,9 +137,11 @@ gitGraph
136137
Below are the typical steps to perform a release using git-flow. See [cheat sheet](https://danielkummer.github.io/git-flow-cheatsheet/) for a quick reference on git-flow commands.
137138

138139
1. **Start Release**
140+
139141
```bash
140142
git flow release start X.Y.Z
141143
```
144+
142145
Creates a `release/X.Y.Z` branch from `develop`. It is recommended to push
143146
the branch to remote.
144147

@@ -148,9 +151,11 @@ Below are the typical steps to perform a release using git-flow. See [cheat shee
148151
- Release notes preparation
149152

150153
3. **Finish Release**
154+
151155
```bash
152156
git flow release finish X.Y.Z
153157
```
158+
154159
- Merges release branch to `main`
155160
- Tags the release
156161
- Merges back to `develop`
@@ -159,6 +164,7 @@ Below are the typical steps to perform a release using git-flow. See [cheat shee
159164
4. **Deploy to Production**
160165
- **Tag-based hosting:** Deploy the tag directly
161166
- **Branch-based hosting (e.g., Lagoon):** Manually sync to `production` branch
167+
162168
```bash
163169
git push origin main:production
164170
```
@@ -190,12 +196,14 @@ During installation, you can choose between Calendar Versioning (CalVer), Semant
190196
- `Z` = Hotfix/patch version (no leading zeroes)
191197

192198
#### Why CalVer
199+
193200
- **Release frequency transparency**: When you have multiple releases per month, dates make it easy to identify when a release happened
194201
- **Intuitive tracking**: Stakeholders can immediately understand "this is from January 2025" vs memorizing version numbers
195202
- **Natural progression**: No ambiguity about major vs minor changes - just the chronological order
196203
- **Marketing alignment**: Easier to communicate to non-technical audiences ("our Q1 2025 release")
197204

198-
#### Examples:
205+
#### Examples
206+
199207
- ✅ Correct: `25.1.0`, `25.11.1`, `25.1.10`, `25.10.1`, `9.12.0`
200208
- ❌ Incorrect: `25.0.0` (no month 0), `2025.1.1` (full year), `25.01.0` (leading zero), `01.1.0` (leading zero in year)
201209

@@ -210,12 +218,14 @@ Learn more: [CalVer.org](https://calver.org/)
210218
- `Z` = Hotfix/patch version (no leading zeroes)
211219

212220
#### Why SemVer
221+
213222
- **Breaking change communication**: Major version bump signals incompatible API changes
214223
- **Dependency management**: Package managers can enforce compatible version ranges
215224
- **Developer expectations**: Well-understood convention in the development community
216225
- **Predictable upgrades**: Minor versions add functionality, patches fix bugs
217226

218-
#### Examples:
227+
#### Examples
228+
219229
- ✅ Correct: `0.1.0`, `1.0.0`, `1.0.1`, `1.0.10`
220230
- ❌ Incorrect: `0.1` (missing patch), `1` (missing minor and patch), `1.0.01` (leading zero)
221231

@@ -263,6 +273,7 @@ Your project includes a `docs/releasing.md` file that serves as the canonical re
263273
- **Release procedures** - Custom workflows specific to your project
264274

265275
You can extend this file with:
276+
266277
- **Detailed release procedures** - A comprehensive outline of _what_ actions to take during releases:
267278
- Steps to create and finish releases
268279
- Steps to deploy to production
@@ -279,6 +290,7 @@ You can extend this file with:
279290
**Deployment Markers**: When configured, **Vortex** automatically creates deployment markers in New Relic when releases are deployed to your environments. These markers help correlate performance changes, errors, and other metrics with specific releases.
280291

281292
**Benefits**:
293+
282294
- Visualize before/after release performance
283295
- Correlate errors with specific deployments
284296
- Track deployment frequency

.vortex/docs/content/workflows/variables.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,14 @@ Default value: `UNDEFINED`
446446

447447
Defined or used in: `CI config`
448448

449+
### `VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE`
450+
451+
Ignore `composer audit` failures.
452+
453+
Default value: `UNDEFINED`
454+
455+
Defined or used in: `CI config`
456+
449457
### `VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE`
450458

451459
Ignore `composer normalize` failures.

.vortex/docs/cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"words": [
1010
"Asciinema",
1111
"Diffy",
12+
"GHSA",
1213
"NRAK",
1314
"REDIS",
1415
"Runsheet",

.vortex/installer/tests/Fixtures/install/_baseline/.github/workflows/build-test-deploy.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ jobs:
256256
COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist"
257257
docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile"
258258
259+
- name: Audit Composer packages
260+
run: docker compose exec -T cli composer audit
261+
continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE == '1' }}
262+
259263
- name: Validate Composer configuration is normalized
260264
if: ${{ matrix.instance == 0 || strategy.job-total == 1 }}
261265
run: docker compose exec -T cli composer normalize --dry-run

.vortex/installer/tests/Fixtures/install/_baseline/composer.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@
8484
"pyrech/composer-changelogs": true,
8585
"tbachert/spi": true
8686
},
87+
"audit": {
88+
"abandoned": "report",
89+
"block-insecure": true
90+
},
8791
"discard-changes": true,
8892
"platform": {
8993
"php": "__VERSION__"

0 commit comments

Comments
 (0)