Summary
Automated multi-layer security scan of agentmap at e806c94 (v0.12.1): dependency audit, static code analysis, secret/history scan, and CI/config review.
Good news first: no dependency CVEs, no hardcoded secrets, and no command-injection / eval / path-traversal / insecure-crypto issues were found. The codebase is already unusually well-hardened. The findings below are CI/supply-chain hardening items, all safely fixable without breaking changes.
| # |
Severity |
Type |
Location |
Recommendation |
| 1 |
Medium |
Over-privileged CI GITHUB_TOKEN (no least-privilege permissions:) |
.github/workflows/ci.yml |
Add top-level permissions: contents: read |
| 2 |
Low |
No top-level permissions: default |
.github/workflows/publish.yml |
Add top-level permissions: contents: read |
| 3 |
Low |
Lockfile root version drift (0.11.0 vs 0.12.1) |
package-lock.json |
Sync to package.json version |
Details
1. CI runs with the default (potentially read/write) GITHUB_TOKEN — Medium
ci.yml triggers on push and pull_request and declares no top-level permissions: block. Only the codeql job scopes its token; the test and secret-scan jobs inherit the repo-default GITHUB_TOKEN scope (often contents: write). Since the workflow runs on fork PRs and executes project code (npm ci/npm test run arbitrary lifecycle & test code), an over-privileged default token widens the blast radius of any compromised dependency or malicious contribution. This is the OpenSSF Scorecard Token-Permissions check.
Fix: add permissions: contents: read at the workflow top level; the codeql job's existing security-events: write block overrides it where needed.
2. publish.yml has no top-level permissions: default — Low
The publish job is correctly scoped (contents: write, id-token: write), but there's no top-level default, so any future job added without its own block would inherit the repo default. Add a permissions: contents: read default for defense-in-depth; the publish job's explicit block still overrides it.
3. package-lock.json version drift — Low
Lockfile root version was 0.11.0 while package.json is 0.12.1 (dependency entries were in sync, so npm ci passed). Stale root version is a supply-chain hygiene issue; sync it to 0.12.1.
Positive observations (already-strong controls)
- Single prod dep (
ts-morph@28.0.0); npm audit clean.
- All git subprocess calls use
execFileSync with arg arrays; the string-based sh() helper is only ever called with static commands — no injection.
--any content search excludes .env/keys/*secret*/*credential*/*password* so local secrets are never surfaced to an LLM.
- MCP
any results are fenced as untrusted DATA (prompt-injection defense).
post-commit hook refuses attacker-plantable ./agentmap.mjs (RCE-on-commit defense).
- CI already runs CodeQL, Gitleaks, and
npm audit --audit-level=high; Actions are SHA-pinned; npm publish uses OIDC provenance.
Remaining items needing human review
None requiring breaking changes / major version bumps.
Scan performed by an automated security agent. A PR addressing findings 1–3 follows.
Summary
Automated multi-layer security scan of
agentmapate806c94(v0.12.1): dependency audit, static code analysis, secret/history scan, and CI/config review.Good news first: no dependency CVEs, no hardcoded secrets, and no command-injection / eval / path-traversal / insecure-crypto issues were found. The codebase is already unusually well-hardened. The findings below are CI/supply-chain hardening items, all safely fixable without breaking changes.
GITHUB_TOKEN(no least-privilegepermissions:).github/workflows/ci.ymlpermissions: contents: readpermissions:default.github/workflows/publish.ymlpermissions: contents: readversiondrift (0.11.0 vs 0.12.1)package-lock.jsonpackage.jsonversionDetails
1. CI runs with the default (potentially read/write)
GITHUB_TOKEN— Mediumci.ymltriggers onpushandpull_requestand declares no top-levelpermissions:block. Only thecodeqljob scopes its token; thetestandsecret-scanjobs inherit the repo-defaultGITHUB_TOKENscope (oftencontents: write). Since the workflow runs on fork PRs and executes project code (npm ci/npm testrun arbitrary lifecycle & test code), an over-privileged default token widens the blast radius of any compromised dependency or malicious contribution. This is the OpenSSF Scorecard Token-Permissions check.Fix: add
permissions: contents: readat the workflow top level; thecodeqljob's existingsecurity-events: writeblock overrides it where needed.2.
publish.ymlhas no top-levelpermissions:default — LowThe
publishjob is correctly scoped (contents: write,id-token: write), but there's no top-level default, so any future job added without its own block would inherit the repo default. Add apermissions: contents: readdefault for defense-in-depth; the publish job's explicit block still overrides it.3.
package-lock.jsonversion drift — LowLockfile root
versionwas0.11.0whilepackage.jsonis0.12.1(dependency entries were in sync, sonpm cipassed). Stale root version is a supply-chain hygiene issue; sync it to0.12.1.Positive observations (already-strong controls)
ts-morph@28.0.0);npm auditclean.execFileSyncwith arg arrays; the string-basedsh()helper is only ever called with static commands — no injection.--anycontent search excludes.env/keys/*secret*/*credential*/*password*so local secrets are never surfaced to an LLM.anyresults are fenced as untrusted DATA (prompt-injection defense).post-commithook refuses attacker-plantable./agentmap.mjs(RCE-on-commit defense).npm audit --audit-level=high; Actions are SHA-pinned; npm publish uses OIDC provenance.Remaining items needing human review
None requiring breaking changes / major version bumps.
Scan performed by an automated security agent. A PR addressing findings 1–3 follows.