# Security Audit Report — balance-sheet-analyzer

- **Report ID:** `fd9cca1e-7149-4b35-b2b0-4c5cb81d6e97`
- **Generated:** 2026-07-29T06:01:15.213149+00:00
- **Signature:** unsigned (cosign keyless signing runs in CI; Req 22.4)

## 1. Executive Summary

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

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

| Severity | Findings |
| --- | --- |
| critical | 0 |
| high | 4 |
| medium | 0 |
| low | 2 |

balance-sheet-analyzer is NOT recommended for integration: the scan surfaced 0 critical and 4 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/cwstedctw/balance-sheet-analyzer
- **Commit scanned:** `unknown`
- **License:** unknown
- **Maintainer:** unknown
- **Version:** unknown

## 3. Per-Scanner Detail

### agentshield (v1.4.0) — unavailable / n/a

No findings.

### cisco-skill-scanner (v2.0.11) — Verified / 94.5

- **[informational] Skill does not specify a license** — Skill manifest does not include a 'license' field. Specifying a license helps users understand usage terms. (/repo/skills/balance-sheet-analyzer/SKILL.md:None)
- **[low] Vague skill description** — 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)
- **[low] Vague skill description** — Skill description is too short (16 chars). Provide detailed explanation. (/repo/skills/balance-sheet-analyzer/references/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/skills/balance-sheet-analyzer/references/SKILL.md:None)

### agent-audit-kit (v0.3.26) — Caution / 84.0

- **[high] Unsigned marketplace.json manifest** — .claude-plugin/marketplace.json lacks a signature or integrity hash field. An attacker with write access to the marketplace can replace the plugin bundle with no detection. (.claude-plugin/marketplace.json:8)

### bearer (v2.0.2) — Unsafe / 55.0

- **[high] Unsanitized dynamic input in file path** — \#\# Description  Using unsanitized dynamic input to determine file paths can allow attackers to gain access to files and folders outside of the intended scope. This vulnerability occurs when input provided by users is directly used to access the filesystem without proper validation or sanitization.  \#\# Remediations  - **Do not** directly use external input to construct file paths. This can lead to unauthorized file access. - **Do** use a safelist to define accessible paths or directories. Only al (/repo/skills/balance-sheet-analyzer/scripts/calc_ratios.py:388)
- **[high] Unsanitized dynamic input in file path** — \#\# Description  Using unsanitized dynamic input to determine file paths can allow attackers to gain access to files and folders outside of the intended scope. This vulnerability occurs when input provided by users is directly used to access the filesystem without proper validation or sanitization.  \#\# Remediations  - **Do not** directly use external input to construct file paths. This can lead to unauthorized file access. - **Do** use a safelist to define accessible paths or directories. Only al (/repo/skills/balance-sheet-analyzer/scripts/generate_chart.py:389)
- **[high] Unsanitized dynamic input in file path** — \#\# Description  Using unsanitized dynamic input to determine file paths can allow attackers to gain access to files and folders outside of the intended scope. This vulnerability occurs when input provided by users is directly used to access the filesystem without proper validation or sanitization.  \#\# Remediations  - **Do not** directly use external input to construct file paths. This can lead to unauthorized file access. - **Do** use a safelist to define accessible paths or directories. Only al (/repo/skills/balance-sheet-analyzer/scripts/generate_chart.py:423)

### nerlo-behavioral (v0.1.0) — Verified / 100.0

No findings.

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

No findings.

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

No findings.

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

No findings.

### osv-scanner (v2.3.8) — 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:** `9cee5de5-a614-4c5c-838c-24b1ffa1ccfe`
- **Completed:** 2026-07-26T04:40:28.862812+00:00
- **Scanner base image:** `us-central1-docker.pkg.dev/nerlo-vsk-prod/nerlo/scanner-base@sha256:86a3d299a4356dfd5a34cd31cfa9f4c28d236d387691f7c8070086afe5224516`
- **AI decision log entries:** 2
  - `2b7cddb1-0edc-4785-81df-14ed8ca1748d`
  - `3a2561fc-5fa3-4a0c-b9fe-2284a9a72ecb`

