T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:49- Finding
Full Secret Values Are Exposed Through JSON Scan Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a local secret-scanning hook with a coherent purpose, but it can expose detected secrets in its own output and has unsafe hook-install behavior.
Review before installing. This skill is not clearly malicious, but it is risky for real secrets: detected credentials may appear in terminal or CI logs, existing pre-commit hooks can be overwritten, and staged-content scanning can be bypassed. Use only after fixing redaction, hook installation, staged-blob scanning, and exit-code behavior.
scripts/main.py:49Full Secret Values Are Exposed Through JSON Scan Output
scripts/main.py:65Pre-Commit Hook Scans Working-Tree Files Instead of Staged Content
scripts/main.py:142Explicit File Scans Return Success When Secrets Are Detected
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- AWS Access Key IDs (`AKIA...`)
- AWS Secret Access Keys
- Passwords, secrets, tokens in variable assignments
- GitHub Personal Access Tokens (`ghp_...`)
- GitHub Fine‑Grained Tokens (`github_pat_...`)
- OpenAI API Keys (`sk-...`)
- Bearer tokens
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
./scripts/main.py scan --file config.yaml --file .env
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
./scripts/main.py scan --file config.yaml --file .env
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
(r'(?i)secret\s*=\s*["\']?([^\s"\']{8,})', "Secret"),
(r'(?i)token\s*=\s*["\']?([^\s"\']{8,})', "Token"),
(r'(?i)api_key\s*=\s*["\']?([^\s"\']{8,})', "API Key"),
(r'(?i)ghp_[0-9a-zA-Z]{36}', "GitHub Personal Access Token"),
(r'(?i)github_pat_[0-9a-zA-Z]{40}', "GitHub Fine‑Grained Token"),
(r'(?i)sk-[0-9a-zA-Z]{48}', "OpenAI API Key"),
(r'(?i)Bearer\s+([0-9a-zA-Z._-]{20,})', "Bearer Token"),
The skill declares executable capabilities that imply reading files, writing hooks, and invoking shell commands, but it does not declare an explicit tool scope such as permissions or allowed-tools. That ambiguity weakens reviewability and least-privilege controls, making it easier for a consumer to run a skill with broader access than expected.
The skill states it prints the first 20 characters of detected secrets to the console, which can itself disclose sensitive material into terminal scrollback, CI logs, shell recording tools, or shared debugging transcripts. Even partial secret exposure may be enough to aid credential identification, brute-force reduction, or accidental secondary leakage.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def get_staged_files():
"""Get list of staged files from git."""
try:
result = subprocess.run(
['git', 'diff', '--cached', '--name-only', '--diff-filter=ACM'],
capture_output=True,
text=True,
The install command overwrites .git/hooks/pre-commit without checking for an existing hook, prompting the user, or creating a backup. This can silently replace repository-local security or workflow controls and may be abused to disrupt expected protections or developer processes.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
try:
# Run the script via subprocess
result = subprocess.run(
[sys.executable, os.path.join(os.path.dirname(__file__), '..', 'scripts', 'main.py'),
'scan', '--file', temp_path],
capture_output=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def test_cli_install_simulation():
"""Test install command (simulated, not in a git repo)."""
# This will fail because we're not in a git repo, but we can check the error
result = subprocess.run(
[sys.executable, os.path.join(os.path.dirname(__file__), '..', 'scripts', 'main.py'),
'install'],
capture_output=True,
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
json_start = i
break
if json_start is not None:
# Find the matching closing brace (simplistic: join from start to end)
json_str = '\n'.join(lines[json_start:])
try:
data = json.loads(json_str)
No suspicious patterns detected.