T09 · Insecure Skill Coding Practices
- Location
scripts/git_inspector.py:191- Finding
Unredacted Git Metadata and Historical Diffs May Expose Sensitive Information
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This code-context skill is mostly purpose-aligned, but it can expose Git history, contributor metadata, raw diffs, and saved reports while claiming redaction that is not implemented.
Review before installing in workplace or private repositories. Treat generated reports as sensitive, avoid exporting raw Git history unless necessary, and do not rely on the advertised automatic redaction. External Slack or collaboration integrations should only be added with explicit admin approval, least-privilege tokens, and clear data-handling rules.
scripts/git_inspector.py:191Unredacted Git Metadata and Historical Diffs May Expose Sensitive Information
scripts/ownership_tracker.py:154Git Argument Injection Through Unvalidated Path and Context Parameters
The supplied code does support part of the declared description: it analyzes codebase structure, basic dependencies, entry points, and core modules. However, the declared purpose significantly overstates the skill’s capabilities. There is no interaction with Git metadata, commit history, blame/ownership information, maintainers, reviewers, or collaboration systems. It does not trace design decisions or explain historical rationale; it only performs static file scanning and simple dependency extraction. Therefore the description does not accurately represent the actual behavior, because several prominent declared capabilities are absent.
The implementation does match part of the description: it analyzes code dependencies, call structure, and change impact within a Python codebase. However, the declared purpose substantially overstates the skill’s capabilities. The code does not inspect Git metadata, blame/history, authorship, maintainers, review context, or collaboration signals. It also does not generally explain design decisions or overall codebase structure beyond function/class relationships discovered in Python files. Because the declared description presents a much broader multi-source code intelligence capability than the actual code provides, this is a description-behavior mismatch.
The documented use of Git history, blame/ownership data, and contributor activity surfaces privacy-sensitive employee metadata without a clear user-facing warning or governance guidance at the point of use. In a workplace tool, this can enable unnecessary profiling, attribution misuse, or exposure of internal collaboration patterns beyond what users may expect from a code-context skill.
The README includes example code that retrieves Slack conversation data via an external API, expanding the skill from local code-context analysis into collection of third-party workspace data. This creates a real data exposure risk because tokens, message contents, and workspace context may be accessed or transmitted without clear scope limits, consent, or data-handling controls.
The Slack API example lacks warnings about sending or retrieving workspace data through an external service and shows bearer-token usage without secure handling guidance. This is dangerous because implementers may copy the pattern directly, leading to overbroad token scopes, accidental credential leakage, and unauthorized access to internal communications.
The documented call to api.slack.com represents external transmission of potentially sensitive project or workplace context, which is materially riskier than local repository analysis. In this skill's context, external communications are more dangerous because the tool is framed as an internal code-understanding assistant, so users may not expect data to leave the local environment.
def fetch_slack_context(self, message_id):
response = requests.get(
f"https://api.slack.com/conversations.history?...",
headers={"Authorization": "Bearer ..."}
)
return response.json()
The skill describes capabilities that inherently require file access, repository inspection, and likely shell execution, but it declares no explicit tool scope or permission boundaries. That creates an overbroad execution surface where an agent could access repositories, inspect sensitive files, or invoke commands without user-visible restriction.
The invocation description is extremely broad, so the skill could be auto-selected for many ordinary code questions and then perform expansive repository, history, or collaborator analysis beyond what the user expected. In a skill system with tools, overbroad triggering increases the chance of unnecessary access to sensitive codebase, contributor, or workflow metadata.
The skill explicitly proposes analyzing maintainers, recent modifiers, responsible parties, and historical activity timing, but the description does not clearly warn that contributor activity and communication metadata will be processed. This can expose behavioral and personnel metadata that is more sensitive than ordinary source code context, especially in workplace environments.
The skill advertises retrieval from Slack/钉钉/企业微信, Confluence/Notion, JIRA/Trello, and even CI/CD trigger/query integration without warning users about external data access or side effects. Accessing collaboration systems can expose confidential discussions and documents, and CI/CD triggering introduces active operational impact rather than passive analysis.
This code file contains natural-language strings that force a specific language for docstrings, status messages, errors, and CLI usage. Under the policy, hard-coding a language without user opt-in or a documented justification is a natural-language policy violation.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _validate_git_repo(self):
"""验证是否为 Git 仓库"""
try:
result = subprocess.run(
['git', 'rev-parse', '--git-dir'],
cwd=self.project_root,
capture_output=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
if file_path:
search_cmd.extend(['--', file_path])
result = subprocess.run(
search_cmd,
cwd=self.project_root,
capture_output=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _get_file_commits(self, file_path: str, max_commits: int) -> List[Dict]:
"""获取文件的提交历史"""
result = subprocess.run(
['git', 'log', '--format=%H|%ai|%an', '--follow',
'--', file_path, '-n', str(max_commits)],
cwd=self.project_root,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _get_commit_details(self, commit_hash: str) -> Dict:
"""获取提交的详细信息"""
# 获取提交信息
message_result = subprocess.run(
['git', 'log', '-1', '--format=%B', commit_hash],
cwd=self.project_root,
capture_output=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
)
# 获取提交的其他信息
log_result = subprocess.run(
['git', 'log', '-1', '--format=%H|%ai|%an|%ae|%P',
commit_hash],
cwd=self.project_root,
The code deliberately extracts contributor email addresses, full commit messages, parent relationships, and later full file diffs, then returns them to the caller without any minimization or warning. In a context-guide skill, this broad exposure increases the chance of leaking personal data, secrets embedded in history, or sensitive code changes to downstream consumers or logs.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"""获取文件在特定提交中的变更"""
try:
# 获取变更统计
stat_result = subprocess.run(
['git', 'show', '--stat', '--format=', commit_hash, '--',
file_path],
cwd=self.project_root,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
)
# 获取实际的 diff
diff_result = subprocess.run(
['git', 'show', commit_hash, '--', file_path],
cwd=self.project_root,
capture_output=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
start_line = max(1, line_number - context)
end_line = line_number + context
result = subprocess.run(
['git', 'blame', '-L', f'{start_line},{end_line}',
'--line-porcelain', file_path],
cwd=self.project_root,
Persisting the generated JSON to an arbitrary path compounds the repository data exposure risk because sensitive history and metadata can be stored on disk outside expected controls. This is especially risky here because the result structure can contain emails, commit messages, and diffs, and the user is not clearly warned about local persistence.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"""分析文件的所有权"""
try:
# 使用 git blame 分析每行的归属
blame_result = subprocess.run(
['git', 'blame', '--line-porcelain', file_path],
cwd=self.project_root,
capture_output=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _get_author_last_active(self, file_path: str) -> Dict[str, str]:
"""获取作者最后活跃时间"""
try:
result = subprocess.run(
['git', 'log', '--format=%an|%ai', '--', file_path],
cwd=self.project_root,
capture_output=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
try:
since_date = datetime.now().strftime(f'%Y-%m-%d')
result = subprocess.run(
['git', 'log', f'--since={since_date}', '--format=%an|%ai|%s',
'--', file_path],
cwd=self.project_root,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def _get_active_hours(self, file_path: str) -> List[int]:
"""获取活跃时间段(小时)"""
try:
result = subprocess.run(
['git', 'log', '--format=%ai', '--', file_path],
cwd=self.project_root,
capture_output=True,
No suspicious patterns detected.