# Security Audit Report — altr-mcp

- **Report ID:** `f55af95e-ce4b-4c03-b613-bc698035e689`
- **Generated:** 2026-07-30T10:49:40.998615+00:00
- **Signature:** unsigned (cosign keyless signing runs in CI; Req 22.4)

## 1. Executive Summary

**Badge:** Unsafe (composite)  
**Security score:** 82.75

| Scanner | Badge |
| --- | --- |
| agent-audit-kit | Unsafe |
| cisco-skill-scanner | Caution |
| nerlo-behavioral | Unsafe |
| nerlo-install-instruction | Verified |
| nerlo-multi-source | unavailable |
| osv-scanner | Verified |
| trivy | Verified |
| trivy_image | unavailable |

| Severity | Findings |
| --- | --- |
| critical | 0 |
| high | 1 |
| medium | 18 |
| low | 1 |
| informational | 10 |

altr-mcp is NOT recommended for integration: the scan surfaced 0 critical and 1 high-severity findings. Treat the Per-Scanner Detail section as a remediation worklist and re-scan before reconsidering.

## 2. Source Provenance

- **Repository:** https://github.com/altrsoftware/altr-mcp-server
- **Commit scanned:** `unknown`
- **License:** GPL-3.0-or-later
- **Maintainer:** unknown
- **Version:** unknown

## 3. Per-Scanner Detail

### cisco-skill-scanner (v2.0.11) — Caution / 75.0

- **[medium] Undeclared network usage** — Skill code uses network libraries but doesn't declare network requirement (/repo/repo/CHANGELOG.md:None)
- **[informational] Vague skill description** — [mcp_server policy: capability-matches-purpose class; severity low -> informational] Skill description is too short (16 chars). Provide detailed explanation. (/repo/SKILL.md:None)
- **[informational] Skill does not specify a license** — Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms. (/repo/SKILL.md:None)
- **[medium] Hardcoded password or secret in variable** — Pattern detected: toke**** (/repo/tests/integration/test_audit.py:338)
- **[medium] Hardcoded password or secret in variable** — Pattern detected: pass**** (/repo/tests/integration/test_database.py:328)
- **[medium] Undeclared network usage** — Skill code uses network libraries but doesn't declare network requirement (/repo/altr_mcp/repo/altr_mcp/instructions.md:None)
- **[informational] Vague skill description** — [mcp_server policy: capability-matches-purpose class; severity low -> informational] Skill description is too short (16 chars). Provide detailed explanation. (/repo/altr_mcp/SKILL.md:None)
- **[informational] Skill name does not follow agent skills naming rules** — Skill name 'altr_mcp' is invalid. Agent skills require lowercase letters, numbers, and hyphens only, with a maximum length of 64 characters. (/repo/altr_mcp/SKILL.md:None)
- **[informational] Skill does not specify a license** — Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms. (/repo/altr_mcp/SKILL.md:None)
- **[informational] Vague skill description** — [mcp_server policy: capability-matches-purpose class; severity low -> informational] Skill description is too short (16 chars). Provide detailed explanation. (/repo/docs/SKILL.md:None)
- **[informational] Skill does not specify a license** — Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms. (/repo/docs/SKILL.md:None)
- **[informational] Vague skill description** — [mcp_server policy: capability-matches-purpose class; severity low -> informational] Skill description is too short (16 chars). Provide detailed explanation. (/repo/.github/ISSUE_TEMPLATE/SKILL.md:None)
- **[informational] Skill name does not follow agent skills naming rules** — Skill name 'Bug report' is invalid. Agent skills require lowercase letters, numbers, and hyphens only, with a maximum length of 64 characters. (/repo/.github/ISSUE_TEMPLATE/SKILL.md:None)
- **[informational] Skill does not specify a license** — Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms. (/repo/.github/ISSUE_TEMPLATE/SKILL.md:None)