## 6. Appendix — Raw Scanner Output

```json
[
  {
    "scanner_name": "agentshield",
    "scanner_version": "1.4.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 1.2617951799184084,
    "status": "not_applicable",
    "examined": null,
    "metadata": {
      "source": "npm",
      "source_url": "https://www.npmjs.com/package/ecc-agentshield",
      "install_command": "npm install -g ecc-agentshield@1.4.0",
      "scans_performed": []
    },
    "display_score": null,
    "display_badge": "unavailable"
  },
  {
    "scanner_name": "cisco-skill-scanner",
    "scanner_version": "2.0.11",
    "score": 94.5,
    "scanner_badge": "Verified",
    "findings": [
      {
        "tool_name": "cisco-skill-scanner",
        "severity": "informational",
        "category": "policy_violation",
        "file_path": "/repo/skills/balance-sheet-analyzer/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": "low",
        "category": "social_engineering",
        "file_path": "/repo/SKILL.md",
        "line_number": null,
        "rule_identifier": "SOCIAL_ENG_VAGUE_DESCRIPTION",
        "title": "Vague skill description",
        "description": "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": "low",
        "category": "social_engineering",
        "file_path": "/repo/skills/balance-sheet-analyzer/references/SKILL.md",
        "line_number": null,
        "rule_identifier": "SOCIAL_ENG_VAGUE_DESCRIPTION",
        "title": "Vague skill description",
        "description": "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/skills/balance-sheet-analyzer/references/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": 74.41673620091751,
    "status": "complete",
    "examined": null,
    "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": [
        "balance-sheet-analyzer",
        "repo",
        "references"
      ],
      "install_command": "pip install --require-hashes -r docker/scanner-base/cisco-skill-scanner/requirements.txt",
      "severity_counts": {
        "low": 2,
        "high": 0,
        "medium": 0,
        "critical": 0,
        "informational": 3
      },
      "artifact_type_policy": "claude_skill"
    },
    "display_score": 94.5,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "agent-audit-kit",
    "scanner_version": "0.3.26",
    "score": 84.0,
    "scanner_badge": "Caution",
    "findings": [
      {
        "tool_name": "agent-audit-kit",
        "severity": "high",
        "category": "supply-chain",
        "file_path": ".claude-plugin/marketplace.json",
        "line_number": 8,
        "rule_identifier": "AAK-MARKETPLACE-001",
        "title": "Unsigned marketplace.json manifest",
        "description": ".claude-plugin/marketplace.json lacks a signature or integrity hash field. An attacker with write access to the marketplace can replace the plugin bundle with no detection.",
        "remediation": "Add a Sigstore signature or subresource-integrity hash to each plugin entry. Verify on install."
      }
    ],
    "execution_duration_seconds": 12.612373756011948,
    "status": "complete",
    "examined": null,
    "metadata": {
      "source": "pypi",
      "source_url": "https://pypi.org/project/agent-audit-kit/0.3.26/",
      "report_type": "agent-audit-kit-sast",
      "files_scanned": 14,
      "install_command": "pip install --require-hashes -r docker/scanner-base/agent-audit-kit/requirements.txt",
      "rules_evaluated": 211,
      "severity_counts": {
        "low": 0,
        "high": 1,
        "medium": 0,
        "critical": 0,
        "informational": 0
      }
    },
    "display_score": 84.0,
    "display_badge": "Caution"
  },
  {
    "scanner_name": "bearer",
    "scanner_version": "2.0.2",
    "score": 55.0,
    "scanner_badge": "Unsafe",
    "findings": [
      {
        "tool_name": "bearer",
        "severity": "high",
        "category": null,
        "file_path": "/repo/skills/balance-sheet-analyzer/scripts/calc_ratios.py",
        "line_number": 388,
        "rule_identifier": null,
        "title": "Unsanitized dynamic input in file path",
        "description": "## Description\n\nUsing unsanitized dynamic input to determine file paths can allow attackers to gain access to files and folders outside of the intended scope. This vulnerability occurs when input provided by users is directly used to access the filesystem without proper validation or sanitization.\n\n## Remediations\n\n- **Do not** directly use external input to construct file paths. This can lead to unauthorized file access.\n- **Do** use a safelist to define accessible paths or directories. Only al",
        "remediation": null
      },
      {
        "tool_name": "bearer",
        "severity": "high",
        "category": null,
        "file_path": "/repo/skills/balance-sheet-analyzer/scripts/generate_chart.py",
        "line_number": 389,
        "rule_identifier": null,
        "title": "Unsanitized dynamic input in file path",
        "description": "## Description\n\nUsing unsanitized dynamic input to determine file paths can allow attackers to gain access to files and folders outside of the intended scope. This vulnerability occurs when input provided by users is directly used to access the filesystem without proper validation or sanitization.\n\n## Remediations\n\n- **Do not** directly use external input to construct file paths. This can lead to unauthorized file access.\n- **Do** use a safelist to define accessible paths or directories. Only al",
        "remediation": null
      },
      {
        "tool_name": "bearer",
        "severity": "high",
        "category": null,
        "file_path": "/repo/skills/balance-sheet-analyzer/scripts/generate_chart.py",
        "line_number": 423,
        "rule_identifier": null,
        "title": "Unsanitized dynamic input in file path",
        "description": "## Description\n\nUsing unsanitized dynamic input to determine file paths can allow attackers to gain access to files and folders outside of the intended scope. This vulnerability occurs when input provided by users is directly used to access the filesystem without proper validation or sanitization.\n\n## Remediations\n\n- **Do not** directly use external input to construct file paths. This can lead to unauthorized file access.\n- **Do** use a safelist to define accessible paths or directories. Only al",
        "remediation": null
      }
    ],
    "execution_duration_seconds": 69.44036304706242,
    "status": "complete",
    "examined": null,
    "metadata": {
      "source": "github-releases",
      "source_url": "https://github.com/Bearer/bearer",
      "report_type": "security",
      "rules_loaded": 554,
      "install_command": "curl -sfL https://raw.githubusercontent.com/Bearer/bearer/main/contrib/install.sh | sh -s -- -b /usr/local/bin \"v2.0.2\"",
      "severity_counts": {
        "low": 0,
        "high": 3,
        "medium": 0,
        "critical": 0,
        "informational": 0
      }
    },
    "display_score": 55.0,
    "display_badge": "Unsafe"
  },
  {
    "scanner_name": "nerlo-behavioral",
    "scanner_version": "0.1.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 64.86823453602847,
    "status": "complete",
    "examined": null,
    "metadata": {
      "source": "nerlo-original",
      "source_url": "https://github.com/nerlo-ai/nerlo",
      "report_type": "nerlo-behavioral",
      "ruleset_path": "/opt/nerlo-rules/exfiltration.yaml",
      "files_scanned": 4,
      "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'",
      "merged_invocation": true
    },
    "display_score": 100.0,
    "display_badge": "Verified"
  },
  {
    "scanner_name": "nerlo-install-instruction",
    "scanner_version": "0.1.0",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 64.86842841503676,
    "status": "complete",
    "examined": null,
    "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",
      "files_scanned": 11,
      "ruleset_paths": [
        "/opt/nerlo-rules/install_instructions.yaml",
        "/opt/nerlo-rules/cursor_rules.yaml"
      ],
      "install_command": "pip install 'semgrep==1.97.0'",
      "merged_invocation": true
    },
    "display_score": 100.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.899240676080808,
    "status": "not_applicable",
    "examined": null,
    "metadata": {
      "source": "nerlo-original",
      "report_type": "nerlo-multi-source",
      "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.6318204560084268,
    "status": "not_applicable",
    "examined": null,
    "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": []
    },
    "display_score": null,
    "display_badge": "unavailable"
  },
  {
    "scanner_name": "osv-scanner",
    "scanner_version": "2.3.8",
    "score": 100.0,
    "scanner_badge": "Verified",
    "findings": [],
    "execution_duration_seconds": 0.6358740589348599,
    "status": "not_applicable",
    "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": null,
    "display_badge": "unavailable"
  }
]
```
