Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
72953e0
docs: add quality and hardening plan (P0, P1, P2)
KNIHAL Oct 31, 2026
573a3e9
security(P0-01): update vulnerable dependencies (simple-git 4, SDK 1.…
KNIHAL Oct 31, 2026
c9c0122
fix(P0-02): Windows nested cmd.exe finds node, ComSpec set (issue #2)
KNIHAL Nov 1, 2026
3f1461f
security(P0-03): redact URL credentials, tokens, connection strings i…
KNIHAL Nov 1, 2026
ff2dafe
security(P0-04): compose via wsl --cd args, no shell text; scan test
KNIHAL Nov 1, 2026
084a4d4
security(P0-05): http_check uses the shared SSRF guard (netGuard)
KNIHAL Nov 1, 2026
afc6d72
security(P0-05): block 6to4, Teredo, ISATAP addresses in SSRF guard
KNIHAL Nov 1, 2026
c6d9936
security(P0-06): consistent path protection with real-path resolution…
KNIHAL Nov 1, 2026
85a53b6
security(P0-06): also protect ~/.causly, CAUSLY_HOME, .env, ~/.kube, …
KNIHAL Nov 2, 2026
b6e680e
ci(P0-07): Node 22/24, npm ci, audit, Dependabot, package contents an…
KNIHAL Nov 2, 2026
55beba8
security(P0-08): raise risky tool levels, per-action levels, enforce …
KNIHAL Nov 2, 2026
1b7f14a
feat(P0-09): MCP tool annotations from permission levels; stdout JSON…
KNIHAL Nov 3, 2026
a904969
fix(P0-13): edit_file matches CRLF files, github_list_issues pages pa…
KNIHAL Nov 3, 2026
7a6dae3
test(P0-10): fuzz helper and boundary tests for path and shell arguments
KNIHAL Nov 3, 2026
2715912
chore(P0-12): homepage, bugs, provenance publish workflow, metadata test
KNIHAL Nov 3, 2026
a2c18df
test(P0-11): 1.5.0 upgrade fixture, corrupt-file tests; clear corrupt…
KNIHAL Nov 3, 2026
b924f5c
chore: release 1.5.4 (version bump; longer timeout for the real-npm-i…
KNIHAL Nov 3, 2026
be74d24
test: make fuzz traversal check OS-aware
KNIHAL Nov 3, 2026
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
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- dependencies

- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- dependencies
58 changes: 55 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,21 @@ on:
jobs:
syntax-check:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: [22, 24]
steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
node-version: ${{ matrix.node }}
cache: npm

- name: Install dependencies
run: npm install
run: npm ci

- name: Check syntax of all JS files
run: |
Expand Down Expand Up @@ -47,9 +52,56 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Install dependencies
run: npm install
run: npm ci

- name: Run focused BoundaryAttest tests
run: npm run test:boundaryattest

audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Install dependencies
run: npm ci

- name: Audit production dependencies (fails on high or critical)
run: npm audit --omit=dev --audit-level=high

# The docs live in the agenv repo. This job checks that the tool pages still match
# packs/manifest.json and the permission levels in tools/security.js.
docs-drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Check out the docs repo
uses: actions/checkout@v4
with:
repository: KNIHAL/causly-agent-environment
ref: master

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Point docs drift at the revision containing the updates

While the P0-06..13 documentation updates remain only on the docs branch, this job checks out master and then runs tests/docsDrift.test.js with CAUSLY_REQUIRE_DOCS=1. That makes the check compare the updated manifest and permission levels against the stale docs revision, so the new docs-drift job fails until the docs changes are merged. Point it at the revision containing those updates, or land the docs changes first.

Useful? React with 👍 / 👎.

path: agenv

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Install dependencies
run: npm ci

- name: Docs drift test
env:
CAUSLY_DOCS_DIR: ${{ github.workspace }}/agenv/website/docs/server
CAUSLY_REQUIRE_DOCS: "1"
run: npx vitest run tests/docsDrift.test.js
2 changes: 1 addition & 1 deletion .github/workflows/cross-os.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [22]
node: [22, 24]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand Down
47 changes: 47 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Publish to npm

# Publishes with provenance (npm shows a verified link from the package to this repository and commit).
# Run it by publishing a GitHub release whose tag is v<version> (for example v1.5.4).
# Needs the repository secret NPM_TOKEN (an npm automation token).
on:
release:
types: [published]
workflow_dispatch:

permissions:
contents: read
id-token: write # required for provenance

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org
cache: npm

- name: Install dependencies
run: npm ci

- name: Release tag must match package.json
if: github.event_name == 'release'
run: |
version="$(node -p "require('./package.json').version")"
if [ "${GITHUB_REF_NAME}" != "v${version}" ]; then
echo "Tag ${GITHUB_REF_NAME} does not match package.json version ${version}"
exit 1
fi

- name: Audit production dependencies
run: npm audit --omit=dev --audit-level=high

- name: Publish with provenance
# prepublishOnly rebuilds the pack manifest and runs the full test suite first.
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,35 @@

All notable changes to this project are documented here.

## [1.5.4]

### Security
- Updated vulnerable dependencies: `simple-git` 4.x, `@modelcontextprotocol/sdk` 1.32.x, `zod` 4.6.x, plus transitive fixes. `npm audit --omit=dev` now reports 0 vulnerabilities.
- Added a test that keeps the direct dependencies on patched versions.
- `http_check` now refuses private, loopback and link-local addresses (SSRF), on every redirect hop, using the same guard as `web_fetch`. `CAUSLY_ALLOW_PRIVATE_HOSTS=true` still turns it off. The guard also judges IPv6 forms that carry an IPv4 address (6to4, ISATAP, Teredo) by that address.
- File and directory tools now protect paths consistently (`copy_file` had no check at all). Paths are resolved to their real location first (`..`, symlinks, junctions, 8.3 short names), compared on folder boundaries, and cover Windows, macOS and Linux system folders. Credential folders (`~/.ssh`, `~/.aws`, `~/.config/gcloud`, OS keychains) can no longer be read or written, and Windows device names (`CON`, `NUL`), alternate data streams and `\\?\` paths are refused. The secrets `store_path` follows the same rules. The same goes for `~/.kube`, `~/.gnupg`, `~/.azure` and Causly's own folder (`~/.causly` or `CAUSLY_HOME`, which holds your API keys), so an agent cannot read your keys through the file tools.
- Docker Compose (WSL fallback on Windows) no longer builds a shell command from the project folder, so a folder name containing quotes or shell characters cannot run commands. A test now fails if any code builds shell text for `exec`.
- Permission levels raised where the risk was higher than the level: `git_push`, `git_merge`, `secrets_get`, `supabase_create_project` and `vercel_cancel_deployment` are now `HIGH` and need `confirm: true` (their input schemas accept it). `git_stash` and `git_tag` are `MEDIUM`, and only their destructive actions (`drop`, `delete`) need `confirm: true`. A test now fails if a shipped tool has no explicit level, or if a `HIGH` or `DESTRUCTIVE` tool cannot accept `confirm`.
- Credentials no longer reach the activity log or error responses: passwords inside URLs and connection strings, Bearer tokens, common token formats and JSON password fields are redacted, and `connection_string`, `dsn` and `database_url` fields are always redacted.

### Added
- Every tool now carries the four MCP annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`), derived from its permission level. They are hints for clients, not enforcement. Tests check that all tools have them, that `READ` tools are never marked destructive, and that stdout carries only JSON-RPC.

### Fixed
- Windows: `npm install` (and any npm lifecycle script) through `run_command` no longer fails with `'node' is not recognized` (issue #2). The Node that runs the server and the npm global folder now come first in `PATH`, `ComSpec` is set when missing, and the hard-coded user name and Node folder are gone.

- A damaged local database (`causly.db`) now gives an error that names the file and says to move it aside or run `causly-server restore`, instead of SQLite's bare `file is not a database`. The file handle is also released, so the damaged file is not left locked on Windows.
- `edit_file` now matches a multi-line `old_str` in files with CRLF line endings (it failed with "not found" on normal Windows files) and keeps the file's original line endings.
- `github_list_issues` with `state: "all"` could return an empty list when the latest items were pull requests (GitHub counts them in the page size). It now reads further pages until it has enough real issues.

### Maintenance
- CI now uses Node.js 22 and 24 and `npm ci` everywhere (it still ran Node 18 and `npm install`), and the cross-OS matrix covers both Node versions.
- New automatic checks: `npm audit --omit=dev --audit-level=high`, a test that the npm package holds only the `files` allowlist (no `.env`, databases, logs or keys), and a docs drift test that compares the tool pages with `packs/manifest.json` and the permission levels.
- Upgrade test with a database written by the real 1.5.0 (pipeline, meetings, action items, reminders): data stays intact, old migrations are not re-run, new writes work. Corrupt `.env`, secrets file, database and client config are covered too.
- Input fuzz tests (`tests/fuzz.boundaries.test.js`, helper `tests/helpers/fuzz.js`) feed quotes, shell metacharacters, injection payloads, traversal, UNC paths, long and non-ASCII names to the file, directory, git, command, project, Terraform and Docker tools and check that nothing is evaluated and nothing leaves the workspace.
- npm package now lists its `homepage` and issue tracker. A new `publish.yml` workflow publishes with npm provenance when a `v<version>` GitHub release is published, and a test keeps `package.json`, `server.json` and the changelog in step.
- Dependabot opens weekly pull requests for npm packages and GitHub Actions.

## [1.5.3]

### Added
Expand Down
Loading
Loading