### agent-audit-kit (v0.3.26) — Unsafe / 33.0

- **[medium] MCP server command uses relative path** — The command uses a relative path that can be hijacked via PATH manipulation. (.mcp.json:5)
- **[low] MCP server repo missing SECURITY.md or security_contact** — A repository whose name or pyproject keywords declare it as an MCP server ships without a top-level SECURITY.md AND without a 'security_contact' entry in marketplace.json / pyproject.toml / package.json. Anthropic's April 2026 SECURITY.md guidance makes this the baseline expectation so researchers have a channel. (SECURITY.md:None)
- **[medium] MCP task has no TTL or cancellation path** — A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs. (altr_mcp/utils/telemetry.py:None)
- **[medium] MCP task has no TTL or cancellation path** — A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs. (altr_mcp/utils/classification.py:None)
- **[medium] MCP task has no TTL or cancellation path** — A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs. (altr_mcp/utils/sidecar_config.py:None)
- **[medium] MCP task has no TTL or cancellation path** — A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs. (altr_mcp/tools/telemetry.py:None)
- **[medium] MCP task has no TTL or cancellation path** — A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs. (altr_mcp/tools/classification.py:None)
- **[medium] MCP task has no TTL or cancellation path** — A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs. (altr_mcp/tools/sidecar_config.py:None)
- **[medium] MCP task has no TTL or cancellation path** — A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs. (tests/integration/test_telemetry.py:None)
- **[medium] MCP task has no TTL or cancellation path** — A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs. (tests/integration/test_sidecar_config.py:None)
- **[medium] Third-party GitHub Action not pinned by full commit SHA** — A workflow in '.github/workflows/' uses a third-party Action ('owner/action@ref') where 'ref' is a tag or branch name instead of a 40-character commit SHA. A repo-takeover of the Action's publisher can re-point the tag to a malicious revision — the downstream repo consuming it will happily run the new code with 'GITHUB_TOKEN' and write permissions. GitHub's April 2026 Security Roadmap ships Immutable Actions and makes SHA pinning the default policy. (.github/workflows/ci.yml:22)
- **[medium] Third-party GitHub Action not pinned by full commit SHA** — A workflow in '.github/workflows/' uses a third-party Action ('owner/action@ref') where 'ref' is a tag or branch name instead of a 40-character commit SHA. A repo-takeover of the Action's publisher can re-point the tag to a malicious revision — the downstream repo consuming it will happily run the new code with 'GITHUB_TOKEN' and write permissions. GitHub's April 2026 Security Roadmap ships Immutable Actions and makes SHA pinning the default policy. (.github/workflows/security.yml:29)
- **[medium] Third-party GitHub Action not pinned by full commit SHA** — A workflow in '.github/workflows/' uses a third-party Action ('owner/action@ref') where 'ref' is a tag or branch name instead of a 40-character commit SHA. A repo-takeover of the Action's publisher can re-point the tag to a malicious revision — the downstream repo consuming it will happily run the new code with 'GITHUB_TOKEN' and write permissions. GitHub's April 2026 Security Roadmap ships Immutable Actions and makes SHA pinning the default policy. (.github/workflows/publish.yml:24)
- **[medium] Third-party GitHub Action not pinned by full commit SHA** — A workflow in '.github/workflows/' uses a third-party Action ('owner/action@ref') where 'ref' is a tag or branch name instead of a 40-character commit SHA. A repo-takeover of the Action's publisher can re-point the tag to a malicious revision — the downstream repo consuming it will happily run the new code with 'GITHUB_TOKEN' and write permissions. GitHub's April 2026 Security Roadmap ships Immutable Actions and makes SHA pinning the default policy. (.github/workflows/publish.yml:44)

### nerlo-behavioral (v0.1.0) — Unsafe / 59.0

