Security-Audit Vault + Plugin (agentic-ventures)
Scope: /Users/marvinkuehlmann/source/agentic-ventures als Vault und Claude-Code-Plugin (Symlink skills/ -> intern/capabilities/skills/). Auditor-Methodik: intern/capabilities/skills/security-audit/SKILL.md, Phase 2 (Secrets), 7 (LLM/Prompt-Injection), 8 (Skill-Supply-Chain), 11 (DSGVO).
Repo-Visibility: PRIVATE (marvin-khl/agentic-ventures, GitHub) — bestaetigt via gh repo view. Senkt das Schadensbild der internen Inhalte deutlich (Voraussetzung: GH-Account-Hygiene + 2FA, ausserhalb dieses Audits).
Findings
F1 — CRIT: Plaintext-Secrets in ~/.claude.json mcpServers
- Severity: CRIT
- Phase: 2 (Secrets) / 8 (MCP-Supply-Chain)
- Befund:
~/.claude.json(User-Home, NICHT im Vault-Repo) enthaelt zwei Live-Tokens im Klartext imenv-Block:github.env.GITHUB_PERSONAL_ACCESS_TOKEN— GH-PATgho_...(write-scope vermutlich, da Plugin-Repos forken/pushen kann)elevenlabs.env.ELEVENLABS_API_KEY—sk_...-Schluessel
- Risiko: Jeder Code-Execution-Bug in einem MCP, jedes neugierige Skill das
cat ~/.claude.jsonausfuehrt, jede Backup-/Sync-/iCloud-Indizierung leakt diese Tokens. Skill-Supply-Chain (siehe F4) macht das real — externe Plugin-Skills laufen mit Marvins User-Rechten und koennen die Datei lesen. - Vergleichsbeispiel: Andere MCPs in derselben Config (
hetzner) machen es richtig:op run -- mcp-hetznermitop://...-Referenz statt Plaintext. - Fix: Beide Tokens nach 1Password verschieben, Eintraege auf
op run-Wrapper umstellen analoghetzner-MCP. Tokens nach Rotation in 1P. ElevenLabs-Key rotieren, da er hier im Audit-Output war (auch wenn ich ihn nicht zitiere — er stand in der Bash-Ausgabe). - Pfad:
~/.claude.json(User-File, kein Vault-Pfad)
F2 — HIGH: skipDangerousModePermissionPrompt: true in ~/.claude/settings.json
- Severity: HIGH
- Phase: 8 (Plugin-Sandbox)
- Befund: Globale Claude-Code-Settings haben
skipDangerousModePermissionPrompt: true. Bedeutet: der Bestaetigungsdialog vor Dangerous-Mode wird uebersprungen. In Kombination mit der breiten Bash-Allowlist (siehe F3) und externen Plugins (F4) verliert Marvin die letzte Bremse vor unkontrollierter Code-Ausfuehrung. - Fix: Auf
falsesetzen oder ganz entfernen. Friction lohnt sich. - Pfad:
~/.claude/settings.json
F3 — HIGH: Project .claude/settings.local.json enthaelt Wildcard-Bash-Permissions
- Severity: HIGH
- Phase: 8
- Befund: Die Project-Allowlist enthaelt mehrere stark generische Eintraege:
Bash(npm install *)— beliebige npm-Pakete ohne Prompt; Supply-Chain-Risiko (typosquatting, malicious post-install scripts).Bash(aws s3 *),Bash(aws lambda *),Bash(aws cloudformation *),Bash(aws ecs *),Bash(aws logs *),Bash(aws configure *)— beliebige Mutations-Calls inkl.aws s3 rm,aws lambda delete-function,aws configure set .... Kein Profil-Gate.Bash(op item *)— beliebige 1Password-Item-Calls ohne Prompt; faktisch Full-Read auf den Vault.Bash(gh api *)— beliebige GitHub-API-Calls inkl. write (POST/DELETE auf Repos, Releases, Secrets).Read(//tmp/**)—//tmpist eine ungewoehnliche Schreibweise; falls als Bypass interpretiert (Doppel-Slash → Root-Match), liest das ggf. mehr als gewuenscht. Pruefen.Read(//Users/marvinkuehlmann/.aws/**)— gibt Lese-Zugriff auf AWS-Credentials/Config inkl. Session-Tokens.
- Risiko: Ein bos-/buggy Skill (oder Prompt-Injection ueber externe Markdown/Email/Inbox-Files) kann diese Permissions ausnutzen ohne Marvin zu fragen.
Read(//Users/.../.aws/**)plusBash(aws s3 *)ist faktisch „delete any bucket”. - Fix: Wildcards aufbrechen. Konkrete Subcommands erlauben (
aws s3 ls,aws s3 cpja;aws s3 rm,aws s3 rbnein).op item *→op item get *(read-only).npm install *raus, lieber pro Session prompten.Read(//Users/.../.aws/**)raus —.aws/credentialsdarf Claude nie sehen.gh api *→gh api -X GET *whitelisten, write-Methoden raus. - Pfad:
/Users/marvinkuehlmann/source/agentic-ventures/.claude/settings.local.json
F4 — MED: Externe Plugin-Marketplaces ohne Pinning, lange Trust-Chain
- Severity: MED
- Phase: 8
- Befund: Aktive externe Marketplaces in
~/.claude/settings.json:every-marketplace(compound-engineering) — kein Pin auf Commit/Tag.coreyhaines31/marketingskills— privater Maintainer, kein Pin.kepano/obsidian-skills— Privatperson.anthropics/skills— offiziell, OK.claude-plugins-official— offiziell, OK.
- Jeder Skill aus diesen Marketplaces kann beim Update beliebig Bash-Blocks einfuegen. Skill-Inhalte sind Prompt-Code — sie werden vom Modell als Anweisungen interpretiert und koennen die Bash-Allowlist (F3) ausnutzen.
- Risiko-Beispiel:
every-marketplaceversioniert die compound-engineering-Skills laufend; ein kompromittierter Commit dort kann z.B. eingit-commit-push-pr-Skill veraendern und in Marvins Workflow Secrets exfiltrieren. - Fix: (a) Marketplaces auf Commit-SHA pinnen sofern Plugin-System das unterstuetzt (siehe
_meta/security.mdfalls dort bereits dokumentiert); (b) Mindestenscoreyhaines31/marketingskillsdeaktivieren wenn nicht aktiv genutzt — laut_externe-skills.mdist Marketing-Disziplin „bewusst nicht eingebunden”, Plugin aber dennoch aktiv; (c) regelmaessigergit logder Marketplace-Forks vor Plugin-Reload. - Pfad:
~/.claude/settings.jsonenabledPlugins+extraKnownMarketplaces
F5 — MED: Sensible Vault-Inhalte committed (Kunden-Stammdaten, USt-IdNr, Telefonnummern, Geheimhaltungs-Context)
- Severity: MED (mitigiert durch Private-Repo, eskaliert wenn Repo je public wird oder geforked)
- Phase: 11 (DSGVO)
- Befund: 260
.md-Files mitvisibility: internal, davon 106 mit echten Kunden-Slugs (Becker, Vibe-Factory, Friseur-im-Sueden, Erlei, Ladezon, …).intern/kunden/ladezon.md— HRB, Steuernummer, GF-Namenintern/kunden/erlei.md— HRB, USt-IdNr DE363248648, Mitarbeiternameintern/kunden/vibe-factory.md— USt-IdNr DE453362151 in Frontmatterintern/projekte/openwebui-vf/2026-05-14-test-plan-use-cases.md— Telefonnummern, Personenrollenintern/runs/2026-05.md— Personennamen + Telefonnummer in Klartextintern/runs/2026-05-13-vf-vault-analyse/...— vertraulicher Mandanten-Kontext
- Risiko: Bei Repo-Visibility-Flip (Public-Klick versehentlich), Backup-Leak, Stolen-Laptop ohne FileVault, oder GitHub-Org-Access-Misconfig haetten Dritte Zugriff auf Auftragsdaten + Personendaten von Kunden. Bei Becker-NDA (Art. 1 (1), Frist 10 Jahre) ist die Existenz der Geschaeftsbeziehung selbst Vertraulich — die schiere Datei-Existenz
intern/kunden/becker*ist NDA-relevant. - Mitigation aktiv: Repo ist privat,
.gitignoreblockt.env*/*--kontakt.md/assets/finanzen/. NDA-PDF (inbox/Geheimhaltungsvereinbarung_BAS_Agentic.pdf) ist??untracked — gut. - Fix: (a) Pre-commit-Hook der
gh repo view --json visibilityprueft und bei Wechsel auf Public hart abbricht; (b) Backup-Pruefung: laeuft iCloud-/Dropbox-Sync auf diesem Ordner? Wenn ja: ausschliessen (siehe_meta/security.md); (c) Disk-Verschluesselung (FileVault) verifizieren; (d)assets/firma/partner-materials/2026-04-22-claude-dsgvo-hosting-summary.pdfundassets/firma/brand-assets/agentic-vorschau.pdfsind die einzigen committeten PDFs — sind das wirklich nicht-vertrauliche Assets? Pruefen.
F6 — LOW: Becker-Attachments in inbox/becker-attachments/
- Severity: LOW (untracked, aber riskant fuer kuenftiges Versehen)
- Phase: 11 + 2
- Befund:
inbox/becker-attachments/enthaelt 5 sensible PDFs/DOCX (Angebot, Datenschutzvertrag, Vertragsbedingungen, NDA-related). Aktuell nicht in Git getrackt — verifiziert viagit ls-files inbox/becker-attachments/→ leer. Aber:inbox/ist nur per.gitkeepplus Session-Prompts getrackt; PDFs koennen versehentlich mitgit add inbox/reinrutschen. - Fix:
.gitignore-Eintraginbox/*.pdfundinbox/*-attachments/ergaenzen, damit Kundenanhaenge nie versehentlich committet werden. Geheimhaltungsvereinbarung_BAS_Agentic.pdf ist ebenfalls untracked → mitigiert mit demselben Pattern.
F7 — LOW: Eigene SKILL.md-Files mit Bash-Blocks — Prompt-Injection-Vektor
- Severity: LOW (kein direkter
${ARGUMENTS}-Sink gefunden, aber Risiko bei kuenftigen Aenderungen) - Phase: 7 (LLM-Security)
- Befund: Eigene Skills enthalten teils dichte Bash-Sequenzen:
security-audit/SKILL.md— 27 Bash-Bloecke (am dichtesten)routine-anlegen/SKILL.md— 7qa-staging/SKILL.md— 5mcp-cloud-bereitstellung/SKILL.md— 4mcp-eigenbau/SKILL.md— 3
- Grep nach
${ARGUMENTS}/$1/direkter User-Input-Interpolation: 0 Treffer. Aktuell sicher. - Risiko (zukunftsorientiert): Wenn Marvin oder ein Skill-Creator-Lauf einen Bash-Block mit User-Input-Interpolation einfuegt (z.B.
grep "$ISSUE_TITLE" ...), wird ein Issue-Title mit Backticks/Semikolons zur Shell-Injection. LLM-Skills sind Prompt-Code, der Bash-Befehle vorschlagen kann — alles was reinkommt sollte als untrusted gelten. - Fix: Konvention in
_meta/security.mdergaenzen: „User-Input in SKILL-Bash-Bloecken NIE direkt interpolieren — immer ueber Argumente an ein Tool oder Heredoc-quoted”. Pre-commit-Hook der Skills auf\$\{?[A-Z_]+\}?in Bash-Bloecken scannt waere ideal.
F8 — LOW: External-Plugin Skills sind beim Update sichtbar in Skill-Tool-Liste — Verwechslungsgefahr
- Severity: LOW
- Phase: 7
- Befund: Die
Skill-Tool-Liste zeigt 200+ Skills inkl. Duplikaten (d230a6dd6eb1:doc-coauthoringetc. — Anthropic-Skills cached-id-mode). Marvin merkt sich Skill-Namen nicht (Regel 20). Risiko: Ein bos benannter externer Skill mit Trigger-Phraseemail-schreibenwuerde vom Modell mit dem eigenen verwechselt — Trigger-Map-Override. - Fix: Skill-Auswahl im Routing strikt nach Plugin-Namespace: bei Konflikt zwischen
agentic-ventures:email-schreibenund externem Skill immeragentic-ventures-Namespace bevorzugen. In CLAUDE.md Regel 20 dies explizit machen.
F9 — INFO: Keine echten Tokens in Vault-Files oder Git-History
- Severity: INFO (positiv)
- Phase: 2
- Befund: Vollscan mit
git log -p --allund Repo-Filescan aufsk-ant-,AKIA[0-9A-Z]{16},gh[posu]_,xoxb-,EAA[...]60+,skc_: 0 Treffer in echten Daten (alle Hits insecurity-audit/SKILL.mdPattern-Beispielen oder QA-Checklisten). inbox/Geheimhaltungsvereinbarung_BAS_Agentic.pdfundinbox/becker-attachments/*sind nicht getrackt..env.localist gitignored und enthaelt 4 Zeilen (3 davon Kommentare).
F10 — INFO: .venv/ mit AWS-Botocore-Code committed
- Severity: INFO (kein Secret, aber Bloat + Audit-Noise)
- Befund:
intern/projekte/telefon-assistent-aws/{webapp,livekit-agent,tools-mcp}/.venv/lib/.../{credentials.py,cacert.pem}etc. — Python-Venv-Inhalt wird tracked (nicht gitignored). Keine echten Credentials drin, nur Library-Source. Aber: blaeht Repo auf und macht Secret-Scans laut. - Fix:
.venv/zu.gitignoreergaenzen und einmaliggit rm -r --cached intern/projekte/telefon-assistent-aws/*/.venv/.
Positive Befunde
- Repo private bestaetigt.
.gitignoredeckt Secrets-Pattern und PII-Pattern (*--kontakt.md) korrekt ab.- Hetzner-MCP benutzt
op://-Reference statt Plaintext-Token (best-practice). - NDA-PDF + Becker-Attachments untracked.
- Keine echten API-Keys/Tokens in
.md-Files oder Git-History.
Top 3 Sofortmassnahmen
- F1 —
~/.claude.jsonSecrets in 1Password verschieben. ElevenLabs-Key + GitHub-PAT rotieren, aufop run-Wrapper umstellen analog Hetzner-MCP. Beide Tokens wurden im Bash-Output dieses Audits sichtbar — Rotation ist nicht optional. Aufwand: 20 Minuten. - F3 — Project-Allowlist
.claude/settings.local.jsonentschaerfen. Mindestens raus:Bash(aws s3 *),Bash(aws lambda *),Bash(aws configure *),Bash(op item *),Bash(gh api *),Bash(npm install *),Read(//Users/marvinkuehlmann/.aws/**). Wildcards durch konkrete read-only-Subcommands ersetzen. Plus F2:skipDangerousModePermissionPrompt: false. Aufwand: 15 Minuten. - F5/F6 — Repo-Visibility-Guard + Inbox-Schutz. Pre-commit-Hook der
gh repo view --json isPrivateprueft und beifalseabbricht;.gitignoreuminbox/*.pdfundinbox/*-attachments/ergaenzen; FileVault + iCloud-Sync-Status verifizieren. Aufwand: 30 Minuten.