Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

### Added

- AUR integration (`feat/aur-integration`): `blueline --ecosystem aur ci
--lockfile aur.lock` reviews added and version-changed pins from a file of
one `pkgbase@pkgver-pkgrel` per line (blank lines and `#` comments
skipped, malformed lines and double pins fail closed with line numbers,
4096-entry cap, base read via `git show` like other ecosystems); a yay v13
`AURPreInstall` Lua hook recipe in the README gating the build on
`blueline review --yes`, with the re-review-on-drift timing note;
`ecosystem = "aur"` policy scoping through the existing generic matcher;
and README threat-model copy stating the repo-scripts-only scope, the
review-with-blueline-build-with-yay flow, and the commit-bound audit
integrity.
- PKGBUILD static heuristics (`src/pkgbuild.rs`, AUR reviews only): a
hand-rolled tokenizer with quote-aware lexing (`$'...'` ANSI-C, line
continuations, word-boundary comments), multi-pass variable folding,
Expand Down Expand Up @@ -75,9 +86,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
16-shard matrix.
- The MCP stdio server no longer prints an stderr note when it receives the
client's `notifications/initialized` message.
- AUR adapter resource use: one shallow clone per pkgbase is now reused
across the read-only history operations of a review (resolve walk,
releases walk, author lookup), halving the clones each evaluation
performs; the cache is keyed by the full clone url and capped, and
`fetch_verified` still re-clones so its archive bytes remain a second,
independent sample from the remote. AUR CI reports now carry a
`removed_count` (rendered in the text and markdown summaries) so pins
deleted from the pin file are visible instead of silently dropped.
PKGBUILD `$'...'` `\xHH` and octal escapes now decode as raw bytes the
way bash emits them (`\xc3\xa9` is `é`, not `é`), with non-UTF-8 byte
sequences becoming U+FFFD and over-one-byte octal escapes failing closed.

### Fixed

- AUR review hardening from the PR #53 review: PKGBUILD function bodies are
comment-stripped before rule scanning, so a commented-out `curl | bash`
inside `build()` no longer produces a HIGH R13/R14/R17 false positive; an
unreadable baseline PKGBUILD now raises `R00_BASELINE_UNREADABLE` at High
(matching the unparseable case) instead of Low, so invalid-UTF-8 baselines
cannot slip past the R12/R19 pair rules for a Low finding; interpreter
process substitution (`bash <(curl -fsSL https://…)` and fused
`bash<(curl …)`) now fires R13 even without a pipe; `git` runs under
`LC_ALL=C` so error classification no longer depends on the system locale;
and `git` invocations run in their own process group with bounded pipe
drain, so a transport child (`git-remote-https`, `ssh`, …) that outlives
git and holds the output pipes can no longer hang the review.
- AUR review hardening from the adapter review follow-up: per-commit
`.SRCINFO` reads distinguish content failures (missing, oversized,
non-UTF-8, malformed — counted as skips) from git plumbing failures
Expand Down
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ If a release exceeds risk thresholds, Blueline blocks the install and halts the

## Project status

- [x] Multi-registry support: npm, crates.io (`--ecosystem cargo`), and PyPI (`--ecosystem pypi`)
- [x] Multi-registry support: npm, crates.io (`--ecosystem cargo`), PyPI (`--ecosystem pypi`), and AUR (`--ecosystem aur`, review-only)
- [x] Sandboxed archive extraction with path traversal, symlink, and decompression bomb guards
- [x] Package manifest parsing, cryptographic integrity (SHA-256 / SHA-512), and PEP 740 / SLSA provenance
- [x] SQLite store for verified baseline releases and audit logging
Expand All @@ -70,6 +70,63 @@ cargo build --release
./target/release/blueline review express@4.21.2
```

## AUR

Blueline reviews AUR packages but never builds them: `blueline install`
refuses `--ecosystem aur` because building a PKGBUILD runs its shell code.
Review with blueline, build with yay or paru.

```bash
blueline --ecosystem aur review yay@12.4.2-1
```

Threat model, plainly stated: the review covers the repo scripts only.
Downloaded upstream sources listed in `source=()` are not reviewed, and the
build step executes the PKGBUILD. Every AUR card carries that scope
disclosure. The stored approval is bound to the reviewed commit: the audit
log keeps the sha256 of the pinned commit's archive bytes, so a history
rewrite never passes as the same approval.

### yay gate hook

yay v13 runs `AURPreInstall` hooks before building. Drop this in your yay
`init.lua` to block the build unless blueline approves the version:

```lua
yay.create_autocmd("AURPreInstall", {
desc = "gate the build on a blueline review",
callback = function(event)
for _, pkg in ipairs(event.data.packages) do
local spec = event.match .. "@" .. pkg.version
local ok = os.execute(
"blueline --ecosystem aur review "
.. string.format("%q", spec) .. " --yes --policy blueline.toml"
)
if ok ~= 0 then
yay.abort(event.match .. ": blueline refused " .. spec)
end
end
end,
})
```

Timing note: the review pins the newest commit for that version at review
time, while yay builds its own download. Re-run the review right before the
build and treat any version drift as a re-review signal.

### AUR in CI

`blueline ci` accepts a pin file with one `pkgbase@pkgver-pkgrel` per line,
blank lines and `#` comments allowed. Pipe your own tooling over
`pacman -Qqm` to produce it:

```bash
blueline --ecosystem aur ci --lockfile aur.lock --base origin/main
```

Policy rules take `ecosystem = "aur"` to scope allows and blocks to AUR,
or omit it to match every ecosystem.

## Contributors

See [CONTRIBUTORS.md](./CONTRIBUTORS.md) for maintainers, contributors, and details on how to get involved.
Expand Down
14 changes: 8 additions & 6 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,13 @@ Rulings:

- yay v13 `AURPreInstall` Lua hook recipe (README): ~10 lines invoking
`blueline --ecosystem aur review <pkgbase>@<version> --yes --policy
blueline.toml` to gate the build. Document the TOCTOU property: the hook
reviews the bytes already downloaded, never a re-fetch.
- `blueline ci`: v1 accepts a file of `pkgbase@commit` lines (lockfile
analog; `pacman -Qqm` output can be piped through the user's own tooling).
No alpm linking.
blueline.toml` to gate the build. Document the timing property honestly:
the review re-pins the newest commit for that version at review time while
yay builds its own download, so re-run the review right before the build
and treat any version drift as a re-review signal.
- `blueline ci`: v1 accepts a pin file of `pkgbase@pkgver-pkgrel` lines
(lockfile analog; `pacman -Qqm` output can be piped through the user's own
tooling). No alpm linking.
- Policy: `ecosystem = "aur"` rules work via the existing optional-ecosystem
matching; audit log records commit hashes.
- Docs: threat-model disclosure card copy and the "review with blueline,
Expand All @@ -137,7 +139,7 @@ Rulings:
- [x] PR1 feat/aur-foundation
- [x] PR2 feat/aur-adapter
- [x] PR3 feat/pkgbuild-heuristics
- [ ] PR4 feat/aur-integration
- [x] PR4 feat/aur-integration

Mark your PR's box `[x]` in the same branch before opening it.

Expand Down
Loading
Loading