- **[high] opt.nerlo-rules.nerlo-py-secret-to-network-egress** — A secret / environment variable / token value flows into a network request (requests / httpx / urllib / socket). This is the postmark-mcp supply-chain exfiltration shape: a credential read from the environment is shipped off-box. Confirm the egress is expected and the value is not being exfiltrated to an attacker-controlled host. (/repo/altr_mcp/utils/audit.py:36)

### nerlo-install-instruction (v0.1.0) — Verified / 95.0

- **[medium] opt.nerlo-rules.nerlo-install-run-bundled-artifact** — Documentation instructs running or double-clicking a bundled/opaque artifact (e.g. "run resource.txt", "execute install.sh", "double-click setup.exe"). This is the FakeGit README shape, where the payload ships as a file the docs tell you to run. Verify the artifact is inspectable and expected — opaque bundled executables directed by docs warrant review. (/repo/README.md:45)

### nerlo-multi-source (v0.1.0) — unavailable / n/a

No findings.

### trivy (v0.71.0) — Verified / 100.0

No findings.

### osv-scanner (v2.3.8) — Verified / 100.0

No findings.

### trivy_image (v0.71.0) — unavailable / n/a

No findings.

## 4. Threat Model

Threat model synthesis has not yet run for this scan. This section is generated by the registry's LLM pipeline (Req 22.3) and will appear in the next regeneration of this report.

## 5. Audit Chain

- **Scan job:** `c9a2ad2e-93c8-4a3f-99f8-04d6b8715146`
- **Completed:** 2026-07-29T19:19:35.841165+00:00
- **Scanner base image:** `us-central1-docker.pkg.dev/nerlo-vsk-prod/nerlo/scanner-base@sha256:18193e789f73339d5d3d9d784011bdb7c9af4b815925f756cc1dc842ecb3fe2d`
- **AI decision log entries:** 2
  - `c6951dc5-ad74-48f3-83b7-d94389396e99`
  - `51830e50-ed0a-49d3-a8a9-8d897f6ddcb9`

## 6. Appendix — Raw Scanner Output

```json
[
  {
    "scanner_name": "cisco-skill-scanner",
    "scanner_version": "2.0.11",
    "score": 75.0,
    "scanner_badge": "Caution",
    "findings": [
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "medium",
        "category": "unauthorized_tool_use",
        "file_path": "/repo/repo/CHANGELOG.md",
        "line_number": null,
        "rule_identifier": "TOOL_ABUSE_UNDECLARED_NETWORK",
        "title": "Undeclared network usage",
        "description": "Skill code uses network libraries but doesn't declare network requirement",
        "remediation": "Declare network usage in compatibility field or remove network calls"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "social_engineering",
        "file_path": "/repo/SKILL.md",
        "line_number": null,
        "rule_identifier": "SOCIAL_ENG_VAGUE_DESCRIPTION",
        "title": "Vague skill description",
        "description": "[mcp_server policy: capability-matches-purpose class; severity low -> informational] Skill description is too short (16 chars). Provide detailed explanation.",
        "remediation": "Provide a clear, detailed description of what the skill does and when to use it"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo/SKILL.md",
        "line_number": null,
        "rule_identifier": "MANIFEST_MISSING_LICENSE",
        "title": "Skill does not specify a license",
        "description": "Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms.",
        "remediation": "Add 'license' field to SKILL.md frontmatter (e.g., MIT, Apache-2.0)"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "medium",
        "category": "hardcoded_secrets",
        "file_path": "/repo/tests/integration/test_audit.py",
        "line_number": 338,
        "rule_identifier": "SECRET_PASSWORD_VAR",
        "title": "Hardcoded password or secret in variable",
        "description": "Pattern detected: toke****",
        "remediation": "Use environment variables or secure vaults for secrets"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "medium",
        "category": "hardcoded_secrets",
        "file_path": "/repo/tests/integration/test_database.py",
        "line_number": 328,
        "rule_identifier": "SECRET_PASSWORD_VAR",
        "title": "Hardcoded password or secret in variable",
        "description": "Pattern detected: pass****",
        "remediation": "Use environment variables or secure vaults for secrets"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "medium",
        "category": "unauthorized_tool_use",
        "file_path": "/repo/altr_mcp/repo/altr_mcp/instructions.md",
        "line_number": null,
        "rule_identifier": "TOOL_ABUSE_UNDECLARED_NETWORK",
        "title": "Undeclared network usage",
        "description": "Skill code uses network libraries but doesn't declare network requirement",
        "remediation": "Declare network usage in compatibility field or remove network calls"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "social_engineering",
        "file_path": "/repo/altr_mcp/SKILL.md",
        "line_number": null,
        "rule_identifier": "SOCIAL_ENG_VAGUE_DESCRIPTION",
        "title": "Vague skill description",
        "description": "[mcp_server policy: capability-matches-purpose class; severity low -> informational] Skill description is too short (16 chars). Provide detailed explanation.",
        "remediation": "Provide a clear, detailed description of what the skill does and when to use it"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo/altr_mcp/SKILL.md",
        "line_number": null,
        "rule_identifier": "MANIFEST_INVALID_NAME",
        "title": "Skill name does not follow agent skills naming rules",
        "description": "Skill name 'altr_mcp' is invalid. Agent skills require lowercase letters, numbers, and hyphens only, with a maximum length of 64 characters.",
        "remediation": "Rename the skill to match `[a-z0-9-]{1,64}` (e.g., 'pdf-processing')"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo/altr_mcp/SKILL.md",
        "line_number": null,
        "rule_identifier": "MANIFEST_MISSING_LICENSE",
        "title": "Skill does not specify a license",
        "description": "Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms.",
        "remediation": "Add 'license' field to SKILL.md frontmatter (e.g., MIT, Apache-2.0)"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "social_engineering",
        "file_path": "/repo/docs/SKILL.md",
        "line_number": null,
        "rule_identifier": "SOCIAL_ENG_VAGUE_DESCRIPTION",
        "title": "Vague skill description",
        "description": "[mcp_server policy: capability-matches-purpose class; severity low -> informational] Skill description is too short (16 chars). Provide detailed explanation.",
        "remediation": "Provide a clear, detailed description of what the skill does and when to use it"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo/docs/SKILL.md",
        "line_number": null,
        "rule_identifier": "MANIFEST_MISSING_LICENSE",
        "title": "Skill does not specify a license",
        "description": "Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms.",
        "remediation": "Add 'license' field to SKILL.md frontmatter (e.g., MIT, Apache-2.0)"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "social_engineering",
        "file_path": "/repo/.github/ISSUE_TEMPLATE/SKILL.md",
        "line_number": null,
        "rule_identifier": "SOCIAL_ENG_VAGUE_DESCRIPTION",
        "title": "Vague skill description",
        "description": "[mcp_server policy: capability-matches-purpose class; severity low -> informational] Skill description is too short (16 chars). Provide detailed explanation.",
        "remediation": "Provide a clear, detailed description of what the skill does and when to use it"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo/.github/ISSUE_TEMPLATE/SKILL.md",
        "line_number": null,
        "rule_identifier": "MANIFEST_INVALID_NAME",
        "title": "Skill name does not follow agent skills naming rules",
        "description": "Skill name 'Bug report' is invalid. Agent skills require lowercase letters, numbers, and hyphens only, with a maximum length of 64 characters.",
        "remediation": "Rename the skill to match `[a-z0-9-]{1,64}` (e.g., 'pdf-processing')"
      },
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo/.github/ISSUE_TEMPLATE/SKILL.md",
        "line_number": null,
        "rule_identifier": "MANIFEST_MISSING_LICENSE",
        "title": "Skill does not specify a license",
        "description": "Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms.",
        "remediation": "Add 'license' field to SKILL.md frontmatter (e.g., MIT, Apache-2.0)"
      }
    ],
    "execution_duration_seconds": 40.39865155899315,
    "status": "complete",
    "examined": {
      "unit": "skills",
      "count": 4
    },
    "metadata": {
      "source": "pypi",
      "source_url": "https://pypi.org/project/cisco-ai-skill-scanner/2.0.11/",
      "report_type": "cisco-skill-sast",
      "analyzers_used": [
        "bytecode",
        "pipeline",
        "static_analyzer"
      ],
      "skills_scanned": [
        "repo",
        "altr_mcp",
        "docs",
        "Bug report"
      ],
      "install_command": "pip install --require-hashes -r docker/scanner-base/cisco-skill-scanner/requirements.txt",
      "severity_counts": {
        "low": 0,
        "high": 0,
        "medium": 4,
        "critical": 0,
        "informational": 10
      },
      "artifact_type_policy": "mcp_server",
      "downweighted_findings": 4
    },
    "display_score": 75.0,
    "display_badge": "Caution"
  },
  {
    "scanner_name": "agent-audit-kit",
    "scanner_version": "0.3.26",
    "score": 33.0,
    "scanner_badge": "Unsafe",
    "findings": [
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": ".mcp.json",
        "line_number": 5,
        "rule_identifier": "AAK-MCP-006",
        "title": "MCP server command uses relative path",
        "description": "The command uses a relative path that can be hijacked via PATH manipulation.",
        "remediation": "Use absolute paths for MCP server executables."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "low",
        "category": "supply-chain",
        "file_path": "SECURITY.md",
        "line_number": null,
        "rule_identifier": "AAK-SEC-MD-001",
        "title": "MCP server repo missing SECURITY.md or security_contact",
        "description": "A repository whose name or pyproject keywords declare it as an MCP server ships without a top-level SECURITY.md AND without a `security_contact` entry in marketplace.json / pyproject.toml / package.json. Anthropic's April 2026 SECURITY.md guidance makes this the baseline expectation so researchers have a channel.",
        "remediation": "Add SECURITY.md at the repo root with a disclosure email and response SLA; OR add `security_contact` to the project manifest."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "altr_mcp/utils/telemetry.py",
        "line_number": null,
        "rule_identifier": "AAK-TASKS-003",
        "title": "MCP task has no TTL or cancellation path",
        "description": "A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs.",
        "remediation": "Set a TTL on every task; expose a cancellation endpoint that zeroizes inputs and credentials."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "altr_mcp/utils/classification.py",
        "line_number": null,
        "rule_identifier": "AAK-TASKS-003",
        "title": "MCP task has no TTL or cancellation path",
        "description": "A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs.",
        "remediation": "Set a TTL on every task; expose a cancellation endpoint that zeroizes inputs and credentials."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "altr_mcp/utils/sidecar_config.py",
        "line_number": null,
        "rule_identifier": "AAK-TASKS-003",
        "title": "MCP task has no TTL or cancellation path",
        "description": "A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs.",
        "remediation": "Set a TTL on every task; expose a cancellation endpoint that zeroizes inputs and credentials."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "altr_mcp/tools/telemetry.py",
        "line_number": null,
        "rule_identifier": "AAK-TASKS-003",
        "title": "MCP task has no TTL or cancellation path",
        "description": "A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs.",
        "remediation": "Set a TTL on every task; expose a cancellation endpoint that zeroizes inputs and credentials."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "altr_mcp/tools/classification.py",
        "line_number": null,
        "rule_identifier": "AAK-TASKS-003",
        "title": "MCP task has no TTL or cancellation path",
        "description": "A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs.",
        "remediation": "Set a TTL on every task; expose a cancellation endpoint that zeroizes inputs and credentials."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "altr_mcp/tools/sidecar_config.py",
        "line_number": null,
        "rule_identifier": "AAK-TASKS-003",
        "title": "MCP task has no TTL or cancellation path",
        "description": "A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs.",
        "remediation": "Set a TTL on every task; expose a cancellation endpoint that zeroizes inputs and credentials."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "tests/integration/test_telemetry.py",
        "line_number": null,
        "rule_identifier": "AAK-TASKS-003",
        "title": "MCP task has no TTL or cancellation path",
        "description": "A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs.",
        "remediation": "Set a TTL on every task; expose a cancellation endpoint that zeroizes inputs and credentials."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "mcp-config",
        "file_path": "tests/integration/test_sidecar_config.py",
        "line_number": null,
        "rule_identifier": "AAK-TASKS-003",
        "title": "MCP task has no TTL or cancellation path",
        "description": "A task record has no expiration and no cancellation endpoint. Orphaned tasks accumulate forever, including their inputs.",
        "remediation": "Set a TTL on every task; expose a cancellation endpoint that zeroizes inputs and credentials."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "supply-chain",
        "file_path": ".github/workflows/ci.yml",
        "line_number": 22,
        "rule_identifier": "AAK-GHA-IMMUTABLE-001",
        "title": "Third-party GitHub Action not pinned by full commit SHA",
        "description": "A workflow in `.github/workflows/` uses a third-party Action (`owner/action@ref`) where `ref` is a tag or branch name instead of a 40-character commit SHA. A repo-takeover of the Action's publisher can re-point the tag to a malicious revision \u2014 the downstream repo consuming it will happily run the new code with `GITHUB_TOKEN` and write permissions. GitHub's April 2026 Security Roadmap ships Immutable Actions and makes SHA pinning the default policy.",
        "remediation": "Repin third-party Actions to a 40-character commit SHA and add a `# v1.2.3`-style trailing comment for humans. First-party Actions under `actions/` and `github/` are exempt (they now ship Immutable Actions). Dependabot will auto-bump SHA pins when `update-type: all` is set."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "supply-chain",
        "file_path": ".github/workflows/security.yml",
        "line_number": 29,
        "rule_identifier": "AAK-GHA-IMMUTABLE-001",
        "title": "Third-party GitHub Action not pinned by full commit SHA",
        "description": "A workflow in `.github/workflows/` uses a third-party Action (`owner/action@ref`) where `ref` is a tag or branch name instead of a 40-character commit SHA. A repo-takeover of the Action's publisher can re-point the tag to a malicious revision \u2014 the downstream repo consuming it will happily run the new code with `GITHUB_TOKEN` and write permissions. GitHub's April 2026 Security Roadmap ships Immutable Actions and makes SHA pinning the default policy.",
        "remediation": "Repin third-party Actions to a 40-character commit SHA and add a `# v1.2.3`-style trailing comment for humans. First-party Actions under `actions/` and `github/` are exempt (they now ship Immutable Actions). Dependabot will auto-bump SHA pins when `update-type: all` is set."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "supply-chain",
        "file_path": ".github/workflows/publish.yml",
        "line_number": 24,
        "rule_identifier": "AAK-GHA-IMMUTABLE-001",
        "title": "Third-party GitHub Action not pinned by full commit SHA",
        "description": "A workflow in `.github/workflows/` uses a third-party Action (`owner/action@ref`) where `ref` is a tag or branch name instead of a 40-character commit SHA. A repo-takeover of the Action's publisher can re-point the tag to a malicious revision \u2014 the downstream repo consuming it will happily run the new code with `GITHUB_TOKEN` and write permissions. GitHub's April 2026 Security Roadmap ships Immutable Actions and makes SHA pinning the default policy.",
        "remediation": "Repin third-party Actions to a 40-character commit SHA and add a `# v1.2.3`-style trailing comment for humans. First-party Actions under `actions/` and `github/` are exempt (they now ship Immutable Actions). Dependabot will auto-bump SHA pins when `update-type: all` is set."
      },
      {
        "tool_name": "agent-audit-kit",
        "severity": "medium",
        "category": "supply-chain",
        "file_path": ".github/workflows/publish.yml",
        "line_number": 44,
        "rule_identifier": "AAK-GHA-IMMUTABLE-001",
        "title": "Third-party GitHub Action not pinned by full commit SHA",
        "description": "A workflow in `.github/workflows/` uses a third-party Action (`owner/action@ref`) where `ref` is a tag or branch name instead of a 40-character commit SHA. A repo-takeover of the Action's publisher can re-point the tag to a malicious revision \u2014 the downstream repo consuming it will happily run the new code with `GITHUB_TOKEN` and write permissions. GitHub's April 2026 Security Roadmap ships Immutable Actions and makes SHA pinning the default policy.",
        "remediation": "Repin third-party Actions to a 40-character commit SHA and add a `# v1.2.3`-style trailing comment for humans. First-party Actions under `actions/` and `github/` are exempt (they now ship Immutable Actions). Dependabot will auto-bump SHA pins when `update-type: all` is set."
      }
    ],
    "execution_duration_seconds": 24.547760620014742,
    "status": "complete",
    "examined": {
      "unit": "files",
      "count": 96
    },
    "metadata": {
      "source": "pypi",
      "source_url": "https://pypi.org/project/agent-audit-kit/0.3.26/",
      "report_type": "agent-audit-kit-sast",
      "install_command": "pip install --require-hashes -r docker/scanner-base/agent-audit-kit/requirements.txt",
      "rules_evaluated": 211,
      "severity_counts": {
        "low": 1,
        "high": 0,
        "medium": 13,
        "critical": 0,
        "informational": 0
      }
    },
    "display_score": 33.0,
    "display_badge": "Unsafe"
  },
  {
    "scanner_name": "nerlo-behavioral",
    "scanner_version": "0.1.0",
    "score": 59.0,
    "scanner_badge": "Unsafe",
    "findings": [
      {
        "tool_name": "nerlo-behavioral",
        "severity": "high",
        "category": "data-exfiltration",
        "file_path": "/repo/altr_mcp/utils/audit.py",
        "line_number": 36,
        "rule_identifier": "opt.nerlo-rules.nerlo-py-secret-to-network-egress",
        "title": "opt.nerlo-rules.nerlo-py-secret-to-network-egress",
        "description": "A secret / environment variable / token value flows into a network request (requests / httpx / urllib / socket). This is the postmark-mcp supply-chain exfiltration shape: a credential read from the environment is shipped off-box. Confirm the egress is expected and the value is not being exfiltrated to an attacker-controlled host.",
        "remediation": null
      }
    ],
    "execution_duration_seconds": 46.71690387401031,
    "status": "complete",
    "examined": {
      "unit": "files",
      "count": 35
    },
    "metadata": {
      "source": "nerlo-original",
      "source_url": "https://github.com/nerlo-ai/nerlo",
      "report_type": "nerlo-behavioral",
      "ruleset_path": "/opt/nerlo-rules/exfiltration.yaml",
      "ruleset_paths": [
        "/opt/nerlo-rules/exfiltration.yaml",
        "/opt/nerlo-rules/clipboard_exfiltration.yaml",
        "/opt/nerlo-rules/rce_endpoint.yaml",
        "/opt/nerlo-rules/taint_egress.yaml"
      ],
      "install_command": "pip install 'semgrep==1.97.0'",
      "severity_counts": {
        "low": 0,
        "high": 1,
        "medium": 0,
        "critical": 0,
        "informational": 0
      },
      "merged_invocation": true
    },
    "display_score": 59.0,
    "display_badge": "Unsafe"
  },
  {
    "scanner_name": "nerlo-install-instruction",
    "scanner_version": "0.1.0",
    "score": 95.0,
    "scanner_badge": "Verified",
    "findings": [
      {
        "tool_name": "nerlo-install-instruction",
        "severity": "medium",
        "category": "install-instruction-run",
        "file_path": "/repo/README.md",
        "line_number": 45,
        "rule_identifier": "opt.nerlo-rules.nerlo-install-run-bundled-artifact",
        "title": "opt.nerlo-rules.nerlo-install-run-bundled-artifact",
        "description": "Documentation instructs running or double-clicking a bundled/opaque artifact (e.g. \"run resource.txt\", \"execute install.sh\", \"double-click setup.exe\"). This is the FakeGit README shape, where the payload ships as a file the docs tell you to run. Verify the artifact is inspectable and expected \u2014 opaque bundled executables directed by docs warrant review.",
        "remediation": null
      }
    ],
    "execution_duration_seconds": 46.72376812301809,
    "status": "complete",
    "examined": {
      "unit": "files",
      "count": 22
    },
    "metadata": {
      "source": "nerlo-original",
      "source_url": "https://github.com/nerlo-ai/nerlo",
      "report_type": "nerlo-install-instruction",
      "ruleset_path": "/opt/nerlo-rules/install_instructions.yaml",
      "ruleset_paths": [
        "/opt/nerlo-rules/install_instructions.yaml",
        "/opt/nerlo-rules/cursor_rules.yaml"
      ],
      "install_command": "pip install 'semgrep==1.97.0'",
      "severity_counts": {
        "low": 0,
        "high": 0,
        "medium": 1,
        "critical": 0,
        "informational": 0
      },
      "merged_invocation": true
    },
    "display_score": 95.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "nerlo-multi-source",
    "scanner_version": "0.1.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 11.4403747789911,
    "status": "not_applicable",
    "examined": null,
    "metadata": {
      "source": "nerlo-original",
      "per_source": [],
      "report_type": "nerlo-multi-source",
      "diverged_sources": [],
      "published_surfaces_scanned": 0
    },
    "display_score": null,
    "display_badge": "unavailable"
  },
  {
    "scanner_name": "trivy",
    "scanner_version": "0.71.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 0.4281242739816662,
    "status": "complete",
    "examined": {
      "unit": "manifests",
      "count": 1
    },
    "metadata": {
      "source": "github-releases",
      "source_url": "https://github.com/aquasecurity/trivy/releases/tag/v0.71.0",
      "report_type": "filesystem-vulnerability",
      "install_command": "curl -sfL -o /tmp/trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.71.0/trivy_0.71.0_Linux-64bit.deb && echo '<sha256>  /tmp/trivy.deb' | sha256sum -c - && dpkg -i /tmp/trivy.deb",
      "manifests_scanned": [
        "uv.lock"
      ]
    },
    "display_score": 100.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "osv-scanner",
    "scanner_version": "2.3.8",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 1.5323171060008463,
    "status": "complete",
    "examined": null,
    "metadata": {
      "source": "github-releases",
      "source_url": "https://github.com/google/osv-scanner/releases/tag/v2.3.8",
      "report_type": "osv-vulnerability",
      "ecosystems_seen": [],
      "install_command": "curl -sfL -o /usr/local/bin/osv-scanner https://github.com/google/osv-scanner/releases/download/v2.3.8/osv-scanner_linux_amd64 && echo '<sha256>  /usr/local/bin/osv-scanner' | sha256sum -c - && chmod +x /usr/local/bin/osv-scanner",
      "manifests_scanned": [],
      "finding_id_aliases": {},
      "cross_scanner_correlation": {
        "only_osv": [],
        "only_trivy": [],
        "intersection_ids": []
      }
    },
    "display_score": 100.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "trivy_image",
    "scanner_version": "0.71.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 4.3469975935295224e-05,
    "status": "not_applicable",
    "examined": {
      "unit": "image_targets",
      "count": 0
    },
    "metadata": {
      "reason": "no OCI image acquired for this artifact"
    },
    "display_score": null,
    "display_badge": "unavailable"
  }
]
```
