Skip to content

feat: merge-train/fairies#22731

Merged
AztecBot merged 4 commits into
nextfrom
merge-train/fairies
Apr 23, 2026
Merged

feat: merge-train/fairies#22731
AztecBot merged 4 commits into
nextfrom
merge-train/fairies

Conversation

@AztecBot

@AztecBot AztecBot commented Apr 22, 2026

Copy link
Copy Markdown
Collaborator

BEGIN_COMMIT_OVERRIDE
fix(aztec test): anchor contract log filter to avoid framework spam (#22726)
fix(aztec-up): Do not leak node_modules/.bin into the PATH (#22709)
END_COMMIT_OVERRIDE

…22726)

## Summary

The default `LOG_LEVEL` for `aztec test` is `error;trace:contract`,
intended to surface `println`/`debug_log` output from Noir user
contracts (whose loggers are named `contract:Name(addr)` since #22027).

`getLogLevelFromFilters` in `foundation/src/log/log-filters.ts` matches
filters via unanchored `RegExp.test`, so `contract` also matches any
framework logger whose name *contains* "contract" as a substring — e.g.
`simulator:contract_provider_for_cpp` and `txe:contract_sync`. The
result is a flood of trace/debug output during `aztec test` runs.

Example spam seen today with defaults:

```
[13:09:56.527] TRACE: simulator:contract_provider_for_cpp Contract provider callback: getContractClass(0x03bab3b2484869300223c1f3aaf03a923b81f0a0943757d39f7b8d4946a4e80c)
[13:09:56.539] DEBUG: txe:contract_sync Wiping contract sync cache (1 entries)
[13:09:56.546] TRACE: simulator:contract_provider_for_cpp Contract provider callback: getContractInstance(0x230040c121741509d2aa2cefa9d9a31b648dd05932ac9325849a1ef9f0ae850a)
[13:09:56.552] DEBUG: txe:contract_sync Wiping contract sync cache (1 entries)
[13:09:56.555] DEBUG: txe:contract_sync Contract 0x29b3f6ea465629ac3087612a293f6dfd3f31e345b91559b766f658c48b0e2d96 synced
[13:09:56.574] DEBUG: txe:contract_sync Wiping contract sync cache (1 entries)
[13:09:56.611] TRACE: simulator:contract_provider_for_cpp Contract provider callback: getContractInstance(0x230040c121741509d2aa2cefa9d9a31b648dd05932ac9325849a1ef9f0ae850a)
[13:09:56.612] TRACE: simulator:contract_provider_for_cpp Contract provider callback: getContractInstance(0x230040c121741509d2aa2cefa9d9a31b648dd05932ac9325849a1ef9f0ae850a)
[13:09:56.685] DEBUG: txe:contract_sync Syncing contract 0x16aba66a0879d78c12d8fc5a9c911c954756fb36f22af1a88fd113dc819b462d
[13:09:56.702] DEBUG: txe:contract_sync Wiping contract sync cache (0 entries)
[13:09:56.709] DEBUG: txe:contract_sync Wiping contract sync cache (1 entries)
[13:09:56.711] TRACE: simulator:contract_provider_for_cpp Contract provider callback: commitCheckpoint
[13:09:56.729] DEBUG: txe:contract_sync Wiping contract sync cache (0 entries)
[13:09:56.790] TRACE: simulator:contract_provider_for_cpp Contract provider callback: getContractInstance(0x230040c121741509d2aa2cefa9d9a31b648dd05932ac9325849a1ef9f0ae850a)
[13:09:56.796] DEBUG: txe:contract_sync Wiping contract sync cache (1 entries)
[13:09:56.797] TRACE: simulator:contract_provider_for_cpp Contract provider callback: addContracts
[13:09:56.797] TRACE: simulator:contract_provider_for_cpp Calling contractsDB.addContracts
[13:09:56.801] TRACE: simulator:contract_provider_for_cpp Contract provider callback: createCheckpoint
[13:09:56.802] TRACE: simulator:contract_provider_for_cpp Contract provider callback: addContracts
[13:09:56.802] TRACE: simulator:contract_provider_for_cpp Calling contractsDB.addContracts
[13:09:56.805] TRACE: simulator:contract_provider_for_cpp Contract provider callback: getContractInstance(0x21fef0a3b913c62a10a0b22974b921f0245e6a6d030d00e7db46ccce7ed0960e)
[13:09:56.821] DEBUG: txe:contract_sync Syncing contract 0x28aa70094cc85d571719a5f75e6a640ce0b61708ade5749d21262b333f7f1375
[13:09:56.859] DEBUG: txe:contract_sync Wiping contract sync cache (0 entries)
[13:09:56.865] TRACE: simulator:contract_provider_for_cpp Contract provider callback: commitCheckpoint
[13:09:56.870] TRACE: simulator:contract_provider_for_cpp Contract provider callback: getContractClass(0x15f2dc8b74f53c4d416f998a91843cc39e8eb4523893d5868d170ba7e930d703)
[13:09:56.883] TRACE: simulator:contract_provider_for_cpp Contract provider callback: addContracts
[13:09:56.883] TRACE: simulator:contract_provider_for_cpp Calling contractsDB.addContracts
[13:09:56.883] TRACE: simulator:contract_provider_for_cpp Contract provider callback: commitCheckpoint
[13:09:56.886] TRACE: simulator:contract_provider_for_cpp Contract provider callback: createCheckpoint
^C[13:09:56.894] TRACE: simulator:contract_provider_for_cpp Contract provider callback: addContracts
[13:09:56.894] TRACE: simulator:contract_provider_for_cpp Calling contractsDB.addContracts
```

## Fix

Anchor the filter to `^contract:` so it matches only user-contract
loggers (named `contract:Name(addr)`) and not framework modules that
happen to contain "contract" somewhere in their name.

This is a minimal/local fix. There's an argument that there is an
underlying issue: `getLogLevelFromFilters` using unanchored
`RegExp.test`.

**If we think that `getLogLevelFromFilters` should be anchored, we can
do the following. DO WE WANT THIS?**
```ts
// yarn-project/foundation/src/log/log-filters.ts
-       const regex = new RegExp(filterModule);
+       const regex = new RegExp('^' + filterModule);
```

One-line change that anchors every filter at the start of the module
name, matching the semantics of the existing `startsWith` fallback and
how callers actually write filters. Users who wrote genuine regex
(`foo.*bar`) still work as `^foo.*bar`; substring-match users would need
to prepend `.*`.

## Test plan

- Run `aztec test` on a Noir contract test suite and confirm
`simulator:contract_provider_for_cpp` and `txe:contract_sync` are silent
at the default level.
- Confirm `contract:Name(addr)` user-contract logs still appear at trace
level.

🤖 Generated with help from [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AztecBot and others added 2 commits April 22, 2026 19:42
## Summary

The `aztec-up` installer adds `$HOME/.aztec/current/node_modules/.bin`
to the user's shell PATH. That directory contains the bin entries of
every transitive npm dependency of the Aztec packages, so ~40
third-party bins (`jest`, `tsc`, `tsserver`, `semver`, `uuid`, `json5`,
`pino`, `mime`, `rlp`, ...) end up on PATH, silently shadowing
user-installed versions.

This PR exposes only the 7 intended `@aztec/*`-owned bins and drops
`node_modules/.bin` from the PATH line.

## Why

Two problems with the current setup:

1. **DX / correctness.** A developer with `jest@29` pinned locally
silently runs Aztec's bundled `jest@30` when typing `jest`, producing
confusing errors (e.g. the renamed `--testPathPattern` flag). Same trap
for `tsc`, `semver`, etc. The user has no way to enumerate what's been
shadowed without reading the dep tree.
2. **Invocation surface.** Install-time trust is unchanged — every
package in the graph already runs code via `postinstall` or when Aztec
uses it — but putting transitive bins on PATH adds a new invocation
vector: a compromised transitive bin can fire on normal dev activity
(`jest`, `tsc`) rather than only when Aztec calls it. Notably, that
bypasses `--ignore-scripts`-style defenses and is stealthier than a
postinstall payload. Standard package managers (`npm install -g`,
`pipx`, `brew`, `cargo install`) do not expose transitive bins on PATH;
they symlink only the package's declared entry points.

Context:
https://gist.github.com/AztecBot/fc2f40d50592c468429f922921a271f2 and
https://www.notion.so/aztecnetwork/Getting-Started-Token-Tutorial-Walk-Through-348a1f6b0e35806a884edc16742866b9

## Changes

- `aztec-up/bin/0.0.1/install` — new `symlink_aztec_bins` function,
called after `install_aztec_packages`. Iterates `node_modules/.bin/*`,
keeps only symlinks whose target starts with `../@aztec/`, and re-links
them into `$version_path/bin/` using relative paths
(`../node_modules/.bin/<name>`). No hard-coded list: the set of exposed
bins follows whatever `@aztec/*` packages declare.
- `aztec-up/bin/0.0.1/aztec-install` — drops
`$HOME/.aztec/current/node_modules/.bin` from the shell-profile PATH
export.
- `aztec-up/bin/0.0.1/aztec-up` — drops `node_modules/.bin` from
`aztec-up env` output so per-project `.aztecrc` switching also skips the
leak.

Each version's `bin/` stays self-contained, so `aztec-up use <ver>`
flips the entire bin set atomically via the `current` symlink — same
mechanism as today.

## Verification

Ran the new `symlink_aztec_bins` function against an existing
`~/.aztec/current` install, mirrored into a throwaway `AZTEC_HOME`:

```
=== Bins exposed in version bin/ ===
aztec aztec-wallet bb bb-cli blob-client noir-codegen txe

=== Symlink resolution ===
aztec         -> .../node_modules/@aztec/aztec/scripts/aztec.sh
aztec-wallet  -> .../node_modules/@aztec/cli-wallet/dest/bin/index.js
bb            -> .../node_modules/@aztec/bb.js/dest/node/bin/index.js
bb-cli        -> .../node_modules/@aztec/bb-prover/dest/bb/index.js
blob-client   -> .../node_modules/@aztec/blob-client/dest/client/bin/index.js
noir-codegen  -> .../node_modules/@aztec/noir-noir_codegen/lib/main.js
txe           -> .../node_modules/@aztec/txe/dest/bin/index.js

=== Transitive bins absent from version bin/ ===
jest tsc tsserver semver uuid json5 pino pino-pretty mime rlp  (all absent)

=== Exec through the chain ===
PATH=$THROWAWAY_BIN:... aztec-wallet --help  →  prints help OK
```

7 bins exposed vs. 40 before; all resolve; end-to-end execution works.

## Confirmed non-regressions

Audited Aztec production CLI code for bare-name shell-outs that could
rely on transitive bins being on PATH:

- `yarn-project/aztec/scripts/aztec.sh` — shells out to `anvil`,
`nargo`, `nc`, and itself. `anvil`/`nargo` live in `current/bin/`
(installed by `aztec-install`), `nc` is system. Unaffected.
- `yarn-project/aztec/src/cli/cmds/compile.ts` / `profile_gates.ts` —
resolve `bb` via `findBbBinary()` (absolute path from `@aztec/bb.js`),
fall back to bare `'bb'` which remains reachable as a new symlink in
`current/bin/`.
- `yarn-project/cli/src/cmds/misc/update/npm.ts` — intentionally invokes
user's system `npm`/`pnpm`/`yarn`. Unaffected.

No other bare-name invocations of transitive bins.

## Migration

Fresh installs and `aztec-up install <ver>` pick up the fix
automatically. Existing users still have the old `export
PATH=…:current/node_modules/.bin:…` line in their shell profile; that
gets rewritten the next time they run `aztec-install` (the existing
dedup at `aztec-install:210` strips old entries). Worth flagging in
release notes.

---------

Co-authored-by: Nicolas Chamo <nicolas@chamo.com.ar>
@vezenovm vezenovm requested a review from charlielye as a code owner April 22, 2026 20:03

@ludamad ludamad left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Auto-approved

@AztecBot AztecBot added this pull request to the merge queue Apr 23, 2026
@AztecBot

Copy link
Copy Markdown
Collaborator Author

🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass.

Merged via the queue into next with commit de7fcc2 Apr 23, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants