You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
[0.2.4] CI hardening + runtime P3 cleanup
Security
Supply chain: all uses: actions pinned to commit SHA across 5 workflows (auto-release, ci, docs-drift, publish, publish-mcp-registry). @v4 tags can be re-pointed upstream to a malicious commit; SHA pins close that window.
Least-privilege: permissions: contents: read default on ci.yml + docs-drift.yml. Publish + auto-release continue to opt into contents: write / id-token: write at the job level explicitly.
@claude workflows: trust gate + per-event principal binding. Previously any GitHub user could comment @claude on an issue/PR and trigger an agent run with AWS Bedrock credentials in scope. Now gated on kevinastuhuaman OR per-event author_association (comment/review/issue/pull_request.user.login), each bound to its triggering principal. Closes a bypass where the issue opener's association would let arbitrary commenters through.
HTTP client: 10 MB response-body cap + response-stream error handler in lib/client.js. A malicious or misconfigured TRACKLY_BASE_URL can no longer OOM the long-lived MCP process via unbounded streaming. res.on('error', reject) prevents an uncaught exception when req.destroy() tears down the socket mid-read.
/ask jobsUrl path allowlist (regex /^\/api\/(v1|jobscout)\/jobs(\?|$)/). Both bin/trackly:cmdAsk and mcp/server.js:trackly_ask refuse any jobsUrl outside the allowlist; MCP also strips the refused URL from its return payload so the agent client doesn't receive a path we just refused.
Tests
New regression test: test/mcp-schema.test.js enforces three invariants — allowlist definition includes the (\?|$) boundary, .test() is called, AND the call appears BEFORE the fetch in source order.
New runtime test: test/client.test.js starts a fake server streaming 11 MB and asserts apiRequest rejects with a specific error (not OOM).
test/client.test.js oversized-body + refresh-token branches now total 29/29 tests.
Publish pipeline
npm publish exit-code capture refactored to || PUBLISH_EXIT=$? so GitHub Actions' implicit set -e can't abort the step before the benign EPUBLISHCONFLICT branch runs.
mcp-publisher still pinned to v1.6.0 + SHA256-verified.
Provenance attestation gate still verifies post-publish.